diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/.gitignore b/sdk/ESP-IDF/esp_fastbee_aliyun/.gitignore
new file mode 100644
index 00000000..636bdedf
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/.gitignore
@@ -0,0 +1,2 @@
+build/
+.idea
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/c_cpp_properties.json b/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/c_cpp_properties.json
new file mode 100644
index 00000000..fddb9c2e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/c_cpp_properties.json
@@ -0,0 +1,23 @@
+{
+ "configurations": [
+ {
+ "name": "Win32",
+ "includePath": [
+ "${workspaceFolder}/**",
+ "D:/soft/esp-idf/Espressif/frameworks/esp-idf-v4.4.7/components/**",
+ "./esp-aliyun/**",
+ ],
+ "defines": [
+ "_DEBUG",
+ "UNICODE",
+ "_UNICODE"
+ ],
+ "windowsSdkVersion": "10.0.22621.0",
+ "compilerPath": "cl.exe",
+ "cStandard": "c17",
+ "cppStandard": "c++17",
+ "intelliSenseMode": "windows-msvc-x64"
+ }
+ ],
+ "version": 4
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/launch.json b/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/launch.json
new file mode 100644
index 00000000..eb835b10
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/launch.json
@@ -0,0 +1,35 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "ESP-IDF Debug: Launch",
+ "type": "espidf",
+ "request": "launch"
+ },
+ {
+ "name": "GDB",
+ "type": "cppdbg",
+ "request": "launch",
+ "MIMode": "gdb",
+ "miDebuggerPath": "${command:espIdf.getXtensaGdb}",
+ "program": "${workspaceFolder}/build/${command:espIdf.getProjectName}.elf",
+ "windows": {
+ "program": "${workspaceFolder}\\build\\${command:espIdf.getProjectName}.elf"
+ },
+ "cwd": "${workspaceFolder}",
+ "environment": [{ "name": "PATH", "value": "${config:idf.customExtraPaths}" }],
+ "setupCommands": [
+ { "text": "set remotetimeout 100" },
+ { "text": "target extended-remote :3333" },
+ { "text": "set remote hardware-watchpoint-limit 2"},
+ { "text": "mon reset halt" },
+ { "text": "thb app_main" },
+ { "text": "flushregs" }
+ ],
+ "externalConsole": false,
+ "logging": {
+ "engineLogging": true
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/settings.json b/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/settings.json
new file mode 100644
index 00000000..a3bc1af0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/.vscode/settings.json
@@ -0,0 +1,19 @@
+{
+ "idf.portWin": "COM6",
+ "idf.adapterTargetName": "esp32s3",
+ "idf.openOcdConfigs": [
+ "board/esp32s3-builtin.cfg"
+ ],
+ "idf.flashType": "UART",
+ "files.associations": {
+ "infra_config.h": "c",
+ "cjson.h": "c",
+ "dm_wrapper.h": "c",
+ "infra_defs.h": "c",
+ "freertos.h": "c",
+ "stddef.h": "c",
+ "string.h": "c",
+ "esp_log.h": "c",
+ "mqtt_client.h": "c"
+ }
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/CMakeLists.txt b/sdk/ESP-IDF/esp_fastbee_aliyun/CMakeLists.txt
new file mode 100644
index 00000000..163a6c23
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+# (Automatically converted from project Makefile by convert_to_cmake.py.)
+
+# The following lines of boilerplate have to be in your project's CMakeLists
+# in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+set (EXTRA_COMPONENT_DIRS "./esp-aliyun")
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+
+project(esp_fastbee_aliyun)
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/Makefile b/sdk/ESP-IDF/esp_fastbee_aliyun/Makefile
new file mode 100644
index 00000000..7454f9b7
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/Makefile
@@ -0,0 +1,11 @@
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+PROJECT_NAME := esp_fastbee_aliyun
+
+EXTRA_COMPONENT_DIRS := $(realpath ./esp-aliyun)
+
+SDKCONFIG_DEFAULTS := sdkconfig_$(chip).defaults
+
+include $(IDF_PATH)/make/project.mk
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/README.md b/sdk/ESP-IDF/esp_fastbee_aliyun/README.md
new file mode 100644
index 00000000..492041ad
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/README.md
@@ -0,0 +1,152 @@
+# ESP 设备对接Fastbee物联网云平台指南
+# 目录
+
+- [1.目的](#aim)
+- [2.硬件准备](#hardwareprepare)
+- [3.云平台准备](#fastbeeprepare)
+- [4.环境搭建](#compileprepare)
+- [5.SDK 准备](#sdkprepare)
+- [6.编译&烧写&运行](#makeflash)
+
+
+# 1.目的
+本项目基于esp-aliyun SDK进行修改,介绍 ESP 设备对接Fastbee物联网云平台,阿里云平台的具体流程。
+主要实现的功能:
+- 支持 配网&接入&控制
+- 支持 <云智能> APP 一键配网
+- 支持 <云智能> APP 控制设备
+- 支持 <天猫精灵智能音箱> 控制设备
+- 支持 <天猫精灵智能音箱> 配网并控制设备
+- 支持 LED 控制(开关,颜色等)
+- 支持 OTA 升级
+
+# 2.硬件准备
+- **linux 环境**
+用来编译 & 烧写 & 运行等操作的必须环境。
+> windows 用户可安装虚拟机,在虚拟机中安装 linux。
+
+- **ESP 设备**
+ESP 设备包括 [ESP芯片](https://www.espressif.com/zh-hans/products/hardware/socs),[ESP模组](https://www.espressif.com/zh-hans/products/hardware/modules),[ESP开发板](https://www.espressif.com/zh-hans/products/hardware/development-boards)等。
+
+- **USB 线**
+连接 PC 和 ESP 设备,用来烧写/下载程序,查看 log 等。
+
+# 3.云平台准备
+
+# 4.环境搭建
+**如果您熟悉 ESP 开发环境,可以很顺利理解下面步骤; 如果您不熟悉某个部分,比如编译,烧录,需要您结合官方的相关文档来理解。如您需阅读 [ESP-IDF 编程指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/index.html)文档等。**
+
+## 4.1 编译器环境搭建
+- ESP8266 平台: 根据[官方链接](https://github.com/espressif/ESP8266_RTOS_SDK)中 **Get toolchain**,获取 toolchain
+- ESP32 & ESP32S2 平台:根据[官方链接](https://github.com/espressif/esp-idf/blob/master/docs/zh_CN/get-started/linux-setup.rst)中 **工具链的设置**,下载 toolchain
+
+toolchain 设置参考 [ESP-IDF 编程指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/get-started/index.html#get-started-setup-toolchain)。
+## 4.2 烧录工具/下载工具获取
+- ESP8266 平台:烧录工具位于 [ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK) 下 `./components/esptool_py/esptool/esptool.py`
+- ESP32 & ESP32S2 平台:烧录工具位于 [esp-idf](https://github.com/espressif/esp-idf) 下 `./components/esptool_py/esptool/esptool.py`
+
+esptool 功能参考:
+
+```
+$ ./components/esptool_py/esptool/esptool.py --help
+```
+
+# 5.SDK 准备
+- [esp-aliyun SDK](https://github.com/espressif/esp-aliyun), 通过该 SDK 可实现使用 MQTT 协议,连接 ESP 设备到阿里云。
+- Espressif SDK
+ - ESP32 & ESP32S2 平台: [ESP-IDF](https://github.com/espressif/esp-idf)
+ - ESP8266 平台: [ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK)
+
+> Espressif SDK 下载好后:
+> ESP-IDF: 请切换到 v4.2 分支: `git checkout v4.2`
+如果需要使用 ESP32S2 模组,请切换到 v4.2 版本: `git checkout v4.2`
+> ESP8266_RTOS_SDK: 请切换到 v3.3 分支: `git checkout v3.3`
+
+# 6.编译 & 烧写 & 运行
+## 6.1 编译
+
+### 6.1.1 导出编译器
+参考 [工具链的设置](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/get-started/linux-setup.html)
+
+### 6.1.2 编译 demo 示例
+**由于 esp32 和 esp8266 将会采用不同的 sdkconfig.defaults 和对应的 partitions.csv,在对应的 make 命令中加入了对应的芯片选项,如 chip=esp32 或 chip=esp8266。**
+
+当 chip=esp32 时将默认使用 sdkconfig_esp32.defaults 以及 partitions_esp32.csv。
+
+当 chip=esp8266 时将默认使用 sdkconfig_esp8266.defaults 以及 partitions_esp8266.csv。
+
+当使用 esp32s2 时,将默认使用 sdkconfig.defaults ,sdkconfig.defaults.esp32s2 以及 partitions_esp32s2.csv,编译方式与 8266 & 32 都不一样,需要使用 cmake 进行编译。
+
+以上需要特别注意。
+
+在 esp-aliyun 目录下执行:
+
+```
+cd fastbee\sdk\ESP-IDF\esp-aliyun
+make chip=esp32 defconfig
+make menuconfig
+```
+
+如果需要编译esp32s2版本, 请按照如下步骤编译:
+
+在 esp-aliyun 目录下执行:
+
+```
+cd fastbee\sdk\ESP-IDF\esp-aliyun
+idf.py set-target esp32s2
+idf.py menuconfig
+```
+
+- 配置烧写串口
+- 配置 `WIFI_SSID`, `WIFI_PASSWORD`
+
+如果需要编译esp32s3版本, 请按照如下步骤编译:
+
+在 esp-aliyun 目录下执行:
+
+```
+cd fastbee\sdk\ESP-IDF\esp-aliyun
+idf.py set-target esp32s3
+idf.py menuconfig
+```
+
+2.生成最终 bin
+
+```
+make -j8
+```
+使用 esp32s2/esp32s3 生成 bin
+
+```
+idf.py build
+```
+
+## 6.2 擦除 & 编译烧写 & 下载固件 & 查看 log
+将 USB 线连接好 ESP 设备和 PC,确保烧写端口正确。
+
+### 6.2.1[可选] 擦除 flash
+```
+make erase_flash
+```
+> 注:无需每次擦除,擦除后需要重做 6.2.3。
+
+### 6.2.2 烧录程序
+```
+make flash
+```
+
+使用 esp32s2/esp32s3 擦除 flash
+```
+idf.py -p (PORT) erase_flash
+```
+
+### 6.2.3 烧录三元组信息
+参考 [量产说明](./aliyunsdk/config/mass_mfg/README.md) 文档烧录三元组 NVS 分区。
+
+## 6.2.4 运行
+
+```
+make monitor
+```
+
+> 也可执行 `make flash monitor` 来编译烧写和查看 log。
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/README_examples.md b/sdk/ESP-IDF/esp_fastbee_aliyun/README_examples.md
new file mode 100644
index 00000000..aeceab57
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/README_examples.md
@@ -0,0 +1,127 @@
+# Smart Light 解决方案
+
+### 解决方案部署
+#### 1.参考 [README](./README.md) 文档进行硬件准备、环境搭建、SDK 准备
+
+#### 2.阿里云平台部署
+在阿里云 [生活物联网平台](https://living.aliyun.com/#/) 创建产品, 参考[创建产品文档](https://living.aliyun.com/doc#readygo.html).
+> 配置较多, 如果不太懂, 也不用纠结, 后续都可以修改.
+
+部署自己的产品, 可参考如下:
+新增 RGB 调色功能:
+
+
+新增测试设备, 此处即可以获得`三元组`, 后续需要烧录到 NVS 分区.
+
+
+
+选择面板, 手机 APP 上会显示同样界面; `配网二维码`是贴在产品包装上, 终端客户给设备配网中需扫描此二维码.
+
+
+选择面板时, 主题面板在手机上仅能显示标准界面, 没有 RGB 调色功能. 可以自定义面板, 增加 RGB 调色.
+
+
+
+
+配网方案选择:
+
+
+完成
+
+
+#### 3.下载本工程
+ ```
+ git clone https://github.com/espressif/esp-aliyun.git
+ cd esp-aliyun
+ ```
+
+#### 4.烧录三元组信息
+- 参考 [量产说明](../../../config/mass_mfg/README.md) 文档烧录三元组 NVS 分区.
+
+> 如果执行了 `make erase_flash`, 需要重新烧录三元组.
+
+#### 5.配置 `smart light example`
+- RGB 灯分别接 ESP32/ESP8266 开发板上 `GPIO0`, `GPIO2`, `GPIO4` (可在 `lightbulb.c` 中修改)
+
+#### 6.编译 `smart light` 并烧录运行
+```
+cd examples/solutions/smart_light
+make chip=esp32 defconfig 或者 make chip=esp8266 defconfig
+make -j8 flash monitor
+```
+使用 esp32s2 请参考根目录 README。
+
+> 在测试配网中, 请先执行 `make erase_flash` .
+
+#### 7.设备第一次运行时, 会进入配网
+
+
+
+#### 8.手机从[阿里云官网](https://living.aliyun.com/doc#muti-app.html) 下载 `云智能` 公版 APP, 国内用户版.
+
+#### 9.注册好账号后,进入 APP, 右上角扫描, 扫描第二步的二维码配网.
+设备端配网成功后会保存 `ssid` 和 `password` :
+
+
+设备与手机绑定成功后, APP 上会弹出灯的配置页面. 返回主页显示灯 `在线`.
+
+
+
+#### 10.控制智能灯
+
+在 APP 上打开灯, 设备端收到消息:
+
+
+在 APP 上设置 RGB 调色:
+
+
+设备端即解析 RGB 颜色, 并设置到具体的灯产品上.
+
+
+#### 11.重新配网
+快速重启设备 5 次, 设备会擦除配置信息, 重新进入配网状态.
+
+可以配置快速重启的次数和超时时间.
+```
+cd examples/solutions/smart_light
+make menuconfig
+```
+
+
+
+#### 12.OTA 支持
+参考 examples/ota/ota_example_mqtt 示例下的 [README](../../ota/ota_example_mqtt/README.md) , 向管理控制台上传固件, 验证固件后, 下发升级指令.
+设备端收到升级指令后, 即开始 OTA:
+
+
+升级完成后, 会检查固件的有效性, 下图说明固件有效.
+
+
+iotkit-embedded 目前没有设置软重启操作, 可以手动按模组重启键运行新固件:
+
+
+#### 13.天猫精灵
+##### 13.1 天猫精灵控制设备
+针对使用公版 APP 的产品,用户可以一键开通天猫精灵,实现天猫精灵音箱对设备的控制. 使用步骤参照[阿里云文档](https://living.aliyun.com/doc#TmallGenie.html).
+- 在阿里云 [生活物联网平台](https://living.aliyun.com/#/)上一键开通天猫精灵, 查看功能映射.
+- 在 `云智能` [公版 APP]((https://living.aliyun.com/doc#muti-app.html))上绑定天猫精灵账号(即淘宝账号).
+
+注意最后步骤, 否则天猫精灵无法找到设备:
+> 在天猫精灵 APP 找到 "阿里智能" 技能, 手动进行 "尝试" 或 "设备同步"(后期会进行自动同步)
+> 即可在 "我家" 的设备列表中看到您的设备
+
+完成以上步骤后,您可以通过天猫精灵音箱控制您的设备了. 您可以对天猫精灵说 "天猫精灵,开灯", "天猫精灵, 关灯", "天猫精灵, 把灯调成红色" 或者其他您希望设置的颜色, 设备即响应相应的命令.
+
+##### 13.2 天猫精灵配网并控制设备
+阿里云设备支持 `零配` 的配网方式.
+使设备进入配网状态, 对天猫精灵说 "天猫精灵,发现设备"
+天猫精灵回复 "正在为您扫描, 发现了智能灯, 现在连接吗"
+对天猫精灵说 "连接" 或者 "是的"
+天猫精灵回复 "好的, 设备连接中, 稍等一下下哦"
+设备收到天猫精灵发送的管理帧配网信息, 进行联网:
+
+
+等待联网成功, 天猫精灵说 "智能设备联网成功, 现在用语音控制它试试", 这时您可以通过天猫精灵音箱控制您的设备了.
+
+如果您之前通过云智能 APP 配网, 天猫精灵配网成功后, 云智能 APP 将不再显示设备. 如果继续通过云智能 APP 配网, APP 会配网失败, 显示 "设备添加失败, 设备已被管理员绑定, 请联系管理员解绑或将设备分享给您".
+> 在天猫精灵 APP 删除设备, 云智能 APP 再进行配网可以配置成功并显示设备.
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-redirect.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-redirect.png
new file mode 100644
index 00000000..f4e5db53
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-redirect.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-se.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-se.png
new file mode 100644
index 00000000..dbce5aa1
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-se.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-sub.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-sub.png
new file mode 100644
index 00000000..a84a4158
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-sub.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-us.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-us.png
new file mode 100644
index 00000000..5fcf7075
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p-us.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p1.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p1.png
new file mode 100644
index 00000000..a2a2b36f
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p1.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p10.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p10.png
new file mode 100644
index 00000000..7c538988
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p10.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p11.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p11.png
new file mode 100644
index 00000000..ab8a48c3
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p11.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p12.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p12.png
new file mode 100644
index 00000000..ca802ae3
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p12.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p13.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p13.png
new file mode 100644
index 00000000..538ebfcc
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p13.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p14.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p14.png
new file mode 100644
index 00000000..a0fbe21f
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p14.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p15.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p15.png
new file mode 100644
index 00000000..1803e23a
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p15.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p16.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p16.png
new file mode 100644
index 00000000..70842f54
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p16.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p17.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p17.png
new file mode 100644
index 00000000..b0ab72dd
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p17.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p18.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p18.png
new file mode 100644
index 00000000..3086b3d4
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p18.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p19.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p19.png
new file mode 100644
index 00000000..798e3064
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p19.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p2.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p2.png
new file mode 100644
index 00000000..80dcc095
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p2.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p20.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p20.png
new file mode 100644
index 00000000..f542d286
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p20.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p21.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p21.png
new file mode 100644
index 00000000..7bceee55
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p21.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p22.jpg b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p22.jpg
new file mode 100644
index 00000000..076fb035
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p22.jpg differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p23.jpg b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p23.jpg
new file mode 100644
index 00000000..3d6e577c
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p23.jpg differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p24.jpg b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p24.jpg
new file mode 100644
index 00000000..51c7ccbf
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p24.jpg differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p3.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p3.png
new file mode 100644
index 00000000..d036d4a6
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p3.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p4.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p4.png
new file mode 100644
index 00000000..c5c8212b
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p4.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p5.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p5.png
new file mode 100644
index 00000000..371e345e
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p5.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p6.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p6.png
new file mode 100644
index 00000000..06f135e4
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p6.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p7.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p7.png
new file mode 100644
index 00000000..e716b2b2
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p7.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p8.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p8.png
new file mode 100644
index 00000000..46705e9b
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p8.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p9.png b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p9.png
new file mode 100644
index 00000000..d93f2312
Binary files /dev/null and b/sdk/ESP-IDF/esp_fastbee_aliyun/_static/p9.png differ
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/CMakeLists.txt b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/CMakeLists.txt
new file mode 100644
index 00000000..415fe200
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(COMPONENT_ADD_INCLUDEDIRS .)
+
+set(COMPONENT_SRCS "factory_restore.c")
+
+set(COMPONENT_REQUIRES "esp-aliyun")
+
+register_component()
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/Kconfig.projbuild b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/Kconfig.projbuild
new file mode 100644
index 00000000..1a456afe
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/Kconfig.projbuild
@@ -0,0 +1,15 @@
+menu "[Aliyun]Factory restore"
+
+ config FACTORY_QUICK_REBOOT_TIMEOUT
+ int "Quick reboot timeout, unit second"
+ default 6
+ help
+ Timeout for exiting quick reboot timer, users should reboot device before this timeout.
+
+ config FACTORY_QUICK_REBOOT_MAX_TIMES
+ int "Quick reboot times max record"
+ default 5
+ help
+ If quick reboot times reach this max value, device will do factory restore.
+
+endmenu
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/component.mk b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/component.mk
new file mode 100644
index 00000000..a82220a1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/component.mk
@@ -0,0 +1,2 @@
+COMPONENT_ADD_INCLUDEDIRS := ./
+COMPONENT_SRCDIRS := ./
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/factory_restore.c b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/factory_restore.c
new file mode 100644
index 00000000..78b7dcfb
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/factory_restore.c
@@ -0,0 +1,103 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2019
+ *
+ * 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
+#include
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/timers.h"
+#include "esp_sleep.h"
+#include "dm_wrapper.h"
+#include "conn_mgr.h"
+
+#define FACTORY_QUICK_REBOOT_TIMEOUT (CONFIG_FACTORY_QUICK_REBOOT_TIMEOUT * 1000)
+#define FACTORY_QUICK_REBOOT_MAX_TIMES CONFIG_FACTORY_QUICK_REBOOT_MAX_TIMES
+#define FACTORY_QUICK_REBOOT_TIMES "q_rt"
+
+#define AWSS_KV_RST "awss.rst"
+
+static const char *TAG = "factory_rst";
+
+static esp_err_t factory_restore_handle(void)
+{
+ esp_err_t ret = ESP_OK;
+ int quick_reboot_times = 0;
+
+ /**< If the device restarts within the instruction time, the event_mdoe value will be incremented by one */
+ int length = sizeof(int);
+ ret = HAL_Kv_Get(FACTORY_QUICK_REBOOT_TIMES, &quick_reboot_times, &length);
+
+ quick_reboot_times++;
+
+ ret = HAL_Kv_Set(FACTORY_QUICK_REBOOT_TIMES, &quick_reboot_times, sizeof(int), 0);
+
+ if (quick_reboot_times >= FACTORY_QUICK_REBOOT_MAX_TIMES) {
+ char rst = 0x01;
+
+ /* since we cannot report reset status to cloud in this stage, just set the reset flag.
+ when connects to cloud, awss will do the reset report. */
+ ret = HAL_Kv_Set(AWSS_KV_RST, &rst, sizeof(rst), 0);
+ ret = HAL_Kv_Del(FACTORY_QUICK_REBOOT_TIMES);
+
+ ESP_LOGW(TAG, "factory restore");
+ conn_mgr_reset_wifi_config();
+ } else {
+ ESP_LOGI(TAG, "quick reboot times %d, don't need to restore", quick_reboot_times);
+ }
+
+ return ret;
+}
+
+static void factory_restore_timer_handler(void *timer)
+{
+ if (!xTimerStop(timer, 0)) {
+ ESP_LOGE(TAG, "xTimerStop timer %p", timer);
+ }
+
+ if (!xTimerDelete(timer, 0)) {
+ ESP_LOGE(TAG, "xTimerDelete timer %p", timer);
+ }
+
+ /* erase reboot times record */
+ HAL_Kv_Del(FACTORY_QUICK_REBOOT_TIMES);
+
+ ESP_LOGI(TAG, "Quick reboot timeout, clear reboot times");
+}
+
+esp_err_t factory_restore_init(void)
+{
+#ifndef CONFIG_IDF_TARGET_ESP8266
+ if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED) {
+ HAL_Kv_Del(FACTORY_QUICK_REBOOT_TIMES);
+ return ESP_OK;
+ }
+#endif
+
+ TimerHandle_t timer = xTimerCreate("factory_clear", FACTORY_QUICK_REBOOT_TIMEOUT / portTICK_RATE_MS,
+ false, NULL, factory_restore_timer_handler);
+
+ xTimerStart(timer, portMAX_DELAY);
+
+ return factory_restore_handle();
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/factory_restore.h b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/factory_restore.h
new file mode 100644
index 00000000..bde37521
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/factory_restore/factory_restore.h
@@ -0,0 +1,50 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2018
+ *
+ * Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, 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"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize factory restore
+ *
+ * @note For some devices which don't have a physical restore key or button, such as light, we use
+ * a quick reboot method to record the reboot times, if users quickly reboot the device within
+ * a specific time, configured by FACTORY_QUICK_REBOOT_TIMEOUT, and reboot several times,
+ * configured by FACTORY_QUICK_REBOOT_MAX_TIMES, the device will do a factory restore, clear
+ * stored ssid and password.
+ *
+ * @return
+ * - ESP_OK : OK
+ * - others : fail
+ */
+esp_err_t factory_restore_init(void);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/CMakeLists.txt b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/CMakeLists.txt
new file mode 100644
index 00000000..9a944f71
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(COMPONENT_ADD_INCLUDEDIRS "./include")
+
+set(COMPONENT_SRCS "fastbee.c" "Config.c" "Mqtt.c")
+
+set(COMPONENT_REQUIRES "esp-aliyun" "mqtt" "json")
+
+register_component()
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/Config.c b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/Config.c
new file mode 100644
index 00000000..d847beed
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/Config.c
@@ -0,0 +1,174 @@
+/*********************************************************************
+ * function: 设备交互
+ * board: esp8266,esp32,esp32s2,esp32s3 core for esp-idf v4.4.7
+ * source: https://gitee.com/zhuangpengli/IOTDeviceSDK
+ * copyright: zhuangpeng.li all rights reserved.
+ ********************************************************************/
+#include "Config.h"
+#include "esp_err.h"
+#include "esp_log.h"
+
+#include "nvs_flash.h"
+#include "nvs.h"
+#include "dm_wrapper.h"
+
+// 设备信息配置
+char g_userId[USER_ID_LEN + 1] = {0};
+char g_productId[PRODUCT_ID_LEN + 1] = {0};
+char g_deviceSN[DEVICE_SN_LEN + 1] = {0};
+
+// Mqtt配置
+char g_mqtt_url[MQTT_URL_LEN + 1] = {0};
+char g_mqtt_username[MQTT_USERNAME_LEN + 1] = {0};
+char g_mqtt_password[MQTT_PASSWORD_LEN + 1] = {0};
+char g_mqtt_clientid[MQTT_CLIENTID_LEN + 1] = {0};
+char g_mqtt_prefix[MQTT_PREFIX_LEN + 1] = {0};
+
+float rssi = 0;
+char wumei_iv[17] = "wumei-smart-open";
+int monitorCount = 0;
+long monitorInterval = 1000;
+bool isApMode = false;
+/********************************** begin 可配置的项 **********************************/
+// wifi信息
+char *wifiSsid = "";
+char *wifiPwd = "";
+// 产品启用授权码,则授权码不能为空
+char *authCode = "";
+// 设备信息配置
+float firmwareVersion = 1.0;
+// 经度和纬度可选,如果产品使用设备定位,则必须传
+float latitude = 0;
+float longitude = 0;
+// Mqtt配置
+char mqttSecret[17] = "KV52PPZ813EFCQD8";
+// NTP地址(用于获取时间,修改为自己部署项目的接口地址)
+char *ntpServer = "http://fastbee.cn:8080/iot/tool/ntp?deviceSendTime=";
+/********************************** end 可配置的项 **********************************/
+
+static const char *TAG = "FASTBEE_CONFIG";
+static bool s_part_init_flag;
+
+static esp_err_t HAL_ProductParam_init(void)
+{
+ esp_err_t ret = ESP_OK;
+
+ do {
+ if (s_part_init_flag == false) {
+ if ((ret = nvs_flash_init_partition(MFG_FASTBEE_PARTITION_NAME)) != ESP_OK) {
+ ESP_LOGE(TAG, "NVS Flash init %s failed, Please check that you have flashed fctry partition!!!", MFG_FASTBEE_PARTITION_NAME);
+ break;
+ }
+
+ s_part_init_flag = true;
+ }
+ } while (0);
+
+ return ret;
+}
+
+static int HAL_GetProductParam(char *param_name, const char *param_name_str)
+{
+ esp_err_t ret;
+ size_t read_len = 0;
+ nvs_handle handle;
+
+ do {
+ if (HAL_ProductParam_init() != ESP_OK) {
+ break;
+ }
+
+ if (param_name == NULL) {
+ ESP_LOGE(TAG, "%s param %s NULL", __func__, param_name);
+ break;
+ }
+
+ ret = nvs_open_from_partition(MFG_FASTBEE_PARTITION_NAME, NVS_FASTBEE_PRODUCT, NVS_READONLY, &handle);
+
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "%s nvs_open failed with %x", __func__, ret);
+ break;
+ }
+
+ ret = nvs_get_str(handle, param_name_str, NULL, (size_t *)&read_len);
+
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "%s nvs_get_str get %s failed with %x", __func__, param_name_str, ret);
+ break;
+ }
+
+ ret = nvs_get_str(handle, param_name_str, param_name, (size_t *)&read_len);
+
+ if (ret != ESP_OK) {
+ ESP_LOGE(TAG, "%s nvs_get_str get %s failed with %x", __func__, param_name_str, ret);
+ } else {
+ ESP_LOGV(TAG, "%s %s %s", __func__, param_name_str, param_name);
+ }
+
+ nvs_close(handle);
+ } while (0);
+
+ return read_len;
+}
+
+int HAL_GetMqttUrl(char mqtt_url[MQTT_URL_LEN + 1])
+{
+ return HAL_GetProductParam(mqtt_url, "MQTTUrl");
+}
+int HAL_GetMqttUsername(char mqtt_username[MQTT_USERNAME_LEN + 1])
+{
+ return HAL_GetProductParam(mqtt_username, "MQTTUsername");
+}
+int HAL_GetMqttPassword(char mqtt_password[MQTT_PASSWORD_LEN + 1])
+{
+ return HAL_GetProductParam(mqtt_password, "MQTTPassword");
+}
+int HAL_GetMqttClientId(char mqtt_clientid[MQTT_CLIENTID_LEN + 1])
+{
+ return HAL_GetProductParam(mqtt_clientid, "MQTTClientId");
+}
+int HAL_GetUserId(char userid[USER_ID_LEN + 1])
+{
+ return HAL_GetProductParam(userid, "UserId");
+}
+int HAL_GetDeviceSN(char deviceSN[DEVICE_SN_LEN + 1])
+{
+ return HAL_GetProductParam(deviceSN, "DeviceSN");
+}
+int HAL_GetProductId(char productId[PRODUCT_ID_LEN + 1])
+{
+ return HAL_GetProductParam(productId, "ProductId");
+}
+
+void loadConfig() {
+ HAL_GetMqttUrl(g_mqtt_url);
+ if (strlen(g_mqtt_url) == 0) {
+ //加载默认配置
+ memcpy(g_mqtt_url, CONFIG_ESP_MQTT_PLATFORM_FASTBEE_URL, strlen(CONFIG_ESP_MQTT_PLATFORM_FASTBEE_URL));
+ }
+ HAL_GetMqttUsername(g_mqtt_username);
+ if (strlen(g_mqtt_username) == 0) {
+ memcpy(g_mqtt_username, CONFIG_ESP_MQTT_PLATFORM_FASTBEE_USERNAME, strlen(CONFIG_ESP_MQTT_PLATFORM_FASTBEE_USERNAME));
+ }
+ HAL_GetMqttPassword(g_mqtt_password);
+ if (strlen(g_mqtt_password) == 0) {
+ memcpy(g_mqtt_password, CONFIG_ESP_MQTT_PLATFORM_FASTBEE_PASSWORD, strlen(CONFIG_ESP_MQTT_PLATFORM_FASTBEE_PASSWORD));
+ }
+ HAL_GetMqttClientId(g_mqtt_clientid);
+ if (strlen(g_mqtt_clientid) == 0) {
+ HAL_Snprintf(g_mqtt_clientid, sizeof(g_mqtt_clientid), "S&%s&%s&%s", CONFIG_ESP_MQTT_PLATFORM_FASTBEE_DEVICESN,CONFIG_ESP_MQTT_PLATFORM_FASTBEE_PRODICTID,CONFIG_ESP_MQTT_PLATFORM_FASTBEE_USERID);
+ }
+ HAL_GetUserId(g_userId);
+ if (strlen(g_userId) == 0) {
+ memcpy(g_userId, CONFIG_ESP_MQTT_PLATFORM_FASTBEE_USERID, strlen(CONFIG_ESP_MQTT_PLATFORM_FASTBEE_USERID));
+ }
+ HAL_GetDeviceSN(g_productId);
+ if (strlen(g_productId) == 0) {
+ memcpy(g_productId, CONFIG_ESP_MQTT_PLATFORM_FASTBEE_PRODICTID, strlen(CONFIG_ESP_MQTT_PLATFORM_FASTBEE_PRODICTID));
+ }
+ HAL_GetProductId(g_deviceSN);
+ if (strlen(g_deviceSN) == 0) {
+ memcpy(g_deviceSN, CONFIG_ESP_MQTT_PLATFORM_FASTBEE_DEVICESN, strlen(CONFIG_ESP_MQTT_PLATFORM_FASTBEE_DEVICESN));
+ }
+ HAL_Snprintf(g_mqtt_prefix, sizeof(g_mqtt_prefix), "/%s/%s", g_productId,g_deviceSN);
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/Mqtt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/Mqtt.c
new file mode 100644
index 00000000..8c8fedc0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/Mqtt.c
@@ -0,0 +1,158 @@
+/*********************************************************************
+ * function: 设备交互
+ * board: esp8266,esp32,esp32s2,esp32s3 core for esp-idf v4.4.7
+ * source: https://gitee.com/zhuangpengli/IOTDeviceSDK
+ * copyright: zhuangpeng.li all rights reserved.
+ ********************************************************************/
+#include "Mqtt.h"
+#include "Config.h"
+#include "cJSON.h"
+#include "esp_log.h"
+#include "dm_wrapper.h"
+
+char *sInfoTopic = "/info/get";
+char *sOtaTopic = "/ota/get";
+char *sNtpTopic = "/ntp/get";
+char *sPropertyTopic = "/property/get";
+char *sFunctionTopic = "/function/get";
+char *sPropertyOnline = "/property-online/get";
+char *sFunctionOnline = "/function-online/get";
+char *sMonitorTopic = "/monitor/get";
+// Mqtt发布的主题
+char *pInfoTopic = "/info/post";
+char *pNtpTopic = "/ntp/post";
+char *pPropertyTopic = "/property/post";
+char *pFunctionTopic = "/function/post";
+char *pMonitorTopic = "/monitor/post";
+char *pEventTopic = "/event/post";
+
+static const char *TAG = "FASTBEE_MQTT";
+// 订阅系统主题
+void subscribeTopic(esp_mqtt_client_handle_t client) {
+ char topic[128] = {0};
+ int msg_id;
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sInfoTopic);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sOtaTopic);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sNtpTopic);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sPropertyTopic);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sFunctionTopic);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sPropertyOnline);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sFunctionOnline);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+
+ memset(topic, 0, sizeof(topic));
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, sMonitorTopic);
+ msg_id = esp_mqtt_client_subscribe(client, topic, 0);
+ ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
+}
+
+// 1.发布设备信息
+void publishInfo(esp_mqtt_client_handle_t client) {
+ char topic[128] = {0};
+ int msg_id;
+ cJSON *json = cJSON_CreateObject();
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, pInfoTopic);
+ // 向JSON对象中添加数据
+ cJSON_AddNumberToObject(json, "rssi", 3);
+ cJSON_AddNumberToObject(json, "firmwareVersion", firmwareVersion);
+ cJSON_AddNumberToObject(json, "status", 3);
+ cJSON_AddStringToObject(json, "userId", g_userId);
+ cJSON_AddNumberToObject(json, "longitude", longitude);
+ cJSON_AddNumberToObject(json, "latitude", latitude);
+
+ cJSON *summary = cJSON_CreateObject();
+ cJSON_AddStringToObject(summary, "name", "fastbee");
+ cJSON_AddStringToObject(summary, "chip", "esp32");
+ cJSON_AddStringToObject(summary, "author", "zhuangpeng.li");
+ cJSON_AddNumberToObject(summary, "version", 1.6);
+ cJSON_AddStringToObject(summary, "create", "2024-07-07");
+
+ cJSON_AddItemToObject(json, "summary", summary);
+ char *json_string = cJSON_Print(json);
+ msg_id = esp_mqtt_client_publish(client, topic, json_string, 0, 0, 0);
+ ESP_LOGI(TAG, "sent publish %s, msg_id= %d, msg: %s", topic, msg_id, json_string);
+
+ cJSON_Delete(json);
+ free(json_string);
+}
+
+// 2.发布时钟同步信,用于获取当前时间(可选)
+void publishNtp(esp_mqtt_client_handle_t client) {
+ char topic[128] = {0};
+ int msg_id;
+ cJSON *json = cJSON_CreateObject();
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, pNtpTopic);
+ cJSON_AddStringToObject(json, "deviceSendTime", "test");
+ char *json_string = cJSON_Print(json);
+ msg_id = esp_mqtt_client_publish(client, topic, json_string, 0, 0, 0);
+ ESP_LOGI(TAG, "sent publish %s, msg_id= %d, msg: %s", topic, msg_id, json_string);
+
+ cJSON_Delete(json);
+ free(json_string);
+}
+
+// 3.发布属性
+void publishProperty(esp_mqtt_client_handle_t client, const char *msg) {
+ char topic[128] = {0};
+ int msg_id;
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, pPropertyTopic);
+ msg_id = esp_mqtt_client_publish(client, topic, msg, 0, 0, 0);
+ ESP_LOGI(TAG, "发布属性主题: %s", topic);
+ ESP_LOGI(TAG, "消息id= %d, 消息: %s", msg_id, msg);
+}
+
+// 4.发布功能
+void publishFunction(esp_mqtt_client_handle_t client, const char *msg) {
+ char topic[128] = {0};
+ int msg_id;
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, pFunctionTopic);
+ msg_id = esp_mqtt_client_publish(client, topic, msg, 0, 0, 0);
+ ESP_LOGI(TAG, "发布功能主题: %s", topic);
+ ESP_LOGI(TAG, "消息id= %d, 消息: %s", msg_id, msg);
+}
+
+// 5.发布事件
+void publishEvent(esp_mqtt_client_handle_t client, const char *msg) {
+ char topic[128] = {0};
+ int msg_id;
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, pEventTopic);
+ msg_id = esp_mqtt_client_publish(client, topic, msg, 0, 0, 0);
+ ESP_LOGI(TAG, "发布事件主题: %s", topic);
+ ESP_LOGI(TAG, "消息id= %d, 消息: %s", msg_id, msg);
+}
+
+// 6.发布实时监测数据
+void publishMonitor(esp_mqtt_client_handle_t client, const char *msg) {
+ char topic[128] = {0};
+ int msg_id;
+ HAL_Snprintf(topic, sizeof(topic), "%s%s", g_mqtt_prefix, pMonitorTopic);
+ // 发布实时监测数据(不会存储,需要实时存储则发布为属性)
+ msg_id = esp_mqtt_client_publish(client, topic, msg, 0, 0, 0);
+ ESP_LOGI(TAG, "发布实时监测主题: %s", topic);
+ ESP_LOGI(TAG, "消息id= %d, 消息: %s", msg_id, msg);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/component.mk b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/component.mk
new file mode 100644
index 00000000..da8d8132
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/component.mk
@@ -0,0 +1,2 @@
+COMPONENT_ADD_INCLUDEDIRS := ./include
+COMPONENT_SRCDIRS := ./
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/multipule_mfg_config.csv b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/multipule_mfg_config.csv
new file mode 100644
index 00000000..399f4a45
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/multipule_mfg_config.csv
@@ -0,0 +1,8 @@
+fastbee-key,namespace,
+MQTTUrl,data,string
+MQTTUsername,data,string
+MQTTPassword,data,string
+MQTTClientId,data,string
+UserId,data,string
+DeviceSN,data,string
+ProductId,data,string
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/multipule_mfg_values.csv b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/multipule_mfg_values.csv
new file mode 100644
index 00000000..895cb576
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/multipule_mfg_values.csv
@@ -0,0 +1,4 @@
+id,MQTTUrl,MQTTUsername,MQTTPassword,MQTTClientId,UserId,DeviceSN,ProductId
+1,fastbee.cn:1883,FastBee,P63653937TRQ8F27,S&DCDA0C11FEBC&588&1,1,DCDA0C11FEBC,588
+2,fastbee.cn:1883,FastBee,P63653937TRQ8F27,S&DCDA0C11FEBC&588&1,1,DCDA0C11FEBC,588
+3,fastbee.cn:1883,FastBee,P63653937TRQ8F27,S&DCDA0C11FEBC&588&1,1,DCDA0C11FEBC,588
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/single_mfg_config.csv b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/single_mfg_config.csv
new file mode 100644
index 00000000..033f7eac
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/config/single_mfg_config.csv
@@ -0,0 +1,9 @@
+key,type,encoding,value
+fastbee-key,namespace,,
+MQTTUrl,data,string,fastbee.cn:1883
+MQTTUsername,data,string,FastBee
+MQTTPassword,data,string,P63653937TRQ8F27
+MQTTClientId,data,string,S&DCDA0C11FEBC&588&1
+UserId,data,string,1
+DeviceSN,data,string,DCDA0C11FEBC
+ProductId,data,string,588
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/fastbee.c b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/fastbee.c
new file mode 100644
index 00000000..bd6a370c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/fastbee.c
@@ -0,0 +1,98 @@
+/*********************************************************************
+ * function: 设备交互
+ * board: esp8266,esp32,esp32s2,esp32s3 core for esp-idf v4.4.7
+ * source: https://gitee.com/zhuangpengli/IOTDeviceSDK
+ * copyright: zhuangpeng.li all rights reserved.
+ ********************************************************************/
+#include "fastbee.h"
+#include "config.h"
+#include "mqtt.h"
+
+#include "esp_log.h"
+#include "dm_wrapper.h"
+
+static const char *TAG = "FASTBEE";
+
+static void log_error_if_nonzero(const char *message, int error_code)
+{
+ if (error_code != 0) {
+ ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
+ }
+}
+/*
+ * @brief Event handler registered to receive MQTT events
+ *
+ * This function is called by the MQTT client event loop.
+ *
+ * @param handler_args user data registered to the event.
+ * @param base Event base for the handler(always MQTT Base in this example).
+ * @param event_id The id for the received event.
+ * @param event_data The data for the event, esp_mqtt_event_handle_t.
+ */
+static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
+{
+ ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
+ esp_mqtt_event_handle_t event = event_data;
+ esp_mqtt_client_handle_t client = event->client;
+ int msg_id;
+ switch ((esp_mqtt_event_id_t)event_id) {
+ case MQTT_EVENT_CONNECTED:
+ ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
+ subscribeTopic(client);
+ publishInfo(client);
+ break;
+ case MQTT_EVENT_DISCONNECTED:
+ ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
+ break;
+ case MQTT_EVENT_SUBSCRIBED:
+ ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
+ msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
+ ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
+ break;
+ case MQTT_EVENT_UNSUBSCRIBED:
+ ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
+ break;
+ case MQTT_EVENT_PUBLISHED:
+ ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
+ break;
+ case MQTT_EVENT_DATA:
+ ESP_LOGI(TAG, "MQTT_EVENT_DATA");
+ printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
+ printf("DATA=%.*s\r\n", event->data_len, event->data);
+ break;
+ case MQTT_EVENT_ERROR:
+ ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
+ if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
+ log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
+ log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
+ log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
+ ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
+ }
+ break;
+ default:
+ ESP_LOGI(TAG, "Other event id:%d", event->event_id);
+ break;
+ }
+}
+
+static int fastbee_thread(void *paras){
+ loadConfig();
+ esp_mqtt_client_config_t mqtt_cfg = {
+ .uri = g_mqtt_url,
+ .client_id = g_mqtt_clientid,
+ .username = g_mqtt_username,
+ .password = g_mqtt_password,
+ };
+ esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
+ /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
+ esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
+ esp_mqtt_client_start(client);
+ return 0;
+}
+
+void fastbee_main(void *paras)
+{
+ while (1) {
+ fastbee_thread(NULL);
+ }
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/Config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/Config.h
new file mode 100644
index 00000000..00f7ce55
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/Config.h
@@ -0,0 +1,58 @@
+/*********************************************************************
+ * function: 设备交互
+ * board: esp8266,esp32,esp32s2,esp32s3 core for esp-idf v4.4.7
+ * source: https://gitee.com/zhuangpengli/IOTDeviceSDK
+ * copyright: zhuangpeng.li all rights reserved.
+ ********************************************************************/
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include
+#include
+#include
+
+#define MQTT_URL_LEN (64)
+#define MQTT_USERNAME_LEN (64)
+#define MQTT_PASSWORD_LEN (64)
+#define MQTT_CLIENTID_LEN (64)
+#define USER_ID_LEN (16)
+#define DEVICE_SN_LEN (64)
+#define PRODUCT_ID_LEN (16)
+#define MQTT_PREFIX_LEN (128)
+
+#define MFG_FASTBEE_PARTITION_NAME "fctry"
+#define NVS_FASTBEE_PRODUCT "fastbee-key"
+
+extern char g_userId[USER_ID_LEN + 1]; // 用户ID
+extern char g_productId[PRODUCT_ID_LEN + 1]; // 产品ID
+extern char g_deviceSN[DEVICE_SN_LEN + 1]; // 设备编号(重要,同时是Mqtt的clientId)
+
+// Mqtt配置
+extern char g_mqtt_url[MQTT_URL_LEN + 1];
+extern char g_mqtt_username[MQTT_USERNAME_LEN + 1];
+extern char g_mqtt_password[MQTT_PASSWORD_LEN + 1];
+extern char g_mqtt_clientid[MQTT_CLIENTID_LEN + 1];
+extern char g_mqtt_prefix[MQTT_PREFIX_LEN + 1];
+
+extern float rssi; // 信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])
+extern char wumei_iv[17]; // AES加密偏移量,固定值16位
+extern int monitorCount; // 发布监测数据的最大次数
+extern long monitorInterval; // 发布监测数据的间隔,默认1000毫秒
+extern bool isApMode; // 是否进入AP配网模式
+
+/********************************** begin 可配置的项 **********************************/
+extern char *wifiSsid; // WIFI的SSID
+extern char *wifiPwd; // WIFI的密码
+
+extern char *authCode; // 产品授权码,产品未启用时为空字符串
+
+extern float firmwareVersion; // 固件版本
+extern float latitude; // 设备精度
+extern float longitude; // 设备维度
+
+extern char mqttSecret[17]; // Mqtt秘钥,16位
+extern char *ntpServer; // NTP服务地址,用于获取当前时间
+/********************************** end 可配置的项 **********************************/
+
+// 加载配置
+void loadConfig();
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/Mqtt.h b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/Mqtt.h
new file mode 100644
index 00000000..43c6f33a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/Mqtt.h
@@ -0,0 +1,43 @@
+/*********************************************************************
+ * function: 设备交互
+ * board: esp8266,esp32,esp32s2,esp32s3 core for esp-idf v4.4.7
+ * source: https://gitee.com/zhuangpengli/IOTDeviceSDK
+ * copyright: zhuangpeng.li all rights reserved.
+ ********************************************************************/
+#ifndef _FASTBEE_MQTT_H
+#define _FASTBEE_MQTT_H
+
+#include "mqtt_client.h"
+// 订阅的主题
+extern char *sInfoTopic; // 订阅设备信息
+extern char *sOtaTopic; // 订阅OTA升级
+extern char *sNtpTopic; // 订阅NTP时间
+extern char *sPropertyTopic; // 订阅属性
+extern char *sFunctionTopic; // 订阅功能
+extern char *sPropertyOnline; // 订阅属性-在线模式
+extern char *sFunctionOnline; // 订阅功能-在线模式
+extern char *sMonitorTopic; // 订阅实时监测
+// 发布的主题
+extern char *pInfoTopic; // 发布设备信息
+extern char *pNtpTopic; // 发布NTP时间
+extern char *pPropertyTopic; // 发布属性
+extern char *pFunctionTopic; // 发布功能
+extern char *pMonitorTopic; // 发布实时监测数据
+extern char *pEventTopic; // 发布事件
+
+// 订阅系统主题
+void subscribeTopic(esp_mqtt_client_handle_t client);
+// 发布设备信息
+void publishInfo(esp_mqtt_client_handle_t client);
+// 发布时钟同步信息
+void publishNtp(esp_mqtt_client_handle_t client);
+// 发布事件
+void publishEvent(esp_mqtt_client_handle_t client, const char *msg);
+// 发布实时监测数据(不会存储,需要实时存储则发布属性)
+void publishMonitor(esp_mqtt_client_handle_t client, const char *msg);
+// 发布属性
+void publishProperty(esp_mqtt_client_handle_t client, const char *msg);
+// 发布功能
+void publishFunction(esp_mqtt_client_handle_t client, const char *msg);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/fastbee.h b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/fastbee.h
new file mode 100644
index 00000000..f9783525
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/fastbee/include/fastbee.h
@@ -0,0 +1,12 @@
+/*********************************************************************
+ * function: 设备交互
+ * board: esp8266,esp32,esp32s2,esp32s3 core for esp-idf v4.4.7
+ * source: https://gitee.com/zhuangpengli/IOTDeviceSDK
+ * copyright: zhuangpeng.li all rights reserved.
+ ********************************************************************/
+#ifndef _FASTBEE_H
+#define _FASTBEE_H
+
+void fastbee_main(void *paras);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/CMakeLists.txt b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/CMakeLists.txt
new file mode 100644
index 00000000..f6119229
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(COMPONENT_ADD_INCLUDEDIRS .)
+
+set(COMPONENT_SRCS "lightbulb.c")
+
+set(COMPONENT_REQUIRES)
+
+register_component()
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/component.mk b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/component.mk
new file mode 100644
index 00000000..a82220a1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/component.mk
@@ -0,0 +1,2 @@
+COMPONENT_ADD_INCLUDEDIRS := ./
+COMPONENT_SRCDIRS := ./
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/lightbulb.c b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/lightbulb.c
new file mode 100644
index 00000000..59a15d9f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/lightbulb.c
@@ -0,0 +1,327 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2019
+ *
+ * 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
+#include
+
+#ifdef CONFIG_IDF_TARGET_ESP8266
+#include "driver/pwm.h"
+#else
+#include "driver/ledc.h"
+#endif
+#include "esp_log.h"
+
+typedef struct rgb {
+ uint8_t r; // 0-100 %
+ uint8_t g; // 0-100 %
+ uint8_t b; // 0-100 %
+} rgb_t;
+
+
+typedef struct hsp {
+ uint16_t h; // 0-360
+ uint16_t s; // 0-100
+ uint16_t b; // 0-100
+} hsp_t;
+
+/* LED numbers below are for ESP-WROVER-KIT */
+/* Red LED */
+#define LEDC_IO_0 (0)
+/* Green LED */
+#define LEDC_IO_1 (2)
+/* Blued LED */
+#define LEDC_IO_2 (4)
+
+#define PWM_DEPTH (1023)
+#define PWM_TARGET_DUTY 8192
+
+static hsp_t s_hsb_val;
+static uint16_t s_brightness;
+static bool s_on = false;
+
+static const char *TAG = "lightbulb";
+
+#ifdef CONFIG_IDF_TARGET_ESP8266
+#define PWM_PERIOD (500)
+#define PWM_IO_NUM 3
+
+// pwm pin number
+const uint32_t pin_num[PWM_IO_NUM] = {
+ LEDC_IO_0,
+ LEDC_IO_1,
+ LEDC_IO_2
+};
+
+// dutys table, (duty/PERIOD)*depth
+uint32_t duties[PWM_IO_NUM] = {
+ 250, 250, 250,
+};
+
+// phase table, (phase/180)*depth
+int16_t phase[PWM_IO_NUM] = {
+ 0, 0, 50,
+};
+
+#define LEDC_CHANNEL_0 0
+#define LEDC_CHANNEL_1 1
+#define LEDC_CHANNEL_2 2
+
+#endif
+
+/**
+ * @brief transform lightbulb's "RGB" and other parameter
+ */
+static void lightbulb_set_aim(uint32_t r, uint32_t g, uint32_t b, uint32_t cw, uint32_t ww, uint32_t period)
+{
+#ifdef CONFIG_IDF_TARGET_ESP8266
+ pwm_stop(0x3);
+ pwm_set_duty(LEDC_CHANNEL_0, r);
+ pwm_set_duty(LEDC_CHANNEL_1, g);
+ pwm_set_duty(LEDC_CHANNEL_2, b);
+ pwm_start();
+#else
+ ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, r);
+ ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, g);
+ ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, b);
+ ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
+ ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1);
+ ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
+#endif
+}
+
+/**
+ * @brief transform lightbulb's "HSV" to "RGB"
+ */
+static bool lightbulb_set_hsb2rgb(uint16_t h, uint16_t s, uint16_t v, rgb_t *rgb)
+{
+ bool res = true;
+ uint16_t hi, F, P, Q, T;
+
+ if (!rgb)
+ return false;
+
+ if (h > 360) return false;
+ if (s > 100) return false;
+ if (v > 100) return false;
+
+ hi = (h / 60) % 6;
+ F = 100 * h / 60 - 100 * hi;
+ P = v * (100 - s) / 100;
+ Q = v * (10000 - F * s) / 10000;
+ T = v * (10000 - s * (100 - F)) / 10000;
+
+ switch (hi) {
+ case 0:
+ rgb->r = v;
+ rgb->g = T;
+ rgb->b = P;
+ break;
+ case 1:
+ rgb->r = Q;
+ rgb->g = v;
+ rgb->b = P;
+ break;
+ case 2:
+ rgb->r = P;
+ rgb->g = v;
+ rgb->b = T;
+ break;
+ case 3:
+ rgb->r = P;
+ rgb->g = Q;
+ rgb->b = v;
+ break;
+ case 4:
+ rgb->r = T;
+ rgb->g = P;
+ rgb->b = v;
+ break;
+ case 5:
+ rgb->r = v;
+ rgb->g = P;
+ rgb->b = Q;
+ break;
+ default:
+ return false;
+ }
+ return res;
+}
+
+/**
+ * @brief set the lightbulb's "HSV"
+ */
+static bool lightbulb_set_aim_hsv(uint16_t h, uint16_t s, uint16_t v)
+{
+ rgb_t rgb_tmp;
+ bool ret = lightbulb_set_hsb2rgb(h, s, v, &rgb_tmp);
+
+ if (ret == false)
+ return false;
+
+ lightbulb_set_aim(rgb_tmp.r * PWM_TARGET_DUTY / 100, rgb_tmp.g * PWM_TARGET_DUTY / 100,
+ rgb_tmp.b * PWM_TARGET_DUTY / 100, (100 - s) * 5000 / 100, v * 2000 / 100, 1000);
+
+ return true;
+}
+
+/**
+ * @brief update the lightbulb's state
+ */
+static void lightbulb_update()
+{
+ lightbulb_set_aim_hsv(s_hsb_val.h, s_hsb_val.s, s_hsb_val.b);
+}
+
+
+/**
+ * @brief initialize the lightbulb lowlevel module
+ */
+void lightbulb_init(void)
+{
+#ifdef CONFIG_IDF_TARGET_ESP8266
+ pwm_init(PWM_PERIOD, duties, PWM_IO_NUM, pin_num);
+ pwm_set_channel_invert(0x1 << 0);
+ pwm_set_phases(phase);
+ pwm_start();
+#else
+ // enable ledc module
+ periph_module_enable(PERIPH_LEDC_MODULE);
+
+ // config the timer
+ ledc_timer_config_t ledc_timer = {
+ //set timer counter bit number
+ .bit_num = LEDC_TIMER_13_BIT,
+ //set frequency of pwm
+ .freq_hz = 5000,
+ //timer mode,
+ .speed_mode = LEDC_LOW_SPEED_MODE,
+ //timer index
+ .timer_num = LEDC_TIMER_0
+ };
+ ledc_timer_config(&ledc_timer);
+
+ //config the channel
+ ledc_channel_config_t ledc_channel = {
+ //set LEDC channel 0
+ .channel = LEDC_CHANNEL_0,
+ //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1)
+ .duty = 100,
+ //GPIO number
+ .gpio_num = LEDC_IO_0,
+ //GPIO INTR TYPE, as an example, we enable fade_end interrupt here.
+ .intr_type = LEDC_INTR_FADE_END,
+ //set LEDC mode, from ledc_mode_t
+ .speed_mode = LEDC_LOW_SPEED_MODE,
+ //set LEDC timer source, if different channel use one timer,
+ //the frequency and bit_num of these channels should be the same
+ .timer_sel = LEDC_TIMER_0
+ };
+ //set the configuration
+ ledc_channel_config(&ledc_channel);
+
+ //config ledc channel1
+ ledc_channel.channel = LEDC_CHANNEL_1;
+ ledc_channel.gpio_num = LEDC_IO_1;
+ ledc_channel_config(&ledc_channel);
+ //config ledc channel2
+ ledc_channel.channel = LEDC_CHANNEL_2;
+ ledc_channel.gpio_num = LEDC_IO_2;
+ ledc_channel_config(&ledc_channel);
+#endif
+}
+
+/**
+ * @brief deinitialize the lightbulb's lowlevel module
+ */
+void lightbulb_deinit(void)
+{
+#ifdef CONFIG_IDF_TARGET_ESP8266
+#else
+ ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0);
+ ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 0);
+ ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, 0);
+#endif
+}
+
+/**
+ * @brief turn on/off the lowlevel lightbulb
+ */
+int lightbulb_set_on(bool value)
+{
+ ESP_LOGI(TAG, "lightbulb_set_on : %s", value == true ? "true" : "false");
+
+ if (value == true) {
+ s_hsb_val.b = s_brightness;
+ s_on = true;
+ } else {
+ s_brightness = s_hsb_val.b;
+ s_hsb_val.b = 0;
+ s_on = false;
+ }
+ lightbulb_update();
+
+ return 0;
+}
+
+/**
+ * @brief set the saturation of the lowlevel lightbulb
+ */
+int lightbulb_set_saturation(float value)
+{
+ ESP_LOGI(TAG, "lightbulb_set_saturation : %f", value);
+
+ s_hsb_val.s = value;
+ if (true == s_on)
+ lightbulb_update();
+
+ return 0;
+}
+
+/**
+ * @brief set the hue of the lowlevel lightbulb
+ */
+int lightbulb_set_hue(float value)
+{
+ ESP_LOGI(TAG, "lightbulb_set_hue : %f", value);
+
+ s_hsb_val.h = value;
+ if (true == s_on)
+ lightbulb_update();
+
+ return 0;
+}
+
+/**
+ * @brief set the brightness of the lowlevel lightbulb
+ */
+int lightbulb_set_brightness(int value)
+{
+ ESP_LOGI(TAG, "lightbulb_set_brightness : %d", value);
+
+ s_hsb_val.b = value;
+ s_brightness = s_hsb_val.b;
+ if (true == s_on)
+ lightbulb_update();
+
+ return 0;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/lightbulb.h b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/lightbulb.h
new file mode 100644
index 00000000..700b0c15
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/lightbulb/lightbulb.h
@@ -0,0 +1,89 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2019
+ *
+ * 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.
+ *
+ */
+#ifndef _LIGHTBULB_H_
+#define _LIGHTBULB_H_
+
+#include
+
+/**
+ * @brief initialize the lightbulb lowlevel module
+ *
+ * @param none
+ *
+ * @return none
+ */
+void lightbulb_init(void);
+
+/**
+ * @brief deinitialize the lightbulb's lowlevel module
+ *
+ * @param none
+ *
+ * @return none
+ */
+void lightbulb_deinit(void);
+
+/**
+ * @brief turn on/off the lowlevel lightbulb
+ *
+ * @param value The "On" value
+ *
+ * @return none
+ */
+int lightbulb_set_on(bool value);
+
+/**
+ * @brief set the saturation of the lowlevel lightbulb
+ *
+ * @param value The Saturation value
+ *
+ * @return
+ * - 0 : OK
+ * - others : fail
+ */
+int lightbulb_set_saturation(float value);
+
+/**
+ * @brief set the hue of the lowlevel lightbulb
+ *
+ * @param value The Hue value
+ *
+ * @return
+ * - 0 : OK
+ * - others : fail
+ */
+int lightbulb_set_hue(float value);
+
+/**
+ * @brief set the brightness of the lowlevel lightbulb
+ *
+ * @param value The Brightness value
+ *
+ * @return
+ * - 0 : OK
+ * - others : fail
+ */
+int lightbulb_set_brightness(int value);
+
+#endif /* _LIGHTBULB_H_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/CMakeLists.txt b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/CMakeLists.txt
new file mode 100644
index 00000000..52977f03
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(COMPONENT_ADD_INCLUDEDIRS .)
+
+set(COMPONENT_SRCS "linkkit_solo.c")
+
+set(COMPONENT_REQUIRES "esp-aliyun" "json" "lightbulb")
+
+register_component()
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/component.mk b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/component.mk
new file mode 100644
index 00000000..a82220a1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/component.mk
@@ -0,0 +1,2 @@
+COMPONENT_ADD_INCLUDEDIRS := ./
+COMPONENT_SRCDIRS := ./
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/linkkit_solo.c b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/linkkit_solo.c
new file mode 100644
index 00000000..cf5a1912
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/linkkit_solo.c
@@ -0,0 +1,468 @@
+
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+void HAL_Printf(const char *fmt, ...);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+
+#ifdef DEPRECATED_LINKKIT
+#include "solo.c"
+#else
+#include
+#include
+#include
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_compat.h"
+#include "infra_compat.h"
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+#endif
+#include "dev_model_api.h"
+#include "dm_wrapper.h"
+#include "cJSON.h"
+#ifdef ATM_ENABLED
+ #include "at_api.h"
+#endif
+
+#include "lightbulb.h"
+#include "esp_log.h"
+
+static const char* TAG = "linkkit_example_solo";
+
+#define EXAMPLE_TRACE(...) \
+ do { \
+ HAL_Printf("\033[1;32;40m%s.%d: ", __func__, __LINE__); \
+ HAL_Printf(__VA_ARGS__); \
+ HAL_Printf("\033[0m\r\n"); \
+ } while (0)
+
+#define EXAMPLE_MASTER_DEVID (0)
+#define EXAMPLE_YIELD_TIMEOUT_MS (200)
+
+typedef struct {
+ int master_devid;
+ int cloud_connected;
+ int master_initialized;
+} user_example_ctx_t;
+
+/**
+ * These PRODUCT_KEY|PRODUCT_SECRET|DEVICE_NAME|DEVICE_SECRET are listed for demo only
+ *
+ * When you created your own devices on iot.console.com, you SHOULD replace them with what you got from console
+ *
+ */
+
+char PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+char PRODUCT_SECRET[IOTX_PRODUCT_SECRET_LEN + 1] = {0};
+char DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0};
+char DEVICE_SECRET[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+
+static user_example_ctx_t g_user_example_ctx;
+
+/** Awss Status event callback */
+static int user_awss_status_event_handler(int status)
+{
+ EXAMPLE_TRACE("Awss Status %d", status);
+
+ return SUCCESS_RETURN;
+}
+
+/** cloud connected event callback */
+static int user_connected_event_handler(void)
+{
+ EXAMPLE_TRACE("Cloud Connected");
+ g_user_example_ctx.cloud_connected = 1;
+
+ return 0;
+}
+
+/** cloud connect fail event callback */
+static int user_connect_fail_event_handler(void)
+{
+ EXAMPLE_TRACE("Cloud Connect Fail");
+
+ return SUCCESS_RETURN;
+}
+
+/** cloud disconnected event callback */
+static int user_disconnected_event_handler(void)
+{
+ EXAMPLE_TRACE("Cloud Disconnected");
+ g_user_example_ctx.cloud_connected = 0;
+
+ return 0;
+}
+
+/** cloud raw_data arrived event callback */
+static int user_rawdata_arrived_event_handler(const int devid, const unsigned char *request, const int request_len)
+{
+ EXAMPLE_TRACE("Cloud Rawdata Arrived");
+
+ return 0;
+}
+
+/* device initialized event callback */
+static int user_initialized(const int devid)
+{
+ EXAMPLE_TRACE("Device Initialized");
+ g_user_example_ctx.master_initialized = 1;
+
+ return 0;
+}
+
+/** recv property post response message from cloud **/
+static int user_report_reply_event_handler(const int devid, const int msgid, const int code, const char *reply,
+ const int reply_len)
+{
+ EXAMPLE_TRACE("Message Post Reply Received, Message ID: %d, Code: %d, Reply: %.*s", msgid, code,
+ reply_len,
+ (reply == NULL)? ("NULL") : (reply));
+ return 0;
+}
+
+/** recv event post response message from cloud **/
+static int user_trigger_event_reply_event_handler(const int devid, const int msgid, const int code, const char *eventid,
+ const int eventid_len, const char *message, const int message_len)
+{
+ EXAMPLE_TRACE("Trigger Event Reply Received, Message ID: %d, Code: %d, EventID: %.*s, Message: %.*s",
+ msgid, code,
+ eventid_len,
+ eventid, message_len, message);
+
+ return 0;
+}
+
+static int user_property_set_event_handler(const int devid, const char *request, const int request_len)
+{
+ int res = 0;
+ cJSON *root = NULL, *LightSwitch = NULL, *LightColor = NULL;
+ ESP_LOGI(TAG,"Property Set Received, Devid: %d, Request: %s", devid, request);
+
+ lightbulb_set_brightness(78);
+ lightbulb_set_saturation(100);
+
+ if (!request) {
+ return NULL_VALUE_ERROR;
+ }
+
+ /* Parse Root */
+ root = cJSON_Parse(request);
+ if (!root) {
+ ESP_LOGI(TAG,"JSON Parse Error");
+ return FAIL_RETURN;
+ }
+
+ /** Switch Lightbulb On/Off */
+ LightSwitch = cJSON_GetObjectItem(root, "LightSwitch");
+ if (LightSwitch) {
+ lightbulb_set_on(LightSwitch->valueint);
+ }
+
+ /** Switch Lightbulb Hue */
+ LightSwitch = cJSON_GetObjectItem(root, "RGBColor");
+ if (LightSwitch) {
+ LightColor = cJSON_GetObjectItem(LightSwitch, "Red");
+ lightbulb_set_hue(LightColor ? LightColor->valueint : 0);
+ LightColor = cJSON_GetObjectItem(LightSwitch, "Green");
+ lightbulb_set_hue(LightColor ? LightColor->valueint : 120);
+ LightColor = cJSON_GetObjectItem(LightSwitch, "Blue");
+ lightbulb_set_hue(LightColor ? LightColor->valueint : 240);
+ }
+
+ cJSON_Delete(root);
+
+ res = IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID, ITM_MSG_POST_PROPERTY,
+ (unsigned char *)request, request_len);
+ ESP_LOGI(TAG,"Post Property Message ID: %d", res);
+
+ return SUCCESS_RETURN;
+}
+
+static int user_property_desired_get_reply_event_handler(const char *serviceid, const int serviceid_len)
+{
+ ESP_LOGI(TAG, "ITE_PROPERTY_DESIRED_GET_REPLY");
+
+ return SUCCESS_RETURN;
+}
+
+static int user_property_get_event_handler(const int devid, const char *serviceid, const int serviceid_len, char **response, int *response_len)
+{
+ ESP_LOGI(TAG,"Get Property Message ID: %d", devid);
+
+ return SUCCESS_RETURN;
+}
+
+
+static int user_service_request_event_handler(const int devid, const char *serviceid, const int serviceid_len,
+ const char *request, const int request_len,
+ char **response, int *response_len)
+{
+ int contrastratio = 0, to_cloud = 0;
+ cJSON *root = NULL, *item_transparency = NULL, *item_from_cloud = NULL;
+ ESP_LOGI(TAG,"Service Request Received, Devid: %d, Service ID: %.*s, Payload: %s", devid, serviceid_len,
+ serviceid,
+ request);
+
+ /* Parse Root */
+ root = cJSON_Parse(request);
+ if (root == NULL || !cJSON_IsObject(root)) {
+ ESP_LOGI(TAG,"JSON Parse Error");
+ return -1;
+ }
+
+ if (strlen("Custom") == serviceid_len && memcmp("Custom", serviceid, serviceid_len) == 0) {
+ /* Parse Item */
+ const char *response_fmt = "{\"Contrastratio\":%d}";
+ item_transparency = cJSON_GetObjectItem(root, "transparency");
+ if (item_transparency == NULL || !cJSON_IsNumber(item_transparency)) {
+ cJSON_Delete(root);
+ return -1;
+ }
+ ESP_LOGI(TAG,"transparency: %d", item_transparency->valueint);
+ contrastratio = item_transparency->valueint + 1;
+
+ /* Send Service Response To Cloud */
+ *response_len = strlen(response_fmt) + 10 + 1;
+ *response = malloc(*response_len);
+ if (*response == NULL) {
+ ESP_LOGW(TAG,"Memory Not Enough");
+ return -1;
+ }
+ memset(*response, 0, *response_len);
+ snprintf(*response, *response_len, response_fmt, contrastratio);
+ *response_len = strlen(*response);
+ } else if (strlen("SyncService") == serviceid_len && memcmp("SyncService", serviceid, serviceid_len) == 0) {
+ /* Parse Item */
+ const char *response_fmt = "{\"ToCloud\":%d}";
+ item_from_cloud = cJSON_GetObjectItem(root, "FromCloud");
+ if (item_from_cloud == NULL || !cJSON_IsNumber(item_from_cloud)) {
+ cJSON_Delete(root);
+ return -1;
+ }
+ ESP_LOGI(TAG,"FromCloud: %d", item_from_cloud->valueint);
+ to_cloud = item_from_cloud->valueint + 1;
+
+ /* Send Service Response To Cloud */
+ *response_len = strlen(response_fmt) + 10 + 1;
+ *response = malloc(*response_len);
+ if (*response == NULL) {
+ ESP_LOGW(TAG,"Memory Not Enough");
+ return -1;
+ }
+ memset(*response, 0, *response_len);
+ snprintf(*response, *response_len, response_fmt, to_cloud);
+ *response_len = strlen(*response);
+ }
+ cJSON_Delete(root);
+
+ return 0;
+}
+
+static int user_timestamp_reply_event_handler(const char *timestamp)
+{
+ EXAMPLE_TRACE("Current Timestamp: %s", timestamp);
+
+ return SUCCESS_RETURN;
+}
+
+static int user_toplist_reply_event_handler(const int devid, const int msgid, const int code, const char *eventid, const int eventid_len)
+{
+ EXAMPLE_TRACE("ITE_TOPOLIST_REPLY");
+
+ return SUCCESS_RETURN;
+}
+
+static int user_permit_join_event_handler(const int devid, const int msgid, const int code, const char *eventid, const int eventid_len)
+{
+ EXAMPLE_TRACE("ITE_PERMIT_JOIN");
+
+ return SUCCESS_RETURN;
+}
+
+/** fota event handler **/
+static int user_fota_event_handler(int type, const char *version)
+{
+ char buffer[1024] = {0};
+ int buffer_length = 1024;
+
+ /* 0 - new firmware exist, query the new firmware */
+ if (type == 0) {
+ EXAMPLE_TRACE("New Firmware Version: %s", version);
+
+ IOT_Linkkit_Query(EXAMPLE_MASTER_DEVID, ITM_MSG_QUERY_FOTA_DATA, (unsigned char *)buffer, buffer_length);
+ }
+
+ return 0;
+}
+
+/* cota event handler */
+static int user_cota_event_handler(int type, const char *config_id, int config_size, const char *get_type,
+ const char *sign, const char *sign_method, const char *url)
+{
+ char buffer[128] = {0};
+ int buffer_length = 128;
+
+ /* type = 0, new config exist, query the new config */
+ if (type == 0) {
+ EXAMPLE_TRACE("New Config ID: %s", config_id);
+ EXAMPLE_TRACE("New Config Size: %d", config_size);
+ EXAMPLE_TRACE("New Config Type: %s", get_type);
+ EXAMPLE_TRACE("New Config Sign: %s", sign);
+ EXAMPLE_TRACE("New Config Sign Method: %s", sign_method);
+ EXAMPLE_TRACE("New Config URL: %s", url);
+
+ IOT_Linkkit_Query(EXAMPLE_MASTER_DEVID, ITM_MSG_QUERY_COTA_DATA, (unsigned char *)buffer, buffer_length);
+ }
+
+ return 0;
+}
+
+static int user_mqtt_connect_succ_event_handler(void)
+{
+ EXAMPLE_TRACE("ITE_MQTT_CONNECT_SUCC");
+
+ return SUCCESS_RETURN;
+}
+
+static void user_post_property(void)
+{
+ static int cnt = 0;
+ int res = 0;
+
+ char property_payload[30] = {0};
+ HAL_Snprintf(property_payload, sizeof(property_payload), "{\"Counter\": %d}", cnt++);
+
+ res = IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID, ITM_MSG_POST_PROPERTY,
+ (unsigned char *)property_payload, strlen(property_payload));
+
+ EXAMPLE_TRACE("Post Property Message ID: %d", res);
+}
+
+static void user_post_event(void)
+{
+ int res = 0;
+ char *event_id = "HardwareError";
+ char *event_payload = "{\"ErrorCode\": 0}";
+
+ res = IOT_Linkkit_TriggerEvent(EXAMPLE_MASTER_DEVID, event_id, strlen(event_id),
+ event_payload, strlen(event_payload));
+ EXAMPLE_TRACE("Post Event Message ID: %d", res);
+}
+
+static void user_deviceinfo_update(void)
+{
+ int res = 0;
+ char *device_info_update = "[{\"attrKey\":\"abc\",\"attrValue\":\"hello,world\"}]";
+
+ res = IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID, ITM_MSG_DEVICEINFO_UPDATE,
+ (unsigned char *)device_info_update, strlen(device_info_update));
+ EXAMPLE_TRACE("Device Info Update Message ID: %d", res);
+}
+
+static void user_deviceinfo_delete(void)
+{
+ int res = 0;
+ char *device_info_delete = "[{\"attrKey\":\"abc\"}]";
+
+ res = IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID, ITM_MSG_DEVICEINFO_DELETE,
+ (unsigned char *)device_info_delete, strlen(device_info_delete));
+ EXAMPLE_TRACE("Device Info Delete Message ID: %d", res);
+}
+
+static int linkkit_thread(void *paras)
+{
+ int res = 0;
+ iotx_linkkit_dev_meta_info_t master_meta_info;
+ int domain_type = 0, dynamic_register = 0, post_reply_need = 0;
+
+#ifdef ATM_ENABLED
+ if (IOT_ATM_Init() < 0) {
+ EXAMPLE_TRACE("IOT ATM init failed!\n");
+ return -1;
+ }
+#endif
+
+ memset(&g_user_example_ctx, 0, sizeof(user_example_ctx_t));
+
+ HAL_GetProductKey(PRODUCT_KEY);
+ HAL_GetProductSecret(PRODUCT_SECRET);
+ HAL_GetDeviceName(DEVICE_NAME);
+ HAL_GetDeviceSecret(DEVICE_SECRET);
+ memset(&master_meta_info, 0, sizeof(iotx_linkkit_dev_meta_info_t));
+ memcpy(master_meta_info.product_key, PRODUCT_KEY, strlen(PRODUCT_KEY));
+ memcpy(master_meta_info.product_secret, PRODUCT_SECRET, strlen(PRODUCT_SECRET));
+ memcpy(master_meta_info.device_name, DEVICE_NAME, strlen(DEVICE_NAME));
+ memcpy(master_meta_info.device_secret, DEVICE_SECRET, strlen(DEVICE_SECRET));
+
+ /* Register Callback */
+ IOT_RegisterCallback(ITE_AWSS_STATUS, user_awss_status_event_handler);
+ IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler);
+ IOT_RegisterCallback(ITE_CONNECT_FAIL, user_connect_fail_event_handler);
+ IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler);
+ IOT_RegisterCallback(ITE_RAWDATA_ARRIVED, user_rawdata_arrived_event_handler);
+ IOT_RegisterCallback(ITE_SERVICE_REQUEST, user_service_request_event_handler);
+ IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_event_handler);
+ IOT_RegisterCallback(ITE_PROPERTY_GET, user_property_get_event_handler);
+ IOT_RegisterCallback(ITE_PROPERTY_DESIRED_GET_REPLY, user_property_desired_get_reply_event_handler);
+ IOT_RegisterCallback(ITE_REPORT_REPLY, user_report_reply_event_handler);
+ IOT_RegisterCallback(ITE_TRIGGER_EVENT_REPLY, user_trigger_event_reply_event_handler);
+ IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_event_handler);
+ IOT_RegisterCallback(ITE_TOPOLIST_REPLY, user_toplist_reply_event_handler);
+ IOT_RegisterCallback(ITE_PERMIT_JOIN, user_permit_join_event_handler);
+ IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized);
+ IOT_RegisterCallback(ITE_FOTA, user_fota_event_handler);
+ IOT_RegisterCallback(ITE_COTA, user_cota_event_handler);
+ IOT_RegisterCallback(ITE_MQTT_CONNECT_SUCC, user_mqtt_connect_succ_event_handler);
+
+#if CONFIG_MQTT_DIRECT
+ domain_type = IOTX_CLOUD_REGION_SHANGHAI;
+#else
+ domain_type = IOTX_CLOUD_REGION_SINGAPORE;
+#endif
+
+ IOT_Ioctl(IOTX_IOCTL_SET_DOMAIN, (void *)&domain_type);
+
+ /* Choose Login Method */
+ dynamic_register = 0;
+ IOT_Ioctl(IOTX_IOCTL_SET_DYNAMIC_REGISTER, (void *)&dynamic_register);
+
+ /* post reply doesn't need */
+ post_reply_need = 1;
+ IOT_Ioctl(IOTX_IOCTL_RECV_EVENT_REPLY, (void *)&post_reply_need);
+
+ /* Create Master Device Resources */
+ g_user_example_ctx.master_devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, &master_meta_info);
+ if (g_user_example_ctx.master_devid < 0) {
+ EXAMPLE_TRACE("IOT_Linkkit_Open Failed\n");
+ return -1;
+ }
+
+ /* Start Connect Aliyun Server */
+ res = IOT_Linkkit_Connect(g_user_example_ctx.master_devid);
+ if (res < 0) {
+ EXAMPLE_TRACE("IOT_Linkkit_Connect Failed\n");
+ IOT_Linkkit_Close(g_user_example_ctx.master_devid);
+ return -1;
+ }
+
+ while (1) {
+ IOT_Linkkit_Yield(EXAMPLE_YIELD_TIMEOUT_MS);
+ }
+
+ IOT_Linkkit_Close(g_user_example_ctx.master_devid);
+
+ IOT_DumpMemoryStats(IOT_LOG_DEBUG);
+ IOT_SetLogLevel(IOT_LOG_NONE);
+ return 0;
+}
+
+void linkkit_main(void *paras)
+{
+ while (1) {
+ linkkit_thread(NULL);
+ }
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/linkkit_solo.h b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/linkkit_solo.h
new file mode 100644
index 00000000..eafc8fc9
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/components/linkkit_handle/linkkit_solo.h
@@ -0,0 +1,29 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2019
+ *
+ * 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.
+ *
+ */
+#ifndef _LINKKIT_SOLO_H__
+#define _LINKKIT_SOLO_H__
+
+void linkkit_main(void *paras);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/CMakeLists.txt b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/CMakeLists.txt
new file mode 100644
index 00000000..4f9ae6c6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/CMakeLists.txt
@@ -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)
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/Kconfig b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/Kconfig
new file mode 100644
index 00000000..7599f3e2
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/Kconfig
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/component.mk b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/component.mk
new file mode 100644
index 00000000..ce30a408
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/component.mk
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/README.md b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/README.md
new file mode 100644
index 00000000..bcc92e14
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/README.md
@@ -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。
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/multipule_mfg_config.csv b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/multipule_mfg_config.csv
new file mode 100644
index 00000000..95fc4c2f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/multipule_mfg_config.csv
@@ -0,0 +1,5 @@
+aliyun-key,namespace,
+DeviceName,data,string
+DeviceSecret,data,string
+ProductKey,data,string
+ProductSecret,data,string
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/multipule_mfg_values.csv b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/multipule_mfg_values.csv
new file mode 100644
index 00000000..1aa970b6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/multipule_mfg_values.csv
@@ -0,0 +1,4 @@
+id,DeviceName,DeviceSecret,ProductKey,ProductSecret
+1,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
+2,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
+3,config,dsj3RuY74pgCBJ3zczKz1LaLK7RGApqh,a10BnLLzGv4,pVfLpS1u3A9JM0go
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/single_mfg_config.csv b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/single_mfg_config.csv
new file mode 100644
index 00000000..d81b3660
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/config/mass_mfg/single_mfg_config.csv
@@ -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
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.c
new file mode 100644
index 00000000..d58492e4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.c
@@ -0,0 +1,415 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2019
+ *
+ * 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
+#include
+#include
+#include
+#include
+#include
+
+#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;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.h
new file mode 100644
index 00000000..c78ebc2c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/conn_mgr/conn_mgr.h
@@ -0,0 +1,149 @@
+/*
+ * ESPRESSIF MIT License
+ *
+ * Copyright (c) 2019
+ *
+ * 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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/certs/root_ca.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/certs/root_ca.c
new file mode 100644
index 00000000..4881a944
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/certs/root_ca.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+
+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-----"
+};
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPExport.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPExport.h
new file mode 100644
index 00000000..5e0016cd
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPExport.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPMessage.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPMessage.h
new file mode 100644
index 00000000..5899698b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPMessage.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPNetwork.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPNetwork.h
new file mode 100644
index 00000000..43ec5b1e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPNetwork.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+
+#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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPPlatform.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPPlatform.h
new file mode 100644
index 00000000..8e8da178
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/Cloud_CoAPPlatform.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __COAP_PLATFORM_OS_H__
+#define __COAP_PLATFORM_OS_H__
+#include
+
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPDeserialize.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPDeserialize.h
new file mode 100644
index 00000000..8d0cef68
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPDeserialize.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __COAP_DESERIALIZE_H__
+#define __COAP_DESERIALIZE_H__
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPDeserialize_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPDeserialize_common.c
new file mode 100644
index 00000000..c034a795
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPDeserialize_common.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#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;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPExport.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPExport.c
new file mode 100644
index 00000000..5c9a6dea
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPExport.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include
+#include
+#include
+#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;
+ }
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPMessage.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPMessage.c
new file mode 100644
index 00000000..4214d880
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPMessage.c
@@ -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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPMessage_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPMessage_common.c
new file mode 100644
index 00000000..47e6104f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPMessage_common.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+
+#include
+#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;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPNetwork.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPNetwork.c
new file mode 100644
index 00000000..68847070
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPNetwork.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#include
+#include
+
+#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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPPlatform.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPPlatform.h
new file mode 100644
index 00000000..02f6eca0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPPlatform.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __COAP_PLATFORM_OS_H__
+#define __COAP_PLATFORM_OS_H__
+
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPSerialize.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPSerialize.h
new file mode 100644
index 00000000..4a8177d1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPSerialize.h
@@ -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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPSerialize_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPSerialize_common.c
new file mode 100644
index 00000000..ae2f0d89
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/CoAPSerialize_common.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#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);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/coap_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/coap_api.h
new file mode 100644
index 00000000..127990dc
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/coap_api.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/coap_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/coap_wrapper.h
new file mode 100644
index 00000000..d11faa30
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/coap_wrapper.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap.h
new file mode 100644
index 00000000..e557ef7a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap.h
@@ -0,0 +1,2 @@
+#include "CoAPServer.h"
+#include "iotx_coap_internal.h"
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_api.c
new file mode 100644
index 00000000..2aa5cd4e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_api.c
@@ -0,0 +1,950 @@
+/*
+* Copyright (C) 2015-2018 Alibaba Group Holding Limited
+*/
+
+#include
+
+#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);
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_config.h
new file mode 100644
index 00000000..489903e3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_config.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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_internal.h
new file mode 100644
index 00000000..364634e6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_cloud/iotx_coap_internal.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __IOTX_COAP_INTERNAL__
+#define __IOTX_COAP_INTERNAL__
+
+#include
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPDeserialize.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPDeserialize.h
new file mode 100644
index 00000000..8d0cef68
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPDeserialize.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __COAP_DESERIALIZE_H__
+#define __COAP_DESERIALIZE_H__
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPDeserialize_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPDeserialize_common.c
new file mode 100644
index 00000000..c034a795
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPDeserialize_common.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#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;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPMessage_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPMessage_common.c
new file mode 100644
index 00000000..47e6104f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPMessage_common.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+
+#include
+#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;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPPlatform.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPPlatform.h
new file mode 100644
index 00000000..02f6eca0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPPlatform.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __COAP_PLATFORM_OS_H__
+#define __COAP_PLATFORM_OS_H__
+
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPSerialize.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPSerialize.h
new file mode 100644
index 00000000..4a8177d1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPSerialize.h
@@ -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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPSerialize_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPSerialize_common.c
new file mode 100644
index 00000000..ae2f0d89
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/CoAPPacket/CoAPSerialize_common.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#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);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/coap_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/coap_api.h
new file mode 100644
index 00000000..127990dc
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/coap_api.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/coap_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/coap_wrapper.h
new file mode 100644
index 00000000..d11faa30
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/coap_wrapper.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap.h
new file mode 100644
index 00000000..e557ef7a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap.h
@@ -0,0 +1,2 @@
+#include "CoAPServer.h"
+#include "iotx_coap_internal.h"
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap_config.h
new file mode 100644
index 00000000..489903e3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap_config.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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap_internal.h
new file mode 100644
index 00000000..364634e6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/iotx_coap_internal.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __IOTX_COAP_INTERNAL__
+#define __IOTX_COAP_INTERNAL__
+
+#include
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPExport.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPExport.c
new file mode 100644
index 00000000..d6e03973
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPExport.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#include
+#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");
+ }
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPExport.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPExport.h
new file mode 100644
index 00000000..bf2b9aab
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPExport.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPInternal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPInternal.h
new file mode 100644
index 00000000..b5441be4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPInternal.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPMessage.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPMessage.c
new file mode 100644
index 00000000..69e96311
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPMessage.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+
+#include
+#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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPMessage.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPMessage.h
new file mode 100644
index 00000000..f5b43506
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPMessage.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPNetwork.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPNetwork.c
new file mode 100644
index 00000000..86755443
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPNetwork.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#include
+#include
+
+#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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPNetwork.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPNetwork.h
new file mode 100644
index 00000000..361d640e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPNetwork.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __CoAPNETWORK_H__
+#define __CoAPNETWORK_H__
+#include
+
+#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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPObserve.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPObserve.c
new file mode 100644
index 00000000..34450703
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPObserve.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPObserve.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPObserve.h
new file mode 100644
index 00000000..8ecc78a1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPObserve.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPPlatform.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPPlatform.c
new file mode 100644
index 00000000..8cef1439
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPPlatform.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+
+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);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPResource.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPResource.c
new file mode 100644
index 00000000..71c29f17
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPResource.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#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;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPResource.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPResource.h
new file mode 100644
index 00000000..f44ab891
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPResource.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef __COAP_RESOURCE_H__
+#define __COAP_RESOURCE_H__
+
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPServer.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPServer.c
new file mode 100644
index 00000000..168a00d8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPServer.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include
+#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
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPServer.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPServer.h
new file mode 100644
index 00000000..795ef514
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/coap_server/server/CoAPServer.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/dev_bind_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/dev_bind_api.h
new file mode 100644
index 00000000..93482be8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/dev_bind_api.h
@@ -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.
+ **/
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/dev_bind_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/dev_bind_wrapper.h
new file mode 100644
index 00000000..2e1f3e4f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/dev_bind_wrapper.h
@@ -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);
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind.c
new file mode 100644
index 00000000..50a3947c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind_statis.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind_statis.c
new file mode 100644
index 00000000..a2533cba
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind_statis.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind_statis.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind_statis.h
new file mode 100644
index 00000000..9fb5b7ae
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_bind_statis.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp.h
new file mode 100644
index 00000000..0e467d4b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp.h
@@ -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
+/**
+ * @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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp_coap.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp_coap.c
new file mode 100644
index 00000000..5be0625f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp_coap.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp_mqtt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp_mqtt.c
new file mode 100644
index 00000000..f4e57dd7
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_cmp_mqtt.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_event.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_event.c
new file mode 100644
index 00000000..399b8908
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_event.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_event.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_event.h
new file mode 100644
index 00000000..f4eaef49
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_event.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_info.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_info.c
new file mode 100644
index 00000000..f85f01f2
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_info.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_info.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_info.h
new file mode 100644
index 00000000..31c6db68
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_info.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_INFO_H__
+#define __AWSS_INFO_H__
+
+#include
+
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_log.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_log.h
new file mode 100644
index 00000000..425929bc
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_log.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_notify.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_notify.c
new file mode 100644
index 00000000..a5e6d72d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_notify.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_notify.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_notify.h
new file mode 100644
index 00000000..4b5691a1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_notify.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_packet.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_packet.c
new file mode 100644
index 00000000..11a859e4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_packet.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_packet.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_packet.h
new file mode 100644
index 00000000..45595a91
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_packet.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_report.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_report.c
new file mode 100644
index 00000000..0deed97c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_report.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset.h
new file mode 100644
index 00000000..c05bbbb5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset/awss_dev_reset.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset/awss_dev_reset.c
new file mode 100644
index 00000000..3a40c8f3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset/awss_dev_reset.c
@@ -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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset/awss_dev_reset_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset/awss_dev_reset_internal.h
new file mode 100644
index 00000000..5489edf7
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_reset/awss_dev_reset_internal.h
@@ -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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_timer.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_timer.c
new file mode 100644
index 00000000..86cb4a2a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_timer.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_timer.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_timer.h
new file mode 100644
index 00000000..f00dc82e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_timer.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_utils.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_utils.h
new file mode 100644
index 00000000..b41303df
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/awss_utils.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/dev_bind_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/dev_bind_internal.h
new file mode 100644
index 00000000..4bbdfd5a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/dev_bind_internal.h
@@ -0,0 +1,27 @@
+#include "infra_config.h"
+#include
+#include
+#include
+#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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/iot_import_awss.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/iot_import_awss.h
new file mode 100644
index 00000000..8faf4020
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/iot_import_awss.h
@@ -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__ */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/os/os.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/os/os.h
new file mode 100644
index 00000000..5fe9a495
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/os/os.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
+#include "infra_defs.h"
+#include
+#include
+#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_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/os/os_misc.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/os/os_misc.c
new file mode 100644
index 00000000..d06b4897
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/os/os_misc.c
@@ -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 */
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/passwd.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/passwd.c
new file mode 100644
index 00000000..67cf2208
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/passwd.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/passwd.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/passwd.h
new file mode 100644
index 00000000..51c61531
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/passwd.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/sha256.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/sha256.c
new file mode 100644
index 00000000..2250d74a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/sha256.c
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/sha256.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/sha256.h
new file mode 100644
index 00000000..b22f2815
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_bind/impl/sha256.h
@@ -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_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_adapter.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_adapter.c
new file mode 100644
index 00000000..f5895501
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_adapter.c
@@ -0,0 +1,910 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include
+#include
+
+#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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_adapter.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_adapter.h
new file mode 100644
index 00000000..dabfca5e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_adapter.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api.c
new file mode 100644
index 00000000..1cec4662
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api.c
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include
+#include
+#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;
+ }
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api.h
new file mode 100644
index 00000000..cdeb96ed
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api_internal.h
new file mode 100644
index 00000000..31adbab5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_api_internal.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_base64.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_base64.c
new file mode 100644
index 00000000..3f4a3d27
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_base64.c
@@ -0,0 +1,132 @@
+
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+#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;
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_base64.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_base64.h
new file mode 100644
index 00000000..6912a09f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_base64.h
@@ -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
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_client.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_client.c
new file mode 100644
index 00000000..54313bde
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_client.c
@@ -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
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_coap.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_coap.c
new file mode 100644
index 00000000..857a7b4d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_coap.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+#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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_coap.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_coap.h
new file mode 100644
index 00000000..398d9dff
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_coap.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_internal.h
new file mode 100644
index 00000000..de02f287
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_internal.h
@@ -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
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_localsetup.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_localsetup.c
new file mode 100644
index 00000000..53a66c72
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_localsetup.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+
+#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);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_localsetup.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_localsetup.h
new file mode 100644
index 00000000..e3d41715
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_localsetup.h
@@ -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
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_mqtt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_mqtt.c
new file mode 100644
index 00000000..ac099492
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_mqtt.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include
+#include
+#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;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_mqtt.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_mqtt.h
new file mode 100644
index 00000000..05902530
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_mqtt.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _ALCS_MQTT_H_
+#define _ALCS_MQTT_H_
+
+#include "alcs_internal.h"
+
+typedef enum {
+ ALCS_MQTT_STATUS_SUCCESS,
+ ALCS_MQTT_STATUS_ERROR
+} alcs_mqtt_status_e;
+
+typedef struct {
+ CoAPContext *coap_ctx;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2];
+ uint32_t send_id;
+} alcs_mqtt_ctx_t;
+
+#define ALCS_MQTT_PREFIX "/sys/%s/%s"
+
+#define ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT "/thing/lan/prefix/get_reply"
+#define ALCS_MQTT_THING_LAN_PREFIX_GET_FMT "/thing/lan/prefix/get"
+#define ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT "/thing/lan/prefix/update"
+#define ALCS_MQTT_THING_LAN_PREFIX_UPDATE_REPLY_FMT "/thing/lan/prefix/update_reply"
+#define ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT "/thing/lan/blacklist/update"
+#define ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_REPLY_FMT "/thing/lan/blacklist/update_reply"
+
+#define ALCS_MQTT_THING_ALCS_REQUEST "{\"id\":\"%d\",\"version\":\"1.0\",\"params\":\"{}\",\"method\":\"thing.lan.prefix.get\"}"
+#define ALCS_MQTT_THING_LAN_PREFIX_RESPONSE_FMT "{\"id\": \"%d\", \"code\": %d, \"data\": %s}"
+#define ALCS_MQTT_THING_ALCS_SUBDEV_REQUEST "{\"id\":\"%d\",\"version\":\"1.0\",\"params\":{\"productKey\":\"%.*s\",\"deviceName\":\"%.*s\"},\"method\":\"thing.lan.prefix.get\"}"
+
+#define ALCS_MQTT_TOPIC_MAX_LEN (128)
+
+#define ALCS_MQTT_JSON_KEY_PRODUCT_KEY "productKey"
+#define ALCS_MQTT_JSON_KEY_DEVICE_NAME "deviceName"
+#define ALCS_MQTT_JSON_KEY_PREFIX "prefix"
+#define ALCS_MQTT_JSON_KEY_SECRET "deviceSecret"
+#define ALCS_MQTT_JSON_KEY_BLACK "blacklist"
+
+#define ALCS_MQTT_PREFIX_MAX_LEN (40)
+#define ALCS_MQTT_SECRET_MAX_LEN (40)
+#define ALCS_MQTT_BLACK_MAX_LEN (100)
+
+alcs_mqtt_status_e alcs_mqtt_init(void *handle, char *product_key, char *device_name);
+alcs_mqtt_status_e alcs_mqtt_deinit(void *handle, char *product_key, char *device_name);
+alcs_mqtt_status_e alcs_mqtt_blacklist_update(void *ctx);
+alcs_mqtt_status_e alcs_mqtt_prefixkey_update(void *ctx);
+void alcs_mqtt_add_srv_key(const char *prefix, const char *secret);
+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);
+alcs_mqtt_status_e alcs_mqtt_prefix_secret_del(const char *pk, uint16_t pk_len,
+ const char *dn, uint16_t dn_len);
+alcs_mqtt_status_e alcs_mqtt_subdev_prefix_get(const char *product_key, const char *device_name);
+alcs_mqtt_status_e alcs_prefixkey_get(const char *product_key, const char *device_name);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_server.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_server.c
new file mode 100644
index 00000000..d609fba2
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/alcs_server.c
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "alcs_internal.h"
+#include "alcs_api_internal.h"
+#include "CoAPPlatform.h"
+#include "CoAPResource.h"
+#ifdef LOG_REPORT_TO_CLOUD
+ #include "iotx_log_report.h"
+#endif
+#define RES_FORMAT "{\"id\":\"%.*s\",\"code\":%d,\"data\":{%s}}"
+
+#ifdef ALCS_SERVER_ENABLED
+
+int sessionid_seed = 0xff;
+static int default_heart_expire = 120000;
+
+void utils_hmac_sha1_base64(const char *msg, int msg_len, const char *key, int key_len, char *digest, int *digest_len)
+{
+ char buf[20];
+ uint32_t outlen;
+ utils_hmac_sha1_hex(msg, msg_len, buf, key, key_len);
+
+ utils_base64encode((unsigned char *)buf, 20, *digest_len, (unsigned char *)digest, &outlen);
+ *digest_len = outlen;
+}
+
+void alcs_rec_auth_select(CoAPContext *ctx, const char *paths, NetworkAddr *from, CoAPMessage *resMsg)
+{
+ int seqlen, datalen;
+ char *seq, *data;
+ char *targetKey = "";
+ int targetLen = 0;
+ auth_list *lst = NULL;
+ char *accesskeys;
+ int keylen;
+ char back;
+ char *str_pos, *entry;
+ int entry_len, type;
+ CoAPMessage msg;
+ char keybuf[32];
+ char payloadbuf[512];
+ CoAPLenString token = {resMsg->header.tokenlen, resMsg->token};
+ CoAPLenString payload;
+
+ /* int res_code = 200; */
+ COAP_DEBUG("receive data:%.*s", resMsg->payloadlen, resMsg->payload);
+
+ do {
+
+ if (!req_payload_parser((const char *)resMsg->payload, resMsg->payloadlen, &seq, &seqlen, &data, &datalen)) {
+ break;
+ }
+ lst = get_list(ctx);
+
+ accesskeys = json_get_value_by_name(data, datalen, "accessKeys", &keylen, NULL);
+ if (!accesskeys || !keylen) {
+ break;
+ }
+ COAP_DEBUG("accessKeys:%.*s", keylen, accesskeys);
+
+ backup_json_str_last_char(accesskeys, keylen, back);
+ json_array_for_each_entry(accesskeys, keylen, str_pos, entry, entry_len, type) {
+ svr_key_item *node = NULL, *next = NULL;
+ svr_group_item *gnode = NULL, *gnext = NULL;
+ COAP_DEBUG("entry:%.*s", entry_len, entry);
+ list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
+ COAP_DEBUG("keyprefix:%s", node->keyInfo.keyprefix);
+ if (strstr(entry, node->keyInfo.keyprefix) == entry) {
+ COAP_DEBUG("target keyprefix:%s", entry);
+ targetKey = entry;
+ targetLen = entry_len;
+ break;
+ }
+ }
+ if (targetKey) {
+ break;
+ }
+
+ list_for_each_entry_safe(gnode, gnext, &lst->lst_svr_group, lst, svr_group_item) {
+ COAP_DEBUG("keyprefix:%s", gnode->keyInfo.keyprefix);
+ if (strstr(entry, gnode->keyInfo.keyprefix) == entry) {
+ COAP_DEBUG("target keyprefix:%s", entry);
+ targetKey = entry;
+ targetLen = entry_len;
+ break;
+ }
+ }
+ if (targetKey) {
+ break;
+ }
+ }
+ restore_json_str_last_char(accesskeys, keylen, back);
+
+ } while (0);
+
+ COAP_DEBUG("key:%s", targetKey);
+
+
+ HAL_Snprintf(keybuf, sizeof(keybuf), "\"accessKey\":\"%.*s\"", targetLen, targetKey);
+
+ HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, targetKey ? 200 : COAP_MSG_CODE_401_UNAUTHORIZED,
+ keybuf);
+ payload.data = (unsigned char *)payloadbuf;
+ payload.len = strlen(payloadbuf);
+
+ alcs_msg_init(ctx, &msg, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
+ alcs_sendrsp(ctx, from, &msg, 1, resMsg->header.msgid, &token);
+}
+
+svr_key_info *is_legal_key(CoAPContext *ctx, const char *keyprefix, int prefixlen, const char *keyseq, int seqlen,
+ int *res_code)
+{
+ auth_list *lst = get_list(ctx);
+ COAP_INFO("islegal prefix:%.*s, seq:%.*s", prefixlen, keyprefix, seqlen, keyseq);
+
+ if (lst) {
+ COAP_DEBUG("find devices");
+ HAL_MutexLock(lst->list_mutex);
+
+ if (lst->revocation) {
+ int len = strlen(lst->revocation);
+ int i;
+ for (i = 0; i < len; i += KEYSEQ_LEN) {
+ if (strncmp(keyseq, lst->revocation + i, seqlen) == 0) {
+ HAL_MutexUnlock(lst->list_mutex);
+ *res_code = ALCS_AUTH_REVOCATE;
+ COAP_INFO("accesskey is revocated");
+ return NULL;
+ }
+ }
+ }
+
+ if (list_empty(&lst->lst_svr)) {
+ COAP_INFO("ALCS_AUTH_AUTHLISTEMPTY:%d\r\n", ALCS_AUTH_AUTHLISTEMPTY);
+ *res_code = ALCS_AUTH_AUTHLISTEMPTY;
+ } else {
+ svr_key_item *node = NULL, *next = NULL;
+ svr_group_item *gnode = NULL, *gnext = NULL;
+ list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
+ COAP_DEBUG("node prefix:%s", node->keyInfo.keyprefix);
+ if (strlen(node->keyInfo.keyprefix) == prefixlen && strncmp(keyprefix, node->keyInfo.keyprefix, prefixlen) == 0) {
+ *res_code = ALCS_AUTH_OK;
+ HAL_MutexUnlock(lst->list_mutex);
+ return &node->keyInfo;
+ }
+ }
+ list_for_each_entry_safe(gnode, gnext, &lst->lst_svr_group, lst, svr_group_item) {
+ COAP_DEBUG("node prefix:%s", gnode->keyInfo.keyprefix);
+ if (strlen(gnode->keyInfo.keyprefix) == prefixlen && strncmp(keyprefix, gnode->keyInfo.keyprefix, prefixlen) == 0) {
+ *res_code = ALCS_AUTH_OK;
+ HAL_MutexUnlock(lst->list_mutex);
+ return &gnode->keyInfo;
+ }
+ }
+
+ COAP_INFO("ALCS_AUTH_UNMATCHPREFIX:%d\r\n", ALCS_AUTH_UNMATCHPREFIX);
+ *res_code = ALCS_AUTH_UNMATCHPREFIX;
+ }
+
+ HAL_MutexUnlock(lst->list_mutex);
+ }
+
+ return NULL;
+}
+
+void alcs_rec_auth(CoAPContext *ctx, const char *paths, NetworkAddr *from, CoAPMessage *resMsg)
+{
+ int seqlen, datalen;
+ char *seq, *data;
+ int res_code = 200;
+ char body[200] = {0};
+ char *accesskey, *randomkey, *sign;
+ int tmplen;
+ char *keyprefix;
+ char *keyseq;
+ char accessToken[64];
+ int tokenlen;
+ int randomkeylen;
+ char buf[40];
+ int calc_sign_len;
+ int pklen, dnlen;
+ char *pk;
+ char *dn;
+ char tmp1;
+ char tmp2;
+ svr_key_info *item;
+ AlcsDeviceKey devKey;
+ session_item *session;
+ CoAPMessage message;
+ char payloadbuf[512];
+ CoAPLenString payload;
+ CoAPLenString token;
+ COAP_INFO("receive data:%.*s, from:%s", resMsg->payloadlen, resMsg->payload, from->addr);
+
+ do {
+ if (!req_payload_parser((const char *)resMsg->payload, resMsg->payloadlen, &seq, &seqlen, &data, &datalen)) {
+ break;
+ }
+
+ accesskey = json_get_value_by_name(data, datalen, "accessKey", &tmplen, NULL);
+ COAP_INFO("accesskey:%.*s", tmplen, accesskey);
+
+ if (!accesskey || tmplen != KEYPREFIX_LEN + 1 + 1 + KEYSEQ_LEN) {
+ break;
+ }
+
+ keyprefix = accesskey;
+ keyseq = accesskey + KEYPREFIX_LEN + 1 + 1;
+
+ item = is_legal_key(ctx, keyprefix, KEYPREFIX_LEN, keyseq, KEYSEQ_LEN, &res_code);
+ if (!item) {
+ COAP_INFO("islegal return null");
+ break;
+ }
+
+ tokenlen = sizeof(accessToken);
+ utils_hmac_sha1_base64(accesskey, tmplen, item->secret, strlen(item->secret), accessToken, &tokenlen);
+
+ COAP_INFO("accessToken:%.*s", tokenlen, accessToken);
+ randomkey = json_get_value_by_name(data, datalen, "randomKey", &randomkeylen, NULL);
+ if (!randomkey || !randomkeylen) {
+ res_code = ALCS_AUTH_INVALIDPARAM;
+ break;
+ }
+
+ /*calc sign, save in buf*/
+
+ calc_sign_len = sizeof(buf);
+ utils_hmac_sha1_base64(randomkey, randomkeylen, accessToken, tokenlen, buf, &calc_sign_len);
+
+ COAP_INFO("calc randomKey:%.*s,token:%.*s,sign:%.*s", randomkeylen, randomkey, tokenlen,
+ accessToken, calc_sign_len, buf);
+
+ sign = json_get_value_by_name(data, datalen, "sign", &tmplen, NULL);
+ if (!sign || tmplen != calc_sign_len || strncmp(sign, buf, calc_sign_len)) {
+ res_code = ALCS_AUTH_ILLEGALSIGN;
+ break;
+ }
+
+ pk = json_get_value_by_name(data, datalen, "prodKey", &pklen, NULL);
+ dn = json_get_value_by_name(data, datalen, "deviceName", &dnlen, NULL);
+
+ if (!pk || !pklen || !dn || !dnlen) {
+ res_code = ALCS_AUTH_INVALIDPARAM;
+ break;
+ }
+ tmp1 = pk[pklen];
+ tmp2 = dn[dnlen];
+ pk[pklen] = 0;
+ dn[dnlen] = 0;
+
+
+ memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
+ memcpy(&devKey.addr, from, sizeof(NetworkAddr));
+ devKey.pk = pk;
+ devKey.dn = dn;
+ session = get_svr_session(ctx, &devKey);
+
+ if (!session) {
+ char path[100] = {0};
+ struct list_head *svr_head;
+ session = (session_item *)coap_malloc(sizeof(session_item));
+ gen_random_key((unsigned char *)session->randomKey, RANDOMKEY_LEN);
+ session->sessionId = ++sessionid_seed;
+
+ strncpy(path, pk, sizeof(path));
+ strncat(path, dn, sizeof(path) - strlen(path) - 1);
+ CoAPPathMD5_sum(path, strlen(path), session->pk_dn, PK_DN_CHECKSUM_LEN);
+
+ memcpy(&session->addr, from, sizeof(NetworkAddr));
+ COAP_INFO("new session, addr:%s, port:%d", session->addr.addr, session->addr.port);
+ svr_head = get_svr_session_list(ctx);
+ list_add_tail(&session->lst, svr_head);
+ }
+
+ pk[pklen] = tmp1;
+ dn[dnlen] = tmp2;
+
+ HAL_Snprintf(buf, sizeof(buf), "%.*s%s", randomkeylen, randomkey, session->randomKey);
+ utils_hmac_sha1_hex(buf, strlen(buf), session->sessionKey, accessToken, tokenlen);
+
+ /*calc sign, save in buf*/
+ calc_sign_len = sizeof(buf);
+ utils_hmac_sha1_base64(session->randomKey, RANDOMKEY_LEN, accessToken, tokenlen, buf, &calc_sign_len);
+ HAL_Snprintf(body, sizeof(body), "\"sign\":\"%.*s\",\"randomKey\":\"%s\",\"sessionId\":%d,\"expire\":86400",
+ calc_sign_len, buf, session->randomKey, session->sessionId);
+
+ session->authed_time = HAL_UptimeMs();
+ session->heart_time = session->authed_time;
+ /* ??? */
+ /* result = 1; */
+
+ } while (0);
+
+ HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, res_code, body);
+ payload.len = strlen(payloadbuf);
+ payload.data = (unsigned char *)payloadbuf;
+ alcs_msg_init(ctx, &message, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
+ token.len = resMsg->header.tokenlen;
+ token.data = resMsg->token;
+ alcs_sendrsp(ctx, from, &message, 1, resMsg->header.msgid, &token);
+}
+
+static int alcs_remove_low_priority_key(CoAPContext *ctx, ServerKeyPriority priority)
+{
+ auth_list *lst = get_list(ctx);
+ svr_key_item *node = NULL, *next = NULL;
+
+ HAL_MutexLock(lst->list_mutex);
+
+ list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
+ if (node->keyInfo.priority < priority) {
+ coap_free(node->keyInfo.secret);
+ list_del(&node->lst);
+ coap_free(node);
+ --lst->svr_count;
+ }
+ }
+ HAL_MutexUnlock(lst->list_mutex);
+
+ return COAP_SUCCESS;
+}
+
+static int add_svr_key(CoAPContext *ctx, const char *keyprefix, const char *secret, bool isGroup,
+ ServerKeyPriority priority)
+{
+ auth_list *lst = get_list(ctx);
+ svr_key_item *node = NULL, *next = NULL;
+ svr_key_item *item;
+ COAP_INFO("add_svr_key\n");
+ if (!lst || lst->svr_count >= KEY_MAXCOUNT || strlen(keyprefix) != KEYPREFIX_LEN) {
+ return COAP_ERROR_INVALID_LENGTH;
+ }
+ alcs_remove_low_priority_key(ctx, priority);
+
+ HAL_MutexLock(lst->list_mutex);
+ list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
+ if (node->keyInfo.priority > priority) {
+ /* find high priority key */
+ HAL_MutexUnlock(lst->list_mutex);
+ return COAP_ERROR_UNSUPPORTED;
+ }
+ }
+
+ item = (svr_key_item *) coap_malloc(sizeof(svr_key_item));
+ if (!item) {
+ HAL_MutexUnlock(lst->list_mutex);
+ return COAP_ERROR_MALLOC;
+ }
+
+ item->keyInfo.secret = (char *) coap_malloc(strlen(secret) + 1);
+ if (!item->keyInfo.secret) {
+ HAL_MutexUnlock(lst->list_mutex);
+ coap_free(item);
+ return COAP_ERROR_MALLOC;
+ }
+ strcpy(item->keyInfo.secret, secret);
+ memcpy(item->keyInfo.keyprefix, keyprefix, KEYPREFIX_LEN);
+ item->keyInfo.priority = priority;
+
+ list_add_tail(&item->lst, &lst->lst_svr);
+ ++lst->svr_count;
+ HAL_MutexUnlock(lst->list_mutex);
+
+ return COAP_SUCCESS;
+}
+
+int alcs_add_svr_key(CoAPContext *ctx, const char *keyprefix, const char *secret, ServerKeyPriority priority)
+{
+ COAP_INFO("alcs_add_svr_key, priority=%d", priority);
+ return add_svr_key(ctx, keyprefix, secret, 0, priority);
+}
+
+
+int alcs_remove_svr_key(CoAPContext *ctx, const char *keyprefix)
+{
+ auth_list *lst = get_list(ctx);
+ svr_key_item *node = NULL, *next = NULL;
+
+ HAL_MutexLock(lst->list_mutex);
+
+ list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
+ if (strcmp(node->keyInfo.keyprefix, keyprefix) == 0) {
+ coap_free(node->keyInfo.secret);
+ list_del(&node->lst);
+ coap_free(node);
+ --lst->svr_count;
+ break;
+ }
+ }
+ HAL_MutexUnlock(lst->list_mutex);
+
+ return COAP_SUCCESS;
+}
+
+int alcs_set_revocation(CoAPContext *ctx, const char *seqlist)
+{
+ auth_list *lst = get_list(ctx);
+ int len;
+
+ HAL_MutexLock(lst->list_mutex);
+
+ len = seqlist ? strlen(seqlist) : 0;
+ if (lst->revocation) {
+ coap_free(lst->revocation);
+ lst->revocation = NULL;
+ }
+
+ if (len > 0) {
+ lst->revocation = (char *)coap_malloc(len + 1);
+ strcpy(lst->revocation, seqlist);
+ }
+ HAL_MutexUnlock(lst->list_mutex);
+
+ return COAP_SUCCESS;
+}
+
+/* ----------------------------------------- */
+
+void send_err_rsp(CoAPContext *ctx, NetworkAddr *addr, int code, CoAPMessage *request)
+{
+ CoAPMessage sendMsg;
+ CoAPLenString payload = {0};
+ CoAPLenString token;
+ alcs_msg_init(ctx, &sendMsg, code, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
+ token.len = request->header.tokenlen;
+ token.data = request->token;
+ alcs_sendrsp(ctx, addr, &sendMsg, 1, request->header.msgid, &token);
+}
+
+void call_cb(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *message, const char *key,
+ char *buf, CoAPRecvMsgHandler cb)
+{
+ CoAPMessage tmpMsg;
+ memcpy(&tmpMsg, message, sizeof(CoAPMessage));
+
+ if (key && buf) {
+ int len = alcs_decrypt((const char *)message->payload, message->payloadlen, key, buf);
+ tmpMsg.payload = (unsigned char *)buf;
+ tmpMsg.payloadlen = len;
+#ifdef LOG_REPORT_TO_CLOUD
+ get_msgid(buf, 0);
+#endif
+ } else {
+ tmpMsg.payload = NULL;
+ tmpMsg.payloadlen = 0;
+ }
+
+ cb(context, path, remote, &tmpMsg);
+}
+
+static secure_resource_cb_item *get_resource_by_path(const char *path)
+{
+ secure_resource_cb_item *node, *next;
+ 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, &secure_resource_cb_head, lst, secure_resource_cb_item) {
+ if (node->path_type == PATH_NORMAL) {
+ if (memcmp(node->path, path_calc, MAX_PATH_CHECKSUM_LEN) == 0) {
+ return node;
+ }
+ } else if (strlen(node->filter_path) > 0) {
+ if (strncmp(node->filter_path, path, strlen(node->filter_path) - 1) == 0) {
+ return node;
+ }
+ }
+ }
+
+ COAP_ERR("receive unknown request, path:%s", path);
+ return NULL;
+}
+
+void recv_msg_handler(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *message)
+{
+ secure_resource_cb_item *node = get_resource_by_path(path);
+ struct list_head *sessions;
+ session_item *session;
+ unsigned int obsVal;
+
+ unsigned int sessionId = 0;
+ CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
+ COAP_DEBUG("recv_msg_handler, sessionID:%d", (int)sessionId);
+ if (!node) {
+ return;
+ }
+ sessions = get_svr_session_list(context);
+ session = get_session_by_checksum(sessions, remote, node->pk_dn);
+ if (!session || session->sessionId != sessionId) {
+ send_err_rsp(context, remote, COAP_MSG_CODE_401_UNAUTHORIZED, message);
+ COAP_ERR("need auth, path:%s, from:%s", path, remote->addr);
+ return;
+ }
+
+ if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) == COAP_SUCCESS) {
+ if (obsVal == 0) {
+ CoAPObsServer_add(context, path, remote, message);
+ }
+ }
+
+ if (message->payloadlen < 256) {
+ char buf[256];
+ call_cb(context, path, remote, message, session->sessionKey, buf, node->cb);
+ } else {
+ char *buf = (char *)coap_malloc(message->payloadlen);
+ if (buf) {
+ call_cb(context, path, remote, message, session->sessionKey, buf, node->cb);
+ coap_free(buf);
+ }
+ }
+}
+
+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)
+{
+ secure_resource_cb_item *node = NULL, *next_node = NULL;
+ char pk_dn[100] = {0};
+ int dup = 0;
+ secure_resource_cb_item *item;
+
+ COAP_INFO("alcs_resource_register_secure");
+ item = (secure_resource_cb_item *)coap_malloc(sizeof(secure_resource_cb_item));
+ if (item == NULL) {
+ return -1;
+ }
+ memset(item, 0, sizeof(secure_resource_cb_item));
+ item->cb = callback;
+ item->path_type = PATH_NORMAL;
+ if (strstr(path, "/#") != NULL) {
+ item->path_type = PATH_FILTER;
+ } else {
+ CoAPPathMD5_sum(path, strlen(path), item->path, MAX_PATH_CHECKSUM_LEN);
+ }
+ list_for_each_entry_safe(node, next_node, &secure_resource_cb_head, lst, secure_resource_cb_item) {
+ if (item->path_type == PATH_NORMAL && node->path_type == PATH_NORMAL) {
+ if (memcmp(node->path, item->path, MAX_PATH_CHECKSUM_LEN) == 0) {
+ dup = 1;
+ }
+ } else if (item->path_type == PATH_FILTER && node->path_type == PATH_FILTER) {
+ if (strncpy(node->filter_path, item->filter_path, strlen(item->filter_path)) == 0) {
+ dup = 1;
+ }
+ }
+ }
+ if (dup == 0) {
+ if (item->path_type == PATH_FILTER) {
+ item->filter_path = coap_malloc(strlen(path) + 1);
+ if (item->filter_path == NULL) {
+ coap_free(item);
+ return -1;
+ }
+ memset(item->filter_path, 0, strlen(path) + 1);
+ strncpy(item->filter_path, path, strlen(path));
+ }
+
+ strncpy(pk_dn, pk, sizeof(pk_dn) - 1);
+ strncat(pk_dn, dn, sizeof(pk_dn) - strlen(pk_dn) - 1);
+
+ CoAPPathMD5_sum(pk_dn, strlen(pk_dn), item->pk_dn, PK_DN_CHECKSUM_LEN);
+
+ list_add_tail(&item->lst, &secure_resource_cb_head);
+ } else {
+ coap_free(item);
+ }
+
+ return CoAPResource_register(context, path, permission, ctype, maxage, &recv_msg_handler);
+}
+
+void alcs_resource_cb_deinit(void)
+{
+ secure_resource_cb_item *del_item = NULL;
+
+ list_for_each_entry(del_item, &secure_resource_cb_head, lst, secure_resource_cb_item) {
+ list_del(&del_item->lst);
+ if (del_item->path_type == PATH_FILTER) {
+ coap_free(del_item->filter_path);
+ }
+ coap_free(del_item);
+ del_item = list_entry(&secure_resource_cb_head, secure_resource_cb_item, lst);
+ }
+}
+
+void alcs_auth_list_deinit(void)
+{
+ auth_list *auth_list_ctx = get_list(ctx);
+ svr_key_item *del_item = NULL, *next_item = NULL;
+
+ list_for_each_entry_safe(del_item, next_item, &auth_list_ctx->lst_svr, lst, svr_key_item) {
+ list_del(&del_item->lst);
+ if (del_item->keyInfo.secret) {
+ coap_free(del_item->keyInfo.secret);
+ }
+ coap_free(del_item);
+ }
+}
+
+void alcs_rec_heart_beat(CoAPContext *ctx, const char *path, NetworkAddr *remote, CoAPMessage *request)
+{
+ struct list_head *ctl_head = get_svr_session_list(ctx);
+ session_item *session = NULL;
+ session_item *node = NULL, *next = NULL;
+ int seqlen, datalen;
+ char *seq, *data;
+ CoAPMessage msg;
+ char databuf[32];
+ char payloadbuf[128];
+ CoAPLenString payload;
+
+ COAP_DEBUG("alcs_rec_heart_beat");
+ if (!ctl_head || list_empty(ctl_head)) {
+ return;
+ }
+
+ list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
+ if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
+ node->heart_time = HAL_UptimeMs();
+ session = node;
+ }
+ }
+
+ if (!session) {
+ COAP_INFO("receive stale heart beat");
+ }
+
+
+ if (!req_payload_parser((const char *)request->payload, request->payloadlen, &seq, &seqlen, &data, &datalen)) {
+ /* do nothing */
+ }
+
+ if (session) {
+ HAL_Snprintf(databuf, sizeof(databuf), "\"delayTime\":%d", default_heart_expire / 1000);
+ HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, 200, databuf);
+ } else {
+ HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, ALCS_HEART_FAILAUTH, "");
+ }
+
+ payload.data = (unsigned char *)payloadbuf;
+ payload.len = strlen(payloadbuf);
+ alcs_msg_init(ctx, &msg, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
+ if (session) {
+ msg.header.msgid = request->header.msgid;
+ msg.header.tokenlen = request->header.tokenlen;
+ memcpy(&msg.token, request->token, request->header.tokenlen);
+ internal_secure_send(ctx, session, remote, &msg, 1, NULL);
+ } else {
+ CoAPLenString token = {request->header.tokenlen, request->token};
+ alcs_sendrsp(ctx, remote, &msg, 1, request->header.msgid, &token);
+ }
+ alcs_msg_deinit(&msg);
+}
+
+int observe_data_encrypt(CoAPContext *ctx, const char *path, NetworkAddr *from, CoAPMessage *message,
+ CoAPLenString *src, CoAPLenString *dest)
+{
+ secure_resource_cb_item *node = get_resource_by_path(path);
+ struct list_head *sessions;
+ session_item *session;
+ COAP_DEBUG("observe_data_encrypt, src:%.*s", src->len, src->data);
+ if (!node) {
+ return COAP_ERROR_NOT_FOUND;
+ }
+
+ sessions = get_svr_session_list(ctx);
+ session = get_session_by_checksum(sessions, from, node->pk_dn);
+
+ if (session) {
+ dest->len = (src->len & 0xfffffff0) + 16;
+ dest->data = (unsigned char *)coap_malloc(dest->len);
+ alcs_encrypt((const char *)src->data, src->len, session->sessionKey, dest->data);
+ CoAPUintOption_add(message, COAP_OPTION_SESSIONID, session->sessionId);
+ return COAP_SUCCESS;
+ }
+
+ return COAP_ERROR_NOT_FOUND;
+}
+
+void on_svr_auth_timer(CoAPContext *ctx)
+{
+ struct list_head *head = get_svr_session_list(ctx);
+ int tick;
+ session_item *node = NULL, *next = NULL;
+
+ if (!head || list_empty(head)) {
+ return;
+ }
+ /* COAP_INFO ("on_svr_auth_timer:%d", (int)HAL_UptimeMs()); */
+
+ /* device_auth_list* dev = get_device (ctx); */
+ tick = HAL_UptimeMs();
+
+ list_for_each_entry_safe(node, next, head, lst, session_item) {
+ if (node->sessionId && node->heart_time + default_heart_expire < tick) {
+ COAP_ERR("heart beat timeout");
+ remove_session(ctx, node);
+ }
+ }
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dev_model_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dev_model_api.h
new file mode 100644
index 00000000..1c954c9b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dev_model_api.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOT_EXPORT_LINKKIT_H_
+#define _IOT_EXPORT_LINKKIT_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+typedef enum {
+ IOTX_LINKKIT_DEV_TYPE_MASTER,
+ IOTX_LINKKIT_DEV_TYPE_SLAVE,
+ IOTX_LINKKIT_DEV_TYPE_MAX
+} iotx_linkkit_dev_type_t;
+
+typedef struct {
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char product_secret[IOTX_PRODUCT_SECRET_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
+} iotx_linkkit_dev_meta_info_t;
+
+typedef enum {
+ /* post property value to cloud */
+ ITM_MSG_POST_PROPERTY,
+
+ /* post device info update message to cloud */
+ ITM_MSG_DEVICEINFO_UPDATE,
+
+ /* post device info delete message to cloud */
+ ITM_MSG_DEVICEINFO_DELETE,
+
+ /* post raw data to cloud */
+ ITM_MSG_POST_RAW_DATA,
+
+ /* only for slave device, send login request to cloud */
+ ITM_MSG_LOGIN,
+
+ /* only for slave device, send logout request to cloud */
+ ITM_MSG_LOGOUT,
+
+ /* only for slave device, send delete topo request to cloud */
+ ITM_MSG_DELETE_TOPO,
+
+ /* query ntp time from cloud */
+ ITM_MSG_QUERY_TIMESTAMP,
+
+ /* only for master device, query topo list */
+ ITM_MSG_QUERY_TOPOLIST,
+
+ /* only for master device, qurey firmware ota data */
+ ITM_MSG_QUERY_FOTA_DATA,
+
+ /* only for master device, qurey config ota data */
+ ITM_MSG_QUERY_COTA_DATA,
+
+ /* only for master device, request config ota data from cloud */
+ ITM_MSG_REQUEST_COTA,
+
+ /* only for master device, request fota image from cloud */
+ ITM_MSG_REQUEST_FOTA_IMAGE,
+
+ /* report subdev's firmware version */
+ ITM_MSG_REPORT_SUBDEV_FIRMWARE_VERSION,
+
+ /* get a device's desired property */
+ ITM_MSG_PROPERTY_DESIRED_GET,
+
+ /* delete a device's desired property */
+ ITM_MSG_PROPERTY_DESIRED_DELETE,
+
+ IOTX_LINKKIT_MSG_MAX
+} iotx_linkkit_msg_type_t;
+
+/**
+ * @brief create a new device
+ *
+ * @param dev_type. type of device which will be created. see iotx_linkkit_dev_type_t
+ * @param meta_info. The product key, product secret, device name and device secret of new device.
+ *
+ * @return success: device id (>=0), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info);
+
+/**
+ * @brief start device network connection.
+ * for master device, start to connect aliyun server.
+ * for slave device, send message to cloud for register new device and add topo with master device
+ *
+ * @param devid. device identifier.
+ *
+ * @return success: device id (>=0), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Connect(int devid);
+
+/**
+ * @brief try to receive message from cloud and dispatch these message to user event callback
+ *
+ * @param timeout_ms. timeout for waiting new message arrived
+ *
+ * @return void.
+ *
+ */
+DLL_IOT_API void IOT_Linkkit_Yield(int timeout_ms);
+
+/**
+ * @brief close device network connection and release resources.
+ * for master device, disconnect with aliyun server and release all local resources.
+ * for slave device, send message to cloud for delete topo with master device and unregister itself, then release device's resources.
+ *
+ * @param devid. device identifier.
+ *
+ * @return success: 0, fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Close(int devid);
+
+/**
+ * @brief Report message to cloud
+ *
+ * @param devid. device identifier.
+ * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
+ * ITM_MSG_POST_PROPERTY
+ * ITM_MSG_DEVICEINFO_UPDATE
+ * ITM_MSG_DEVICEINFO_DELETE
+ * ITM_MSG_POST_RAW_DATA
+ * ITM_MSG_LOGIN
+ * ITM_MSG_LOGOUT
+ *
+ * @param payload. message payload.
+ * @param payload_len. message payload length.
+ *
+ * @return success: 0 or message id (>=1), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
+ int payload_len);
+
+/**
+ * @brief post message to cloud
+ *
+ * @param devid. device identifier.
+ * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
+ * ITM_MSG_QUERY_TIMESTAMP
+ * ITM_MSG_QUERY_TOPOLIST
+ * ITM_MSG_QUERY_FOTA_DATA
+ * ITM_MSG_QUERY_COTA_DATA
+ * ITM_MSG_REQUEST_COTA
+ * ITM_MSG_REQUEST_FOTA_IMAGE
+ *
+ * @param payload. message payload.
+ * @param payload_len. message payload length.
+ *
+ * @return success: 0 or message id (>=1), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
+ int payload_len);
+
+/**
+ * @brief post event to cloud
+ *
+ * @param devid. device identifier.
+ * @param eventid. tsl event id.
+ * @param eventid_len. length of tsl event id.
+ * @param payload. event payload.
+ * @param payload_len. event payload length.
+ *
+ * @return success: message id (>=1), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_api.c
new file mode 100644
index 00000000..60f256e1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_api.c
@@ -0,0 +1,2070 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include "iotx_dm_internal.h"
+
+static dm_api_ctx_t g_dm_api_ctx;
+
+static dm_api_ctx_t *_dm_api_get_ctx(void)
+{
+ return &g_dm_api_ctx;
+}
+
+static void _dm_api_lock(void)
+{
+ dm_api_ctx_t *ctx = _dm_api_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexLock(ctx->mutex);
+ }
+}
+
+static void _dm_api_unlock(void)
+{
+ dm_api_ctx_t *ctx = _dm_api_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexUnlock(ctx->mutex);
+ }
+}
+
+int iotx_dm_open(void)
+{
+ int res = 0;
+ dm_api_ctx_t *ctx = _dm_api_get_ctx();
+#if defined(ALCS_ENABLED) || defined(DEPRECATED_LINKKIT)
+ lite_cjson_hooks hooks;
+#endif
+ memset(ctx, 0, sizeof(dm_api_ctx_t));
+
+#if defined(ALCS_ENABLED) || defined(DEPRECATED_LINKKIT)
+ /* lite-cjson Hooks Init */
+ hooks.malloc_fn = dm_utils_malloc;
+ hooks.free_fn = dm_utils_free;
+ lite_cjson_init_hooks(&hooks);
+#endif
+
+ /* DM Mutex Create*/
+ ctx->mutex = HAL_MutexCreate();
+ if (ctx->mutex == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ /* DM OTA Module Init */
+ res = dm_ota_init();
+ if (res != SUCCESS_RETURN) {
+ goto ERROR;
+ }
+#endif
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ /* DM Message Cache Init */
+ res = dm_msg_cache_init();
+ if (res != SUCCESS_RETURN) {
+ goto ERROR;
+ }
+#endif
+ /* DM Cloud Message Parse And Assemble Module Init */
+ res = dm_msg_init();
+ if (res != SUCCESS_RETURN) {
+ goto ERROR;
+ }
+
+ /* DM IPC Module Init */
+ res = dm_ipc_init(CONFIG_DISPATCH_QUEUE_MAXLEN);
+ if (res != SUCCESS_RETURN) {
+ goto ERROR;
+ }
+
+ /* DM Manager Module Init */
+ res = dm_mgr_init();
+ if (res != SUCCESS_RETURN) {
+ goto ERROR;
+ }
+
+#ifdef ALCS_ENABLED
+ /* Open Local Connection */
+ res = dm_server_open();
+ if (res < SUCCESS_RETURN) {
+ goto ERROR;
+ }
+#endif
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ /* DM OTA Module Init */
+ res = dm_ota_sub();
+ if (res == SUCCESS_RETURN) {
+ /* DM Config OTA Module Init */
+ dm_cota_init();
+
+ /* DM Firmware OTA Mudule Init */
+ dm_fota_init();
+ }
+#endif
+
+ /* Open Cloud Connection */
+ res = dm_client_open();
+ if (res < SUCCESS_RETURN) {
+ goto ERROR;
+ }
+
+ return SUCCESS_RETURN;
+
+ERROR:
+ dm_client_close();
+#ifdef ALCS_ENABLED
+ dm_server_close();
+#endif
+ dm_mgr_deinit();
+ dm_ipc_deinit();
+ dm_msg_deinit();
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_deinit();
+#endif
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ dm_ota_deinit();
+#endif
+
+ if (ctx->mutex) {
+ HAL_MutexDestroy(ctx->mutex);
+ }
+ return FAIL_RETURN;
+}
+
+int iotx_dm_connect(_IN_ iotx_dm_init_params_t *init_params)
+{
+ int res = 0;
+ dm_api_ctx_t *ctx = _dm_api_get_ctx();
+
+ if (init_params == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* DM Event Callback */
+ if (init_params->event_callback != NULL) {
+ ctx->event_callback = init_params->event_callback;
+ }
+
+ res = dm_client_connect(IOTX_DM_CLIENT_CONNECT_TIMEOUT_MS);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+#ifdef ALCS_ENABLED
+ /* DM Connect Local */
+ res = dm_server_connect();
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_subscribe(_IN_ int devid)
+{
+ int res = 0, dev_type = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_by_devid(devid, product_key, device_name, device_secret);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return res;
+ }
+
+ res = dm_mgr_get_dev_type(devid, &dev_type);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return res;
+ }
+
+#ifdef ALCS_ENABLED
+ if (devid > 0) {
+ dm_server_add_device(product_key, device_name);
+ }
+
+ res = dm_server_subscribe_all(product_key, device_name);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return res;
+ }
+#endif
+
+ res = dm_client_subscribe_all(product_key, device_name, dev_type);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return res;
+ }
+
+ _dm_api_unlock();
+ dm_log_info("Devid %d Sub Completed", devid);
+
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_close(void)
+{
+ dm_api_ctx_t *ctx = _dm_api_get_ctx();
+
+ dm_client_close();
+#ifdef ALCS_ENABLED
+ dm_server_close();
+#endif
+ dm_mgr_deinit();
+ dm_ipc_deinit();
+ dm_msg_deinit();
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_deinit();
+#endif
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ dm_cota_deinit();
+ dm_fota_deinit();
+ dm_ota_deinit();
+#endif
+
+ if (ctx->mutex) {
+ HAL_MutexDestroy(ctx->mutex);
+ }
+
+#ifdef LOG_REPORT_TO_CLOUD
+ remove_log_poll();
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_yield(int timeout_ms)
+{
+ if (timeout_ms <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ dm_client_yield(timeout_ms);
+#ifdef ALCS_ENABLED
+ dm_server_yield();
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+void iotx_dm_dispatch(void)
+{
+ int count = 0;
+ void *data = NULL;
+ dm_api_ctx_t *ctx = _dm_api_get_ctx();
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_tick();
+#endif
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ dm_cota_status_check();
+ dm_fota_status_check();
+#endif
+ while (CONFIG_DISPATCH_QUEUE_MAXLEN == 0 || count++ < CONFIG_DISPATCH_QUEUE_MAXLEN) {
+ if (dm_ipc_msg_next(&data) == SUCCESS_RETURN) {
+ dm_ipc_msg_t *msg = (dm_ipc_msg_t *)data;
+
+ if (ctx->event_callback) {
+ ctx->event_callback(msg->type, msg->data);
+ }
+
+ if (msg->data) {
+ DM_free(msg->data);
+ }
+ DM_free(msg);
+ data = NULL;
+ } else {
+ break;
+ }
+ }
+}
+
+int iotx_dm_post_rawdata(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_model_up_raw(devid, payload, payload_len);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+int iotx_dm_set_opt(int opt, void *data)
+{
+ return dm_opt_set(opt, data);
+}
+
+int iotx_dm_get_opt(int opt, void *data)
+{
+ if (data == NULL) {
+ return FAIL_RETURN;
+ }
+
+ return dm_opt_get(opt, data);
+}
+#ifdef DEVICE_MODEL_SHADOW
+int iotx_dm_property_desired_get(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_property_desired_get(devid, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_property_desired_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_property_desired_delete(devid, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+#endif
+
+int iotx_dm_post_property(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_property_post(devid, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+#ifdef LOG_REPORT_TO_CLOUD
+int iotx_dm_log_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_log_post(devid, payload, payload_len, 0);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+#endif
+
+
+int iotx_dm_post_event(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload,
+ _IN_ int payload_len)
+{
+ int res = 0, method_len = 0;
+ const char *method_fmt = "thing.event.%.*s.post";
+ char *method = NULL;
+
+ if (devid < 0 || identifier == NULL || identifier_len == 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ method_len = strlen(method_fmt) + strlen(identifier) + 1;
+ method = DM_malloc(method_len);
+ if (method == NULL) {
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(method, 0, method_len);
+ HAL_Snprintf(method, method_len, method_fmt, identifier_len, identifier);
+
+ res = dm_mgr_upstream_thing_event_post(devid, identifier, identifier_len, method, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ DM_free(method);
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ DM_free(method);
+ _dm_api_unlock();
+ return res;
+}
+
+
+int iotx_dm_send_service_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier,
+ _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len, void *ctx)
+{
+ int res = 0;
+
+ if (devid < 0 || msgid == NULL || msgid_len <= 0 || identifier == NULL || identifier_len <= 0 || payload == NULL
+ || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ dm_log_debug("Current Service Response Payload, Length: %d, Payload: %.*s", payload_len, payload_len, payload);
+
+ res = dm_mgr_upstream_thing_service_response(devid, msgid, msgid_len, code, identifier, identifier_len, payload,
+ payload_len, ctx);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_send_property_get_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ iotx_dm_error_code_t code, _IN_ char *payload, _IN_ int payload_len, void *ctx)
+{
+ int res = 0;
+
+ if (devid < 0 || msgid == NULL || msgid_len <= 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ dm_log_debug("Current Property Get Response Payload, Length: %d, Payload: %.*s", payload_len, payload_len, payload);
+
+ res = dm_mgr_upstream_thing_property_get_response(devid, msgid, msgid_len, code, payload,
+ payload_len, ctx);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_deviceinfo_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_deviceinfo_update(devid, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_deviceinfo_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_deviceinfo_delete(devid, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_qurey_ntp(void)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_ntp_request();
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_send_aos_active(int devid)
+{
+ int active_param_len;
+ int i;
+ char *active_param;
+ char aos_active_data[AOS_ACTIVE_INFO_LEN];
+ char subdev_aos_verson[VERSION_NUM_SIZE] = {0};
+ char subdev_mac_num[MAC_ADDRESS_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, ACTIVE_SUBDEV, ACTIVE_LINKKIT_OTHERS};
+ char subdev_chip_code[CHIP_CODE_SIZE] = {0x01, 0x02, 0x03, 0x04};
+ char random_num[RANDOM_NUM_SIZE];
+ const char *fmt =
+ "[{\"attrKey\":\"SYS_ALIOS_ACTIVATION\",\"attrValue\":\"%s\",\"domain\":\"SYSTEM\"}]";
+
+ aos_get_version_hex((unsigned char *)subdev_aos_verson);
+
+ HAL_Srandom(HAL_UptimeMs());
+ for (i = 0; i < 4; i ++) {
+ random_num[i] = (char)HAL_Random(0xFF);
+ }
+ aos_get_version_info((unsigned char *)subdev_aos_verson, (unsigned char *)random_num, (unsigned char *)subdev_mac_num,
+ (unsigned char *)subdev_chip_code, (unsigned char *)aos_active_data, AOS_ACTIVE_INFO_LEN);
+ memcpy(aos_active_data + 40, "1111111111222222222233333333334444444444", 40);
+
+ active_param_len = strlen(fmt) + strlen(aos_active_data) + 1;
+ active_param = DM_malloc(active_param_len);
+ if (active_param == NULL) {
+ return FAIL_RETURN;
+ }
+ HAL_Snprintf(active_param, active_param_len, fmt, aos_active_data);
+ iotx_dm_deviceinfo_update(devid, active_param, active_param_len);
+ DM_free(active_param);
+
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_send_rrpc_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *rrpcid, _IN_ int rrpcid_len, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ if (devid < 0 || msgid == NULL || msgid_len <= 0 || rrpcid == NULL || rrpcid_len <= 0 || payload == NULL
+ || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_rrpc_response(devid, msgid, msgid_len, code, rrpcid, rrpcid_len, payload, payload_len);
+
+ _dm_api_unlock();
+ return res;
+}
+#endif
+
+int iotx_dm_cota_perform_sync(_OU_ char *buffer, _IN_ int buffer_len)
+{
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ return dm_cota_perform_sync(buffer, buffer_len);
+#else
+ return -1;
+#endif
+}
+
+int iotx_dm_cota_get_config(_IN_ const char *config_scope, const char *get_type, const char *attribute_keys)
+{
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ return dm_cota_get_config(config_scope, get_type, attribute_keys);
+#else
+ return -1;
+#endif
+}
+
+int iotx_dm_fota_perform_sync(_OU_ char *buffer, _IN_ int buffer_len)
+{
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ return dm_fota_perform_sync(buffer, buffer_len);
+#else
+ return -1;
+#endif
+}
+
+int iotx_dm_fota_request_image(const char *version, int buffer_len)
+{
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ return dm_fota_request_image(version, buffer_len);
+#else
+ return -1;
+#endif
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+int iotx_dm_query_topo_list(void)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_topo_get();
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_subdev_create(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ int *devid)
+{
+ int res = 0;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ devid == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (device_secret != NULL && strlen(device_secret) >= IOTX_DEVICE_SECRET_LEN + 1) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_device_create(IOTX_DM_DEVICE_SUBDEV, product_key, device_name, device_secret, devid);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_subdev_destroy(_IN_ int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_device_destroy(devid);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_subdev_number(void)
+{
+ int number = 0;
+
+ _dm_api_lock();
+ number = dm_mgr_device_number();
+ _dm_api_unlock();
+
+ return number;
+}
+
+int iotx_dm_subdev_register(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_node_by_devid(devid, (void **)&search_node);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ if ((strlen(search_node->device_secret) > 0) && (strlen(search_node->device_secret) < IOTX_DEVICE_SECRET_LEN + 1)) {
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+ }
+
+ res = dm_mgr_upstream_thing_sub_register(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_subdev_unregister(_IN_ int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_sub_unregister(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_subdev_topo_add(_IN_ int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_topo_add(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_subdev_topo_del(_IN_ int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_thing_topo_delete(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_subdev_login(_IN_ int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_combine_login(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_subdev_logout(_IN_ int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_upstream_combine_logout(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_get_device_type(_IN_ int devid, _OU_ int *type)
+{
+ int res = 0;
+
+ if (devid < 0 || type == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_get_dev_type(devid, type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_get_device_avail_status(_IN_ int devid, _OU_ iotx_dm_dev_avail_t *status)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+
+ if (devid < 0 || status == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_by_devid(devid, product_key, device_name, device_secret);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_get_dev_avail(product_key, device_name, status);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_get_device_status(_IN_ int devid, _OU_ iotx_dm_dev_status_t *status)
+{
+ int res = 0;
+
+ if (devid < 0 || status == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_get_dev_status(devid, status);
+ _dm_api_unlock();
+
+ return res;
+}
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+int iotx_dm_firmware_version_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_upstream_thing_firmware_version_update(devid, payload, payload_len);
+ if (res < SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_send_firmware_version(int devid, const char *version)
+{
+ char msg[FIRMWARE_VERSION_MSG_LEN] = {0};
+ int msg_len = 0;
+ /* firmware report message json data generate */
+ int ret = HAL_Snprintf(msg,
+ FIRMWARE_VERSION_MSG_LEN,
+ "{\"id\":\"%d\",\"params\":{\"version\":\"%s\"}}",
+ iotx_report_id(),
+ version
+ );
+ if (ret <= 0) {
+ printf("firmware report message json data generate err");
+ return FAIL_RETURN;
+ }
+
+ msg_len = strlen(msg);
+
+ ret = iotx_dm_firmware_version_update(devid, msg, msg_len);
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_ota_switch_device(_IN_ int devid)
+{
+ return dm_ota_switch_device(devid);
+}
+#endif
+#endif
+
+#ifdef DEPRECATED_LINKKIT
+int iotx_dm_deprecated_set_tsl(_IN_ int devid, _IN_ iotx_dm_tsl_source_t source, _IN_ const char *tsl, _IN_ int tsl_len)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ if (source == IOTX_DM_TSL_SOURCE_CLOUD) {
+ res = dm_mgr_upstream_thing_dynamictsl_get(devid);
+
+ _dm_api_unlock();
+ return res;
+ }
+
+ if (source == IOTX_DM_TSL_SOURCE_LOCAL) {
+ if (tsl == NULL || tsl_len <= 0) {
+ _dm_api_unlock();
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_deprecated_set_tsl(devid, IOTX_DM_TSL_TYPE_ALINK, tsl, tsl_len);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+ }
+
+ _dm_api_unlock();
+ return FAIL_RETURN;
+}
+
+int iotx_dm_deprecated_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_set_property_value(devid, key, key_len, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_property_value(devid, key, key_len, value);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_set_event_output_value(devid, key, key_len, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_event_output_value(devid, key, key_len, value);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_service_input_value(devid, key, key_len, value);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_set_service_output_value(devid, key, key_len, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_service_output_value(devid, key, key_len, value);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_post_property_start(_IN_ int devid, _OU_ void **handle)
+{
+ dm_api_property_t *dapi_property = NULL;
+
+ if (devid < 0 || handle == NULL || *handle != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ dapi_property = DM_malloc(sizeof(dm_api_property_t));
+ if (dapi_property == NULL) {
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(dapi_property, 0, sizeof(dm_api_property_t));
+
+
+ /* Create Mutex */
+ dapi_property->mutex = HAL_MutexCreate();
+ if (dapi_property->mutex == NULL) {
+ DM_free(dapi_property);
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ /* Set Devid */
+ dapi_property->devid = devid;
+
+ /* Init Json Object */
+ dapi_property->lite = lite_cjson_create_object();
+ if (dapi_property->lite == NULL) {
+ DM_free(dapi_property->mutex);
+ DM_free(dapi_property);
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ *handle = (void *)dapi_property;
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+static int _iotx_dm_deprecated_post_property_add(_IN_ void *handle, _IN_ char *identifier, _IN_ int identifier_len)
+{
+ int res = 0;
+ dm_api_property_t *dapi_property = NULL;
+
+ if (handle == NULL || identifier == NULL || identifier_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+ dapi_property = (dm_api_property_t *)handle;
+
+ /* Assemble Property Payload */
+ res = dm_mgr_deprecated_assemble_property(dapi_property->devid, identifier, identifier_len, dapi_property->lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_post_property_add(_IN_ void *handle, _IN_ char *identifier, _IN_ int identifier_len)
+{
+ int ret = SUCCESS_RETURN, res = 0, index = 0, number = 0;
+ void *property_refer = NULL;
+ char *identifier_refer = NULL;
+ dm_api_property_t *dapi_property = NULL;
+
+ if (handle == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ dapi_property = (dm_api_property_t *)handle;
+
+ if (identifier != IOTX_DM_POST_PROPERTY_ALL) {
+ if (identifier_len <= 0) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+ ret = _iotx_dm_deprecated_post_property_add(handle, identifier, identifier_len);
+
+ _dm_api_unlock();
+ return ret;
+ }
+
+ res = dm_mgr_deprecated_get_property_number(dapi_property->devid, &number);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ for (index = 0; index < number; index++) {
+ property_refer = NULL;
+ identifier_refer = NULL;
+
+ res = dm_mgr_deprecated_get_property_by_index(dapi_property->devid, index, &property_refer);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ res = dm_mgr_deprecated_get_property_identifier(property_refer, &identifier_refer);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ res = _iotx_dm_deprecated_post_property_add(handle, identifier_refer, strlen(identifier_refer));
+ if (res != SUCCESS_RETURN) {
+ ret = FAIL_RETURN;
+ }
+ }
+
+ _dm_api_unlock();
+ return ret;
+}
+
+int iotx_dm_deprecated_post_property_end(_IN_ void **handle)
+{
+ int res = 0;
+ char *payload = NULL;
+ dm_api_property_t *dapi_property = NULL;
+
+ if (handle == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ dapi_property = *((dm_api_property_t **)handle);
+
+ payload = lite_cjson_print_unformatted(dapi_property->lite);
+ if (payload == NULL) {
+ lite_cjson_delete(dapi_property->lite);
+ if (dapi_property->mutex) {
+ HAL_MutexDestroy(dapi_property->mutex);
+ }
+ DM_free(dapi_property);
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ dm_log_debug("Current Property Post Payload, Length: %d, Payload: %s", strlen(payload), payload);
+
+ res = dm_mgr_upstream_thing_property_post(dapi_property->devid, payload, strlen(payload));
+
+ DM_free(payload);
+ lite_cjson_delete(dapi_property->lite);
+ if (dapi_property->mutex) {
+ HAL_MutexDestroy(dapi_property->mutex);
+ }
+ DM_free(dapi_property);
+ *handle = NULL;
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_deprecated_post_event(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len)
+{
+ int res = 0;
+ void *event = NULL;
+ lite_cjson_item_t *lite = NULL;
+ char *method = NULL, *payload = NULL;
+
+ if (devid < 0 || identifier == NULL || identifier_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ lite = lite_cjson_create_object();
+ if (lite == NULL) {
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ res = dm_mgr_deprecated_assemble_event_output(devid, identifier, identifier_len, lite);
+ if (res != SUCCESS_RETURN) {
+ lite_cjson_delete(lite);
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ payload = lite_cjson_print_unformatted(lite);
+ lite_cjson_delete(lite);
+ if (payload == NULL) {
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ dm_log_debug("Current Event Post Payload, Length: %d, Payload: %s", strlen(payload), payload);
+
+ res = dm_mgr_deprecated_get_event_by_identifier(devid, identifier, &event);
+ if (res != SUCCESS_RETURN) {
+ DM_free(payload);
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_event_method(event, &method);
+ if (res != SUCCESS_RETURN) {
+ DM_free(payload);
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Current Event Method: %s", method);
+
+ res = dm_mgr_upstream_thing_event_post(devid, identifier, identifier_len, method, payload, strlen(payload));
+
+ DM_free(payload);
+ DM_free(method);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_deprecated_legacy_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char *value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_property_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = (value == NULL) ? (atoi(value_str)) : (*(int *)value);
+ res = dm_mgr_deprecated_set_property_value(devid, key, key_len, &value_int, sizeof(int));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = (value == NULL) ? (atof(value_str)) : (*(float *)value);
+ res = dm_mgr_deprecated_set_property_value(devid, key, key_len, &value_float, sizeof(float));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = (value == NULL) ? (atof(value_str)) : (*(double *)value);
+ res = dm_mgr_deprecated_set_property_value(devid, key, key_len, &value_double, sizeof(double));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = (value == NULL) ? (value_str) : (value);
+ res = dm_mgr_deprecated_set_property_value(devid, key, key_len, value_string, strlen(value_string));
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char **value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_property_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = 0;
+ res = dm_mgr_deprecated_get_property_value(devid, key, key_len, (void *)&value_int);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(int *)value = value_int;
+ }
+ if (value_str) {
+ res = dm_utils_itoa_direct(value_int, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = 0;
+ res = dm_mgr_deprecated_get_property_value(devid, key, key_len, (void *)&value_float);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(float *)value = value_float;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_float, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = 0;
+ res = dm_mgr_deprecated_get_property_value(devid, key, key_len, (void *)&value_double);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(double *)value = value_double;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_double, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = NULL;
+ res = dm_mgr_deprecated_get_property_value(devid, key, key_len, (void *)&value_string);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ memcpy(value, value_string, strlen(value_string));
+ }
+ if (value_str) {
+ *value_str = value_string;
+ } else {
+ HAL_Free(value_string);
+ }
+ }
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char *value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_event_output_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = (value == NULL) ? (atoi(value_str)) : (*(int *)value);
+ res = dm_mgr_deprecated_set_event_output_value(devid, key, key_len, &value_int, sizeof(int));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = (value == NULL) ? (atof(value_str)) : (*(float *)value);
+ res = dm_mgr_deprecated_set_event_output_value(devid, key, key_len, &value_float, sizeof(float));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = (value == NULL) ? (atof(value_str)) : (*(double *)value);
+ res = dm_mgr_deprecated_set_event_output_value(devid, key, key_len, &value_double, sizeof(double));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = (value == NULL) ? (value_str) : (value);
+ res = dm_mgr_deprecated_set_event_output_value(devid, key, key_len, value_string, strlen(value_string));
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char **value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_event_output_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = 0;
+ res = dm_mgr_deprecated_get_event_output_value(devid, key, key_len, (void *)&value_int);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(int *)value = value_int;
+ }
+ if (value_str) {
+ res = dm_utils_itoa_direct(value_int, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = 0;
+ res = dm_mgr_deprecated_get_event_output_value(devid, key, key_len, (void *)&value_float);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(float *)value = value_float;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_float, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = 0;
+ res = dm_mgr_deprecated_get_event_output_value(devid, key, key_len, (void *)&value_double);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(double *)value = value_double;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_double, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = NULL;
+ res = dm_mgr_deprecated_get_event_output_value(devid, key, key_len, (void *)&value_string);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ memcpy(value, value_string, strlen(value_string));
+ }
+ if (value_str) {
+ *value_str = value_string;
+ } else {
+ HAL_Free(value_string);
+ }
+ }
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
+ _IN_ void *value,
+ _IN_ char **value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_deprecated_get_service_input_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = 0;
+ res = dm_mgr_deprecated_get_service_input_value(devid, key, key_len, (void *)&value_int);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(int *)value = value_int;
+ }
+ if (value_str) {
+ res = dm_utils_itoa_direct(value_int, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = 0;
+ res = dm_mgr_deprecated_get_service_input_value(devid, key, key_len, (void *)&value_float);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(float *)value = value_float;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_float, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = 0;
+ res = dm_mgr_deprecated_get_service_input_value(devid, key, key_len, (void *)&value_double);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(double *)value = value_double;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_double, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = NULL;
+ res = dm_mgr_deprecated_get_service_input_value(devid, key, key_len, (void *)&value_string);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ memcpy(value, value_string, strlen(value_string));
+ }
+ if (value_str) {
+ *value_str = value_string;
+ } else {
+ HAL_Free(value_string);
+ }
+ }
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
+ _IN_ void *value,
+ _IN_ char *value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_get_service_output_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = (value == NULL) ? (atoi(value_str)) : (*(int *)value);
+ res = dm_mgr_deprecated_set_service_output_value(devid, key, key_len, &value_int, sizeof(int));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = (value == NULL) ? (atof(value_str)) : (*(float *)value);
+ res = dm_mgr_deprecated_set_service_output_value(devid, key, key_len, &value_float, sizeof(float));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = (value == NULL) ? (atof(value_str)) : (*(double *)value);
+ res = dm_mgr_deprecated_set_service_output_value(devid, key, key_len, &value_double, sizeof(double));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = (value == NULL) ? (value_str) : (value);
+ res = dm_mgr_deprecated_set_service_output_value(devid, key, key_len, value_string, strlen(value_string));
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
+ _IN_ void *value,
+ _IN_ char **value_str)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e type;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || ((value == NULL) && (value_str == NULL))) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+
+ res = dm_mgr_deprecated_get_service_output_data(devid, key, key_len, &data);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &type);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ int value_int = 0;
+ res = dm_mgr_deprecated_get_service_output_value(devid, key, key_len, (void *)&value_int);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(int *)value = value_int;
+ }
+ if (value_str) {
+ res = dm_utils_itoa_direct(value_int, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = 0;
+ res = dm_mgr_deprecated_get_service_output_value(devid, key, key_len, (void *)&value_float);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(float *)value = value_float;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_float, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value_double = 0;
+ res = dm_mgr_deprecated_get_service_output_value(devid, key, key_len, (void *)&value_double);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ *(double *)value = value_double;
+ }
+ if (value_str) {
+ res = dm_utils_ftoa_direct(value_double, value_str);
+ }
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value_string = NULL;
+ res = dm_mgr_deprecated_get_service_output_value(devid, key, key_len, (void *)&value_string);
+ if (res == SUCCESS_RETURN) {
+ if (value) {
+ memcpy(value, value_string, strlen(value_string));
+ }
+ if (value_str) {
+ *value_str = value_string;
+ } else {
+ HAL_Free(value_string);
+ }
+ }
+ }
+ break;
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_pkdn_by_devid(_IN_ int devid, _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0;
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+
+ if (devid < 0 || product_key == NULL || device_name == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_by_devid(devid, product_key, device_name, device_secret);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_devid_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ int *devid)
+{
+ int res = 0;
+
+ if (devid == NULL || product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, devid);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_thingid_by_devid(_IN_ int devid, _OU_ void **thing_id)
+{
+ int res = 0;
+
+ if (devid < 0 || thing_id == NULL || *thing_id != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_node_by_devid(devid, thing_id);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_devid_by_thingid(_IN_ void *thing_id, _OU_ int *devid)
+{
+ int res = 0;
+
+ if (thing_id == NULL || devid == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_deprecated_search_devid_by_device_node(thing_id, devid);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_get_pkdn_ptr_by_devid(_IN_ int devid, _OU_ char **product_key, _OU_ char **device_name)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || product_key == NULL || *product_key != NULL ||
+ device_name == NULL || *device_name != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ res = dm_mgr_search_device_node_by_devid(devid, (void **)&node);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ *product_key = node->product_key;
+ *device_name = node->device_name;
+
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+}
+
+int iotx_dm_deprecated_legacy_send_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+
+ _dm_api_lock();
+
+ res = dm_mgr_deprecated_upstream_thing_service_response(devid, msgid, code, identifier, identifier_len, payload,
+ payload_len);
+
+ _dm_api_unlock();
+ return res;
+}
+
+int iotx_dm_deprecated_send_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier,
+ _IN_ int identifier_len)
+{
+ int res = 0;
+ lite_cjson_item_t *lite = NULL;
+ char *payload = NULL;
+
+ if (devid < 0 || msgid < 0 || identifier == NULL || identifier_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ lite = lite_cjson_create_object();
+ if (lite == NULL) {
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ res = dm_mgr_deprecated_assemble_service_output(devid, identifier, identifier_len, lite);
+ if (res != SUCCESS_RETURN) {
+ lite_cjson_delete(lite);
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+
+ payload = lite_cjson_print_unformatted(lite);
+ lite_cjson_delete(lite);
+ if (payload == NULL) {
+ _dm_api_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ dm_log_debug("Current Service Response Payload, Length: %d, Payload: %s", strlen(payload), payload);
+
+ res = dm_mgr_deprecated_upstream_thing_service_response(devid, msgid, code, identifier, identifier_len, payload,
+ strlen(payload));
+
+ DM_free(payload);
+
+ _dm_api_unlock();
+ return res;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+int iotx_dm_deprecated_subdev_register(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1])
+{
+ int res = 0;
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_api_lock();
+ if ((device_secret != NULL) && (strlen(device_secret) > 0) && (strlen(device_secret) < IOTX_DEVICE_SECRET_LEN + 1)) {
+ res = dm_mgr_search_device_node_by_devid(devid, (void **)&search_node);
+ if (res != SUCCESS_RETURN) {
+ _dm_api_unlock();
+ return FAIL_RETURN;
+ }
+ memset(search_node->device_secret, 0, IOTX_DEVICE_SECRET_LEN + 1);
+ memcpy(search_node->device_secret, device_secret, strlen(device_secret));
+ _dm_api_unlock();
+ return SUCCESS_RETURN;
+ }
+
+ res = dm_mgr_upstream_thing_sub_register(devid);
+
+ _dm_api_unlock();
+ return res;
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client.c
new file mode 100644
index 00000000..45b71091
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client.c
@@ -0,0 +1,738 @@
+#include "iotx_dm_internal.h"
+
+#ifdef DEV_BIND_ENABLED
+ #include "dev_bind_api.h"
+#endif
+#ifdef LOG_REPORT_TO_CLOUD
+ #include "iotx_log_report.h"
+#endif
+
+static dm_client_uri_map_t g_dm_client_uri_map[] = {
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ {DM_URI_THING_EVENT_POST_REPLY_WILDCARD, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_event_post_reply },
+#ifdef DEVICE_MODEL_SHADOW
+ {DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_property_desired_delete_reply},
+ {DM_URI_THING_PROPERTY_DESIRED_GET_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_property_desired_get_reply },
+ {DM_URI_THING_SERVICE_PROPERTY_GET, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_service_property_get },
+#endif
+ {DM_URI_THING_SERVICE_PROPERTY_SET, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_service_property_set },
+ {DM_URI_THING_SERVICE_REQUEST_WILDCARD, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_service_request },
+ {DM_URI_THING_DEVICEINFO_UPDATE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_deviceinfo_update_reply },
+ {DM_URI_THING_DEVICEINFO_DELETE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_deviceinfo_delete_reply },
+ {DM_URI_THING_DYNAMICTSL_GET_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_dynamictsl_get_reply },
+ {DM_URI_RRPC_REQUEST_WILDCARD, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_rrpc_request_wildcard },
+ {DM_URI_NTP_RESPONSE, DM_URI_EXT_NTP_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_ntp_response },
+ {NULL, DM_URI_EXT_ERROR_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_ext_error },
+#endif
+ {DM_URI_THING_MODEL_DOWN_RAW, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_model_down_raw },
+ {DM_URI_THING_MODEL_UP_RAW_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_model_up_raw_reply },
+
+#ifdef DEVICE_MODEL_GATEWAY
+ {DM_URI_THING_TOPO_ADD_NOTIFY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_add_notify },
+ {DM_URI_THING_GATEWAY_PERMIT, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_gateway_permit },
+ {DM_URI_THING_SUB_REGISTER_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_sub_register_reply },
+ {DM_URI_THING_SUB_UNREGISTER_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_sub_unregister_reply },
+ {DM_URI_THING_TOPO_ADD_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_add_reply },
+ {DM_URI_THING_TOPO_DELETE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_delete_reply },
+ {DM_URI_THING_TOPO_GET_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_get_reply },
+ {DM_URI_THING_LIST_FOUND_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_list_found_reply },
+ {DM_URI_COMBINE_LOGIN_REPLY, DM_URI_EXT_SESSION_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_combine_login_reply },
+ {DM_URI_COMBINE_LOGOUT_REPLY, DM_URI_EXT_SESSION_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_combine_logout_reply },
+ {DM_URI_THING_DISABLE, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_disable },
+ {DM_URI_THING_ENABLE, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_enable },
+ {DM_URI_THING_DELETE, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_delete },
+#endif
+};
+
+static int _dm_client_subscribe_filter(char *uri, char *uri_name, char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ int res = 0;
+#endif
+ if (uri_name == NULL) {
+ return SUCCESS_RETURN;
+ }
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ if (strlen(uri_name) == strlen(DM_URI_THING_EVENT_POST_REPLY_WILDCARD) &&
+ memcmp(uri_name, DM_URI_THING_EVENT_POST_REPLY_WILDCARD, strlen(uri_name)) == 0) {
+ int event_post_reply_opt = 0;
+ res = dm_opt_get(DM_OPT_DOWNSTREAM_EVENT_POST_REPLY, &event_post_reply_opt);
+ if (res == SUCCESS_RETURN && event_post_reply_opt == 0) {
+ dm_client_unsubscribe(uri);
+ return FAIL_RETURN;
+ }
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int dm_client_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ int dev_type)
+{
+ int res = 0, index = 0, fail_count = 0;
+ int number = sizeof(g_dm_client_uri_map) / sizeof(dm_client_uri_map_t);
+ char *uri = NULL;
+ uint8_t local_sub = 0;
+#ifdef SUB_PERSISTENCE_ENABLED
+ char device_key[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 4] = {0};
+#endif
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ index = 1;
+
+ for (fail_count = 0; fail_count < IOTX_DM_CLIENT_SUB_RETRY_MAX_COUNTS; fail_count++) {
+
+ res = dm_utils_service_name((char *)g_dm_client_uri_map[0].uri_prefix, (char *)g_dm_client_uri_map[0].uri_name,
+ product_key, device_name, &uri);
+ if (res < SUCCESS_RETURN) {
+ continue;
+ }
+ res = _dm_client_subscribe_filter(uri, (char *)g_dm_client_uri_map[0].uri_name, product_key, device_name);
+ if (res < SUCCESS_RETURN) {
+ DM_free(uri);
+ continue;
+ }
+
+ res = dm_client_subscribe(uri, (iotx_cm_data_handle_cb)g_dm_client_uri_map[0].callback, 0);
+ if (res < SUCCESS_RETURN) {
+ DM_free(uri);
+ continue;
+ }
+
+ DM_free(uri);
+ break;
+ }
+#else
+ index = 0;
+#endif
+ fail_count = 0;
+#ifdef SUB_PERSISTENCE_ENABLED
+ {
+ int len = 1;
+ HAL_Snprintf(device_key, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN, "qub_%s%s", product_key, device_name);
+ HAL_Kv_Get(device_key, &local_sub, &len);
+ }
+#endif
+
+ for (; index < number; index++) {
+ if ((g_dm_client_uri_map[index].dev_type & dev_type) == 0) {
+ continue;
+ }
+ dm_log_info("index: %d", index);
+
+ if (fail_count >= IOTX_DM_CLIENT_SUB_RETRY_MAX_COUNTS) {
+ fail_count = 0;
+ continue;
+ }
+ res = dm_utils_service_name((char *)g_dm_client_uri_map[index].uri_prefix, (char *)g_dm_client_uri_map[index].uri_name,
+ product_key, device_name, &uri);
+ if (res < SUCCESS_RETURN) {
+ index--;
+ continue;
+ }
+
+ res = _dm_client_subscribe_filter(uri, (char *)g_dm_client_uri_map[index].uri_name, product_key, device_name);
+ if (res < SUCCESS_RETURN) {
+ DM_free(uri);
+ continue;
+ }
+
+ res = dm_client_subscribe(uri, (iotx_cm_data_handle_cb)g_dm_client_uri_map[index].callback, &local_sub);
+ if (res < SUCCESS_RETURN) {
+ index--;
+ fail_count++;
+ DM_free(uri);
+ continue;
+ }
+
+ fail_count = 0;
+ DM_free(uri);
+ }
+#ifdef SUB_PERSISTENCE_ENABLED
+ local_sub = 1;
+ HAL_Kv_Set(device_key, &local_sub, 1, 1);
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+static void _dm_client_event_cloud_connected_handle(void)
+{
+ dm_log_info("IOTX_CM_EVENT_CLOUD_CONNECTED");
+
+#ifdef DEV_BIND_ENABLED
+ awss_report_cloud();
+#endif
+ dm_msg_cloud_connected();
+}
+
+static void _dm_client_event_cloud_disconnect_handle(void)
+{
+ dm_log_info("IOTX_CM_EVENT_CLOUD_DISCONNECT");
+
+ dm_msg_cloud_disconnect();
+}
+
+void dm_client_event_handle(int fd, iotx_cm_event_msg_t *event, void *context)
+{
+ switch (event->type) {
+ case IOTX_CM_EVENT_CLOUD_CONNECTED: {
+ _dm_client_event_cloud_connected_handle();
+ }
+ break;
+ case IOTX_CM_EVENT_CLOUD_CONNECT_FAILED: {
+
+ }
+ break;
+ case IOTX_CM_EVENT_CLOUD_DISCONNECT: {
+ _dm_client_event_cloud_disconnect_handle();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void dm_client_thing_model_down_raw(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_model_down_raw(&source);
+}
+
+void dm_client_thing_model_up_raw_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_model_up_raw_reply(&source);
+}
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+void dm_client_thing_service_property_set(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+ int prop_set_reply_opt = 0;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_SET_REPLY;
+
+ res = dm_msg_proc_thing_service_property_set(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+
+ prop_set_reply_opt = 0;
+ res = dm_opt_get(DM_OPT_UPSTREAM_PROPERTY_SET_REPLY, &prop_set_reply_opt);
+ if (res == SUCCESS_RETURN) {
+ if (prop_set_reply_opt) {
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
+#ifdef LOG_REPORT_TO_CLOUD
+ if (SUCCESS_RETURN == check_target_msg(request.id.value, request.id.value_length)) {
+ send_permance_info(request.id.value, request.id.value_length, "2", 1);
+ }
+#endif
+ }
+ }
+}
+
+#ifdef DEVICE_MODEL_SHADOW
+void dm_client_thing_service_property_get(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+ unsigned char *data = NULL;
+ int data_len = 0;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_GET_REPLY;
+
+ res = dm_msg_proc_thing_service_property_get(&source, &dest, &request, &response, &data, &data_len);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+}
+#endif
+
+void dm_client_thing_service_request(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_service_request(&source);
+}
+
+void dm_client_thing_event_post_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_event_post_reply(&source);
+}
+#ifdef DEVICE_MODEL_SHADOW
+void dm_client_thing_property_desired_get_reply(int fd, const char *topic, const char *payload,
+ unsigned int payload_len, void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_property_desired_get_reply(&source);
+}
+
+void dm_client_thing_property_desired_delete_reply(int fd, const char *topic, const char *payload,
+ unsigned int payload_len, void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_property_desired_delete_reply(&source);
+}
+#endif
+
+void dm_client_thing_deviceinfo_update_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_deviceinfo_update_reply(&source);
+}
+
+void dm_client_thing_deviceinfo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_deviceinfo_delete_reply(&source);
+}
+
+void dm_client_thing_dynamictsl_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_dynamictsl_get_reply(&source);
+}
+
+void dm_client_rrpc_request_wildcard(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_rrpc_request(&source);
+}
+
+void dm_client_ntp_response(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_disp_ntp_response(&source);
+}
+
+void dm_client_ext_error(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_disp_ext_error_response(&source);
+}
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+int dm_client_subdev_unsubscribe(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0, index = 0;
+ int number = sizeof(g_dm_client_uri_map) / sizeof(dm_client_uri_map_t);
+ char *uri = NULL;
+
+ for (index = 0; index < number; index++) {
+ if ((g_dm_client_uri_map[index].dev_type & IOTX_DM_DEVICE_SUBDEV) == 0) {
+ continue;
+ }
+
+ res = dm_utils_service_name((char *)g_dm_client_uri_map[index].uri_prefix, (char *)g_dm_client_uri_map[index].uri_name,
+ product_key, device_name, &uri);
+ if (res < SUCCESS_RETURN) {
+ index--;
+ continue;
+ }
+
+ dm_client_unsubscribe(uri);
+ DM_free(uri);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+void dm_client_thing_topo_add_notify(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_TOPO_ADD_NOTIFY_REPLY;
+
+ res = dm_msg_proc_thing_topo_add_notify(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
+}
+
+void dm_client_thing_disable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_DISABLE_REPLY;
+
+ res = dm_msg_proc_thing_disable(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
+}
+
+void dm_client_thing_enable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_ENABLE_REPLY;
+
+ res = dm_msg_proc_thing_enable(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
+}
+
+void dm_client_thing_delete(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_DELETE_REPLY;
+
+ res = dm_msg_proc_thing_delete(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
+}
+
+void dm_client_thing_gateway_permit(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dest.uri_name = DM_URI_THING_GATEWAY_PERMIT_REPLY;
+
+ res = dm_msg_proc_thing_gateway_permit(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ return;
+ }
+
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
+}
+
+void dm_client_thing_sub_register_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_sub_register_reply(&source);
+}
+
+void dm_client_thing_sub_unregister_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_sub_unregister_reply(&source);
+}
+
+void dm_client_thing_topo_add_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_topo_add_reply(&source);
+}
+
+void dm_client_thing_topo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_topo_delete_reply(&source);
+}
+
+void dm_client_thing_topo_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_topo_get_reply(&source);
+}
+
+void dm_client_thing_list_found_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_thing_list_found_reply(&source);
+}
+
+void dm_client_combine_login_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_combine_login_reply(&source);
+}
+
+void dm_client_combine_logout_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context)
+{
+ dm_msg_source_t source;
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = topic;
+ source.payload = (unsigned char *)payload;
+ source.payload_len = payload_len;
+ source.context = NULL;
+
+ dm_msg_proc_combine_logout_reply(&source);
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client.h
new file mode 100644
index 00000000..08e138cc
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client.h
@@ -0,0 +1,75 @@
+#ifndef _DM_CLIENT_H_
+#define _DM_CLIENT_H_
+
+typedef struct {
+ const char *uri_name;
+ const char *uri_prefix;
+ int dev_type;
+ void *callback;
+} dm_client_uri_map_t;
+
+void dm_client_event_handle(int fd, iotx_cm_event_msg_t *event, void *context);
+
+int dm_client_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1], int dev_type);
+
+void dm_client_thing_model_down_raw(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_model_up_raw_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+void dm_client_thing_property_desired_get_reply(int fd, const char *topic, const char *payload,
+ unsigned int payload_len, void *context);
+void dm_client_thing_property_desired_delete_reply(int fd, const char *topic, const char *payload,
+ unsigned int payload_len, void *context);
+void dm_client_thing_service_property_set(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_service_property_get(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_service_property_post(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_event_property_post_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_deviceinfo_update_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_deviceinfo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_dynamictsl_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_service_request(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_event_post_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_rrpc_request_wildcard(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_ntp_response(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
+void dm_client_ext_error(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+int dm_client_subdev_unsubscribe(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+void dm_client_thing_topo_add_notify(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_disable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
+void dm_client_thing_enable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
+void dm_client_thing_delete(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
+void dm_client_thing_gateway_permit(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_sub_register_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_sub_unregister_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_topo_add_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_topo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_topo_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_thing_list_found_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_combine_login_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+void dm_client_combine_logout_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client_adapter.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client_adapter.c
new file mode 100644
index 00000000..b42197ff
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client_adapter.c
@@ -0,0 +1,145 @@
+#include "iotx_dm_internal.h"
+
+static dm_client_ctx_t g_dm_client_ctx = {0};
+
+static dm_client_ctx_t *dm_client_get_ctx(void)
+{
+ return &g_dm_client_ctx;
+}
+
+int dm_client_open(void)
+{
+ int res = 0;
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+ iotx_cm_init_param_t cm_param;
+
+ memset(ctx, 0, sizeof(dm_client_ctx_t));
+ memset(&cm_param, 0, sizeof(iotx_cm_init_param_t));
+
+ cm_param.request_timeout_ms = IOTX_DM_CLIENT_REQUEST_TIMEOUT_MS;
+ cm_param.keepalive_interval_ms = IOTX_DM_CLIENT_KEEPALIVE_INTERVAL_MS;
+ cm_param.write_buf_size = CONFIG_MQTT_TX_MAXLEN;
+ cm_param.read_buf_size = CONFIG_MQTT_RX_MAXLEN;
+#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
+ cm_param.protocol_type = IOTX_CM_PROTOCOL_TYPE_COAP;
+#else
+ cm_param.protocol_type = IOTX_CM_PROTOCOL_TYPE_MQTT;
+#endif
+ cm_param.handle_event = dm_client_event_handle;
+
+ res = iotx_cm_open(&cm_param);
+
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+ ctx->fd = res;
+
+ dm_log_info("CM Fd: %d", ctx->fd);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_client_connect(int timeout_ms)
+{
+ int res = 0;
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+
+ res = iotx_cm_connect(ctx->fd, timeout_ms);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_client_close(void)
+{
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+
+ return iotx_cm_close(ctx->fd);
+}
+
+int dm_client_subscribe(char *uri, iotx_cm_data_handle_cb callback, void *context)
+{
+ int res = 0;
+ uint8_t local_sub = 0;
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+ iotx_cm_ext_params_t sub_params;
+
+ memset(&sub_params, 0, sizeof(iotx_cm_ext_params_t));
+ if (context != NULL) {
+ local_sub = *((uint8_t *)context);
+ }
+
+ if (local_sub == 1) {
+ sub_params.ack_type = IOTX_CM_MESSAGE_SUB_LOCAL;
+ sub_params.sync_mode = IOTX_CM_ASYNC;
+ } else {
+ sub_params.ack_type = IOTX_CM_MESSAGE_NO_ACK;
+ sub_params.sync_mode = IOTX_CM_SYNC;
+ }
+
+ sub_params.sync_timeout = IOTX_DM_CLIENT_SUB_TIMEOUT_MS;
+ sub_params.ack_cb = NULL;
+
+ res = iotx_cm_sub(ctx->fd, &sub_params, (const char *)uri, callback, NULL);
+ dm_log_info("Subscribe Result: %d", res);
+
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_client_unsubscribe(char *uri)
+{
+ int res = 0;
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+
+ res = iotx_cm_unsub(ctx->fd, uri);
+
+ dm_log_info("Unsubscribe Result: %d", res);
+
+ return res;
+}
+
+int dm_client_publish(char *uri, unsigned char *payload, int payload_len, iotx_cm_data_handle_cb callback)
+{
+ int res = 0;
+ char *pub_uri = NULL;
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+ iotx_cm_ext_params_t pub_param;
+
+ memset(&pub_param, 0, sizeof(iotx_cm_ext_params_t));
+ pub_param.ack_type = IOTX_CM_MESSAGE_NO_ACK;
+ pub_param.sync_mode = IOTX_CM_ASYNC;
+ pub_param.sync_timeout = 0;
+ pub_param.ack_cb = NULL;
+
+#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
+ pub_param.ack_cb = callback;
+ res = dm_utils_uri_add_prefix("/topic", uri, &pub_uri);
+ if (res < SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+#else
+ pub_uri = uri;
+#endif
+
+ res = iotx_cm_pub(ctx->fd, &pub_param, (const char *)pub_uri, (const char *)payload, (unsigned int)payload_len);
+ dm_log_info("Publish Result: %d", res);
+
+#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
+ DM_free(pub_uri);
+#endif
+
+ return res;
+}
+
+int dm_client_yield(unsigned int timeout)
+{
+ dm_client_ctx_t *ctx = dm_client_get_ctx();
+
+ return iotx_cm_yield(ctx->fd, timeout);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client_adapter.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client_adapter.h
new file mode 100644
index 00000000..bf82c90b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_client_adapter.h
@@ -0,0 +1,18 @@
+#ifndef _DM_CLIENT_ADAPTER_H_
+#define _DM_CLIENT_ADAPTER_H_
+
+typedef struct {
+ int fd;
+ iotx_conn_info_t *conn_info;
+ void *callback;
+} dm_client_ctx_t;
+
+int dm_client_open(void);
+int dm_client_connect(int timeout_ms);
+int dm_client_close(void);
+int dm_client_subscribe(char *uri, iotx_cm_data_handle_cb callback, void *context);
+int dm_client_unsubscribe(char *uri);
+int dm_client_publish(char *uri, unsigned char *payload, int payload_len, iotx_cm_data_handle_cb callback);
+int dm_client_yield(unsigned int timeout);
+
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_cota.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_cota.c
new file mode 100644
index 00000000..ed8aeee4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_cota.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define DM_COTA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "dm.cota")
+ #define DM_COTA_FREE(ptr) LITE_free(ptr)
+#else
+ #define DM_COTA_MALLOC(size) HAL_Malloc(size)
+ #define DM_COTA_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+static dm_cota_ctx_t g_dm_cota_ctx;
+
+static dm_cota_ctx_t *_dm_cota_get_ctx(void)
+{
+ return &g_dm_cota_ctx;
+}
+
+int dm_cota_init(void)
+{
+ dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
+
+ memset(ctx, 0, sizeof(dm_cota_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_cota_deinit(void)
+{
+ dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
+
+ memset(ctx, 0, sizeof(dm_cota_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_cota_send_new_config_to_user(void *ota_handle)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+ uint32_t config_size = 0;
+ char *config_id = NULL, *sign = NULL, *sign_method = NULL, *url = NULL, *get_type = NULL;
+ const char *cota_new_config_fmt =
+ "{\"configId\":\"%s\",\"configSize\":%d,\"getType\":\"%s\",\"sign\":\"%s\",\"signMethod\":\"%s\",\"url\":\"%s\"}";
+
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_CONFIG_ID, (void *)&config_id, 1);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_CONFIG_SIZE, &config_size, 4);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_SIGN, (void *)&sign, 1);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_SIGN_METHOD, (void *)&sign_method, 1);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_URL, (void *)&url, 1);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_GETTYPE, (void *)&get_type, 1);
+
+ if (config_id == NULL || sign == NULL || sign_method == NULL || url == NULL || get_type == NULL) {
+ res = FAIL_RETURN;
+ goto ERROR;
+ }
+
+ message_len = strlen(cota_new_config_fmt) + strlen(config_id) + DM_UTILS_UINT32_STRLEN + strlen(get_type) +
+ strlen(sign) + strlen(sign_method) + strlen(url) + 1;
+
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ res = DM_MEMORY_NOT_ENOUGH;
+ goto ERROR;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, cota_new_config_fmt, config_id, config_size, get_type, sign, sign_method, url);
+
+ dm_log_info("Send To User: %s", message);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_COTA_NEW_CONFIG, message);
+ if (res != SUCCESS_RETURN) {
+ if (message) {
+ DM_free(message);
+ }
+ res = FAIL_RETURN;
+ goto ERROR;
+ }
+
+ res = SUCCESS_RETURN;
+ERROR:
+ if (config_id) {
+ DM_COTA_FREE(config_id);
+ }
+ if (sign) {
+ DM_COTA_FREE(sign);
+ }
+ if (sign_method) {
+ DM_COTA_FREE(sign_method);
+ }
+ if (url) {
+ DM_COTA_FREE(url);
+ }
+ if (get_type) {
+ DM_COTA_FREE(get_type);
+ }
+
+ return res;
+}
+
+int dm_cota_perform_sync(_OU_ char *output, _IN_ int output_len)
+{
+ int res = 0, file_download = 0;
+ uint32_t file_size = 0, file_downloaded = 0;
+ uint32_t percent_pre = 0, percent_now = 0;
+ unsigned long long report_pre = 0, report_now = 0;
+ dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
+ void *ota_handle = NULL;
+ uint32_t ota_type = IOT_OTAT_NONE;
+
+ if (output == NULL || output_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Get Ota Handle */
+ res = dm_ota_get_ota_handle(&ota_handle);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (ota_handle == NULL) {
+ return FAIL_RETURN;
+ }
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
+
+ if (ota_type != IOT_OTAT_COTA) {
+ return FAIL_RETURN;
+ }
+
+ /* reset the size_fetched in ota_handle to be 0 */
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
+ /* Prepare Write Data To Storage */
+ HAL_Firmware_Persistence_Start();
+
+ while (1) {
+ file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
+ if (file_download < 0) {
+ IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
+ HAL_Firmware_Persistence_Stop();
+ ctx->is_report_new_config = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Write Config File Into Stroage */
+ HAL_Firmware_Persistence_Write(output, file_download);
+
+ /* Get OTA information */
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
+
+ /* Calculate Download Percent And Update Report Timestamp*/
+ percent_now = (file_downloaded * 100) / file_size;
+ report_now = HAL_UptimeMs();
+
+ /* Report Download Process To Cloud */
+ if (report_now < report_pre) {
+ report_pre = report_now;
+ }
+ if ((((percent_now - percent_pre) > 5) &&
+ ((report_now - report_pre) > 50)) || (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
+ IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
+ percent_pre = percent_now;
+ report_pre = report_now;
+ }
+
+ /* Check If OTA Finished */
+ if (IOT_OTA_IsFetchFinish(ota_handle)) {
+ uint32_t file_isvalid = 0;
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_CONFIG, &file_isvalid, 4);
+ if (file_isvalid == 0) {
+ HAL_Firmware_Persistence_Stop();
+ ctx->is_report_new_config = 0;
+ return FAIL_RETURN;
+ } else {
+ break;
+ }
+ }
+ }
+
+ HAL_Firmware_Persistence_Stop();
+ ctx->is_report_new_config = 0;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_cota_get_config(const char *config_scope, const char *get_type, const char *attribute_keys)
+{
+ int res = 0;
+ void *ota_handle = NULL;
+
+ /* Get Ota Handle */
+ res = dm_ota_get_ota_handle(&ota_handle);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return iotx_ota_get_config(ota_handle, config_scope, get_type, attribute_keys);
+}
+
+int dm_cota_status_check(void)
+{
+ int res = 0;
+ dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
+ void *ota_handle = NULL;
+
+ /* Get Ota Handle */
+ res = dm_ota_get_ota_handle(&ota_handle);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (IOT_OTA_IsFetching(ota_handle)) {
+ uint32_t ota_type = IOT_OTAT_NONE;
+
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
+
+ if (ota_type == IOT_OTAT_COTA) {
+ /* Send New Config Information To User */
+ if (ctx->is_report_new_config == 0) {
+ dm_log_debug("Cota Status Check");
+ res = _dm_cota_send_new_config_to_user(ota_handle);
+ if (res == SUCCESS_RETURN) {
+ ctx->is_report_new_config = 1;
+ }
+ }
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_cota.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_cota.h
new file mode 100644
index 00000000..c5f54d07
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_cota.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_COTA_H_
+#define _DM_COTA_H_
+
+typedef struct {
+ int is_report_new_config;
+} dm_cota_ctx_t;
+
+int dm_cota_init(void);
+int dm_cota_deinit(void);
+int dm_cota_perform_sync(_OU_ char *output, _IN_ int output_len);
+int dm_cota_get_config(const char *config_scope, const char *get_type, const char *attribute_keys);
+int dm_cota_status_check(void);
+
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_fota.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_fota.c
new file mode 100644
index 00000000..ec71d056
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_fota.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+
+static dm_fota_ctx_t g_dm_fota_ctx;
+
+static dm_fota_ctx_t *_dm_fota_get_ctx(void)
+{
+ return &g_dm_fota_ctx;
+}
+
+int dm_fota_init(void)
+{
+ dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
+
+ memset(ctx, 0, sizeof(dm_fota_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_fota_deinit(void)
+{
+ dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
+
+ memset(ctx, 0, sizeof(dm_fota_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_fota_send_new_config_to_user(void *ota_handle)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+ char version[128] = {0};
+ const char *fota_new_config_fmt = "{\"version\":\"%s\"}";
+
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_VERSION, version, 128);
+
+ message_len = strlen(fota_new_config_fmt) + strlen(version) + 1;
+
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, fota_new_config_fmt, version);
+
+ dm_log_info("Send To User: %s", message);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_FOTA_NEW_FIRMWARE, message);
+ if (res != SUCCESS_RETURN) {
+ if (message) {
+ DM_free(message);
+ }
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len)
+{
+ int res = 0, file_download = 0;
+ uint32_t file_size = 0, file_downloaded = 0;
+ uint32_t percent_pre = 0, percent_now = 0;
+ unsigned long long report_pre = 0, report_now = 0;
+ dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
+ void *ota_handle = NULL;
+ uint32_t ota_type = IOT_OTAT_NONE;
+ int ret = 0;
+ uint8_t is_header = 1;
+
+ if (output == NULL || output_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Get Ota Handle */
+ res = dm_ota_get_ota_handle(&ota_handle);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (ota_handle == NULL) {
+ return FAIL_RETURN;
+ }
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
+
+ if (ota_type != IOT_OTAT_FOTA) {
+ return FAIL_RETURN;
+ }
+
+ /* reset the size_fetched in ota_handle to be 0 */
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
+ /* Prepare Write Data To Storage */
+ HAL_Firmware_Persistence_Start();
+ while (1) {
+ file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
+ if (file_download < 0) {
+ IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
+ HAL_Firmware_Persistence_Stop();
+ ctx->is_report_new_config = 0;
+ return FAIL_RETURN;
+ }
+#ifdef SUPPORT_SECURITY_OTA
+ /* Check safe upgrade word in image */
+ if (is_header) {
+ if (HAL_Firmware_Check_Rsa_Key(output, file_download)) {
+ IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_CHECK_FALIED, NULL);
+ HAL_Firmware_Persistence_Stop();
+ return SUCCESS_RETURN;
+ }
+ is_header = 0;
+ }
+#endif
+ /* Write Config File Into Stroage */
+ ret = HAL_Firmware_Persistence_Write(output, file_download);
+ if (-1 == ret) {
+ IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_BURN_FAILED, NULL);
+ dm_log_err("Fota write firmware failed");
+ }
+
+ /* Get OTA information */
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
+
+ /* Calculate Download Percent And Update Report Timestamp*/
+ percent_now = (file_downloaded * 100) / file_size;
+ report_now = HAL_UptimeMs();
+
+ /* Report Download Process To Cloud */
+ if (report_now < report_pre) {
+ report_pre = report_now;
+ }
+ if ((((percent_now - percent_pre) > 5) &&
+ ((report_now - report_pre) > 50)) || (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
+ IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
+ percent_pre = percent_now;
+ report_pre = report_now;
+ }
+
+ /* Check If OTA Finished */
+ if (IOT_OTA_IsFetchFinish(ota_handle)) {
+ uint32_t file_isvalid = 0;
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_CONFIG, &file_isvalid, 4);
+ if (file_isvalid == 0) {
+ HAL_Firmware_Persistence_Stop();
+ ctx->is_report_new_config = 0;
+ return FAIL_RETURN;
+ } else {
+ break;
+ }
+ }
+ }
+
+ HAL_Firmware_Persistence_Stop();
+ ctx->is_report_new_config = 0;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_fota_status_check(void)
+{
+ int res = 0;
+ dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
+ void *ota_handle = NULL;
+
+ /* Get Ota Handle */
+ res = dm_ota_get_ota_handle(&ota_handle);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (IOT_OTA_IsFetching(ota_handle)) {
+ uint32_t ota_type = IOT_OTAT_NONE;
+
+ IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
+
+ if (ota_type == IOT_OTAT_FOTA) {
+ /* Send New Config Information To User */
+ if (ctx->is_report_new_config == 0) {
+ dm_log_debug("Fota Status Check");
+ res = _dm_fota_send_new_config_to_user(ota_handle);
+ if (res == SUCCESS_RETURN) {
+ ctx->is_report_new_config = 1;
+ }
+ }
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_fota_request_image(const char *version, int buffer_len)
+{
+ int res = 0;
+ void *ota_handle = NULL;
+ char *version_str = NULL;
+
+ if (NULL == version || buffer_len <= 0) {
+ dm_log_info("invalid input");
+ return FAIL_RETURN;
+ }
+
+ /* Get Ota Handle */
+ res = dm_ota_get_ota_handle(&ota_handle);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ version_str = DM_malloc(buffer_len + 1);
+ if (NULL == version_str) {
+ dm_log_info("failed to malloc");
+ return FAIL_RETURN;
+ }
+ memset(version_str, 0, buffer_len + 1);
+ memcpy(version_str, version, buffer_len);
+
+ res = iotx_req_image(ota_handle, version_str);
+ DM_free(version_str);
+ return res;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_fota.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_fota.h
new file mode 100644
index 00000000..d75157a1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_fota.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_FOTA_H_
+#define _DM_FOTA_H_
+
+typedef struct {
+ int is_report_new_config;
+} dm_fota_ctx_t;
+
+int dm_fota_init(void);
+int dm_fota_deinit(void);
+int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len);
+int dm_fota_status_check(void);
+int dm_fota_request_image(_IN_ const char *version, _IN_ int buffer_len);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_intf.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_intf.h
new file mode 100644
index 00000000..1d26f06c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_intf.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _IOT_DM_API_H_
+#define _IOT_DM_API_H_
+
+typedef struct {
+ void *mutex;
+ void *cloud_connectivity;
+ void *local_connectivity;
+ iotx_dm_event_callback event_callback;
+} dm_api_ctx_t;
+
+#if defined(DEPRECATED_LINKKIT)
+typedef struct {
+ void *mutex;
+ int devid;
+ lite_cjson_item_t *lite;
+} dm_api_property_t;
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ipc.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ipc.c
new file mode 100644
index 00000000..44a5126e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ipc.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include "iotx_dm_internal.h"
+
+dm_ipc_t g_dm_ipc;
+
+static dm_ipc_t *_dm_ipc_get_ctx(void)
+{
+ return &g_dm_ipc;
+}
+
+static void _dm_ipc_lock(void)
+{
+ dm_ipc_t *ctx = _dm_ipc_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexLock(ctx->mutex);
+ }
+}
+
+static void _dm_ipc_unlock(void)
+{
+ dm_ipc_t *ctx = _dm_ipc_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexUnlock(ctx->mutex);
+ }
+}
+
+int dm_ipc_init(int max_size)
+{
+ dm_ipc_t *ctx = _dm_ipc_get_ctx();
+
+ memset(ctx, 0, sizeof(dm_ipc_t));
+
+ /* Create Mutex */
+ ctx->mutex = HAL_MutexCreate();
+ if (ctx->mutex == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Init List */
+ ctx->msg_list.max_size = max_size;
+ INIT_LIST_HEAD(&ctx->msg_list.message_list);
+
+ return SUCCESS_RETURN;
+}
+
+void dm_ipc_deinit(void)
+{
+ dm_ipc_t *ctx = _dm_ipc_get_ctx();
+ dm_ipc_msg_node_t *del_node = NULL;
+ dm_ipc_msg_node_t *next_node = NULL;
+ dm_ipc_msg_t *del_msg = NULL;
+
+ if (ctx->mutex) {
+ HAL_MutexDestroy(ctx->mutex);
+ }
+
+ list_for_each_entry_safe(del_node, next_node, &ctx->msg_list.message_list, linked_list, dm_ipc_msg_node_t) {
+ /* Free Message */
+ del_msg = (dm_ipc_msg_t *)del_node->data;
+ if (del_msg->data) {
+ DM_free(del_msg->data);
+ }
+ DM_free(del_msg);
+ del_msg = NULL;
+
+ /* Free Node */
+ list_del(&del_node->linked_list);
+ DM_free(del_node);
+ }
+}
+
+int dm_ipc_msg_insert(void *data)
+{
+ dm_ipc_t *ctx = _dm_ipc_get_ctx();
+ dm_ipc_msg_node_t *node = NULL;
+
+ if (data == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_ipc_lock();
+ dm_log_debug("dm msg list size: %d, max size: %d", ctx->msg_list.size, ctx->msg_list.max_size);
+ if (ctx->msg_list.size >= ctx->msg_list.max_size) {
+ dm_log_warning("dm ipc list full");
+ _dm_ipc_unlock();
+ return FAIL_RETURN;
+ }
+
+ node = DM_malloc(sizeof(dm_ipc_msg_node_t));
+ if (node == NULL) {
+ _dm_ipc_unlock();
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(node, 0, sizeof(dm_ipc_msg_node_t));
+
+ node->data = data;
+ INIT_LIST_HEAD(&node->linked_list);
+ ctx->msg_list.size++;
+ list_add_tail(&node->linked_list, &ctx->msg_list.message_list);
+
+ _dm_ipc_unlock();
+ return SUCCESS_RETURN;
+}
+
+int dm_ipc_msg_next(void **data)
+{
+ dm_ipc_t *ctx = _dm_ipc_get_ctx();
+ dm_ipc_msg_node_t *node = NULL;
+
+ if (data == NULL || *data != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_ipc_lock();
+
+ if (list_empty(&ctx->msg_list.message_list)) {
+ _dm_ipc_unlock();
+ return FAIL_RETURN;
+ }
+
+ node = list_first_entry(&ctx->msg_list.message_list, dm_ipc_msg_node_t, linked_list);
+ list_del(&node->linked_list);
+ ctx->msg_list.size--;
+
+ *data = node->data;
+ DM_free(node);
+
+ _dm_ipc_unlock();
+ return SUCCESS_RETURN;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ipc.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ipc.h
new file mode 100644
index 00000000..36ebe1b3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ipc.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_IPC_H_
+#define _DM_IPC_H_
+
+#include "iotx_dm_internal.h"
+
+typedef struct {
+ iotx_dm_event_types_t type;
+ char *data;
+} dm_ipc_msg_t;
+
+typedef struct {
+ void *data;
+ struct list_head linked_list;
+} dm_ipc_msg_node_t;
+
+typedef struct {
+ int max_size;
+ int size;
+ struct list_head message_list;
+} dm_ipc_msg_list_t;
+
+typedef struct {
+ void *mutex;
+ dm_ipc_msg_list_t msg_list;
+} dm_ipc_t;
+
+int dm_ipc_init(int max_size);
+void dm_ipc_deinit(void);
+int dm_ipc_msg_insert(void *data);
+int dm_ipc_msg_next(void **data);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_log_report.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_log_report.c
new file mode 100644
index 00000000..bbe839ac
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_log_report.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_dm_internal.h"
+
+#ifdef LOG_REPORT_TO_CLOUD
+
+#include "dev_model_api.h"
+
+const char THING_LOG_POST_PARAMS_HEAD[] =
+ "\"%.*s %s %ld ";
+const char THING_LOG_POST_PARAMS_BODY[] =
+ "%s %ld ";
+const char THING_LOG_POST_PARAMS_END[] =
+ "%s %ld\",";
+
+char *g_log_poll = NULL;
+static char *current_log_pos = NULL;
+
+int remove_log_poll()
+{
+ if (NULL != g_log_poll) {
+ HAL_Free(g_log_poll);
+ g_log_poll = NULL;
+ current_log_pos = NULL;
+ }
+ return 0;
+}
+
+
+unsigned int push_log(const char *input_log, int input_log_size)
+{
+ if (NULL == current_log_pos || NULL == input_log || input_log_size <= 0) {
+ dm_log_debug("invalid params");
+ return -1;
+ }
+ memcpy(current_log_pos, input_log, input_log_size);
+ current_log_pos += input_log_size;
+ return (current_log_pos - g_log_poll);
+}
+
+unsigned int add_tail()
+{
+ const char *tail = "]}";
+ current_log_pos -= 1;
+ return push_log(tail, strlen(tail));
+}
+
+void add_log_header()
+{
+ const char *subprefix = "{\"template\": \"traceContext logContent\",\"contents\":[";
+ int sublen = strlen(subprefix);
+ push_log(subprefix, sublen);
+}
+
+int reset_log_poll()
+{
+ if (NULL == g_log_poll) {
+ dm_log_err("log buffer is NULL");
+ return -1;
+ }
+ memset(g_log_poll, 0, LOG_POLL_SIZE);
+ current_log_pos = g_log_poll;
+ add_log_header();
+ return 0;
+}
+
+int create_log_poll()
+{
+ int ret;
+ remove_log_poll();
+ g_log_poll = HAL_Malloc(LOG_POLL_SIZE);
+ ret = reset_log_poll();
+ return ret;
+}
+
+static int switch_status = 0; /* 0 for switch off; 1 for switch on */
+static unsigned int sample_interval = 5;
+static unsigned int sample_count = 1000;
+
+#define MSG_ID_LEN (64)
+char msg_array[MSG_ID_LEN] = {0};
+int check_target_msg(const char *input, int len)
+{
+ /* do not upload log when swith is off */
+ if (0 == switch_status) {
+ return -1;
+ }
+ if (NULL == input || len <= 0) {
+ dm_log_err("invalid params");
+ return -1;
+ }
+ return strncmp(input, msg_array, len);
+}
+
+static unsigned int msg_num = 0;
+/* return 0 for success; -1 for failure */
+int set_target_msg(const char *input, int len)
+{
+ if (0 == switch_status) {
+ return -1;
+ }
+ if ((msg_num % sample_interval == 0) && (msg_num < sample_count)) {
+ if (NULL == input || len <= 0) {
+ dm_log_err("invalid params");
+ return -1;
+ }
+ strncpy(msg_array, input, len);
+ return 0;
+ }
+ return -1;
+}
+
+void parse_msg_id(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_request_payload_t *request)
+{
+ lite_cjson_t lite;
+
+ if (payload == NULL || payload_len <= 0 || request == NULL) {
+ return;
+ }
+
+ dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite);
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_ID, strlen(DM_MSG_KEY_ID), cJSON_String, &request->id);
+}
+
+int stop_sample()
+{
+ if (current_log_pos > g_log_poll) {
+ dm_mgr_upstream_thing_log_post(0, NULL, 0, 1);
+ }
+ switch_status = 0;
+ dm_log_info("stop sample");
+ return remove_log_poll();
+}
+
+void parse_switch_info(_IN_ char *payload, _IN_ int payload_len)
+{
+ lite_cjson_t lite, lite_sample_count, lite_sample_interval, lite_sample_target;
+ const char *c1 = "Count";
+ const char *c2 = "Interval";
+ const char *c3 = "ProfileTarget";
+ char *sample_target;
+ int sample_target_len;
+ const char *target = "propSet";
+ int ret = -1;
+
+ if (payload == NULL || payload_len <= 0) {
+ return;
+ }
+ dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite);
+ ret = lite_cjson_object_item(&lite, c1, strlen(c1), &lite_sample_count);
+ if (ret < SUCCESS_RETURN) {
+ return;
+ }
+
+ ret = lite_cjson_object_item(&lite, c2, strlen(c2), &lite_sample_interval);
+ if (ret < SUCCESS_RETURN) {
+ return;
+ }
+
+ ret = lite_cjson_object_item(&lite, c3, strlen(c3), &lite_sample_target);
+ if (ret < SUCCESS_RETURN) {
+ return;
+ }
+
+ sample_count = lite_sample_count.value_int;
+ sample_interval = lite_sample_interval.value_int;
+ sample_target = lite_sample_target.value;
+ sample_target_len = lite_sample_target.value_length;
+ dm_log_info("switch count is %d, interval is %d, target is %.*s\n", sample_count, sample_interval,
+ sample_target_len, sample_target);
+ /* if the target is not property set, return */
+ if (0 != strncmp(sample_target, target, sample_target_len)) {
+ dm_log_info("target is not propSet, return\n");
+ return;
+ }
+ if (sample_interval <= 0) {
+ dm_log_err("invalid sample interval\n");
+ return;
+ }
+ msg_num = 0;
+ /* when it switch off, force upload the remaining log */
+ if (0 == sample_count) {
+ ret = stop_sample();
+ } else {
+ switch_status = 1;
+ ret = create_log_poll();
+ }
+
+ dm_log_info("log switch run status is %d\n", ret);
+}
+
+REPORT_STATE g_report_status = READY;
+
+void send_permance_info(char *input, int input_len, char *comments, int report_format)
+{
+#define LOCAL_POST_LEN (150)
+ char data[LOCAL_POST_LEN] = {0};
+ const char *format = NULL;
+ if (0 == switch_status) {
+ return;
+ }
+
+ switch (report_format) {
+ case 0:
+ if (NULL == input || input_len <= 0) {
+ dm_log_err("invalid params");
+ return;
+ }
+ format = THING_LOG_POST_PARAMS_HEAD;
+ HAL_Snprintf(data, sizeof(data), format, input_len, input,
+ comments, (long)HAL_UptimeMs());
+ break;
+ case 1:
+ format = THING_LOG_POST_PARAMS_BODY;
+ HAL_Snprintf(data, sizeof(data), format,
+ comments, (long)HAL_UptimeMs());
+ break;
+ case 2:
+ format = THING_LOG_POST_PARAMS_END;
+ HAL_Snprintf(data, sizeof(data), format,
+ comments, (long)HAL_UptimeMs());
+ g_report_status = DONE;
+ break;
+ default:
+ return;
+ }
+ iotx_dm_log_post(0, data, strlen((const char *)data));
+ if (2 == report_format) {
+ g_report_status = READY;
+ }
+}
+
+void get_msgid(char *payload, int is_cloud)
+{
+ const char *interest = "\"method\":\"thing.service.property.set";
+ char *found;
+ dm_msg_request_payload_t request;
+ if (0 == switch_status || NULL == payload) {
+ return;
+ }
+
+ found = strstr(payload, interest);
+ if (NULL == found) {
+ return;
+ }
+ found = strstr(payload, "{");
+ if (NULL == found) {
+ return;
+ }
+ msg_num++;
+ parse_msg_id(found, strlen(found), &request);
+ if (RUNNING == g_report_status) {
+ dm_log_info("current working on a sample, return");
+ return;
+ }
+
+ if (sample_count <= msg_num) {
+ stop_sample();
+ return;
+ }
+
+ /* if it does not meet the sample conditions, do NOT take sample */
+ if (SUCCESS_RETURN != set_target_msg(request.id.value, request.id.value_length)) {
+ return;
+ }
+
+ g_report_status = RUNNING;
+
+ if (1 == is_cloud) {
+ send_permance_info(request.id.value, request.id.value_length, "1_cloud", 0);
+ } else if (0 == is_cloud) {
+ send_permance_info(request.id.value, request.id.value_length, "1_alcs", 0);
+ }
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_manager.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_manager.c
new file mode 100644
index 00000000..947a564d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_manager.c
@@ -0,0 +1,2261 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include "iotx_dm_internal.h"
+
+static dm_mgr_ctx g_dm_mgr = {0};
+
+static dm_mgr_ctx *_dm_mgr_get_ctx(void)
+{
+ return &g_dm_mgr;
+}
+
+static void _dm_mgr_mutex_lock(void)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexLock(ctx->mutex);
+ }
+}
+
+static void _dm_mgr_mutex_unlock(void)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexUnlock(ctx->mutex);
+ }
+}
+
+static int _dm_mgr_next_devid(void)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+
+ return ctx->global_devid++;
+}
+
+static int _dm_mgr_search_dev_by_devid(_IN_ int devid, _OU_ dm_mgr_dev_node_t **node)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ if (search_node->devid == devid) {
+ /* dm_log_debug("Device Found, devid: %d", devid); */
+ if (node) {
+ *node = search_node;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ dm_log_debug("Device Not Found, devid: %d", devid);
+ return FAIL_RETURN;
+}
+
+static int _dm_mgr_search_dev_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ dm_mgr_dev_node_t **node)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ if ((strlen(search_node->product_key) == strlen(product_key)) &&
+ (memcmp(search_node->product_key, product_key, strlen(product_key)) == 0) &&
+ (strlen(search_node->device_name) == strlen(device_name)) &&
+ (memcmp(search_node->device_name, device_name, strlen(device_name)) == 0)) {
+ /* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
+ if (node) {
+ *node = search_node;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ dm_log_debug("Device Not Found, Product Key: %s, Device Name: %s", product_key, device_name);
+ return FAIL_RETURN;
+}
+
+static int _dm_mgr_insert_dev(_IN_ int devid, _IN_ int dev_type, char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0;
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || product_key == NULL || strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1 ||
+ device_name == NULL || strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, NULL);
+ if (res == SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ node = DM_malloc(sizeof(dm_mgr_dev_node_t));
+ if (node == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(node, 0, sizeof(dm_mgr_dev_node_t));
+
+ node->devid = devid;
+ node->dev_type = dev_type;
+ memcpy(node->product_key, product_key, strlen(product_key));
+ memcpy(node->device_name, device_name, strlen(device_name));
+ INIT_LIST_HEAD(&node->linked_list);
+
+ list_add_tail(&node->linked_list, &ctx->dev_list);
+
+ return SUCCESS_RETURN;
+}
+
+static void _dm_mgr_destroy_devlist(void)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *del_node = NULL;
+ dm_mgr_dev_node_t *next_node = NULL;
+
+ list_for_each_entry_safe(del_node, next_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ list_del(&del_node->linked_list);
+#ifdef DEPRECATED_LINKKIT
+ dm_shw_destroy(&del_node->dev_shadow);
+#endif
+ DM_free(del_node);
+ }
+}
+
+#ifdef DEPRECATED_LINKKIT
+static int _dm_mgr_legacy_thing_created(int devid)
+{
+ int res = 0, message_len = 0;
+ const char *thing_created_fmt = "{\"devid\":%d}";
+ char *message = NULL;
+
+ message_len = strlen(thing_created_fmt) + DM_UTILS_UINT32_STRLEN + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, thing_created_fmt, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_LEGACY_THING_CREATED, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+int dm_mgr_init(void)
+{
+ int res = 0;
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ memset(ctx, 0, sizeof(dm_mgr_ctx));
+
+ /* Create Mutex */
+ ctx->mutex = HAL_MutexCreate();
+ if (ctx->mutex == NULL) {
+ goto ERROR;
+ }
+
+ /* Init Device Id*/
+ ctx->global_devid = IOTX_DM_LOCAL_NODE_DEVID + 1;
+
+ /* Init Device List */
+ INIT_LIST_HEAD(&ctx->dev_list);
+
+ /* Local Node */
+ HAL_GetProductKey(product_key);
+ HAL_GetDeviceName(device_name);
+ res = _dm_mgr_insert_dev(IOTX_DM_LOCAL_NODE_DEVID, IOTX_DM_DEVICE_TYPE, product_key, device_name);
+ if (res != SUCCESS_RETURN) {
+ goto ERROR;
+ }
+
+#ifdef DEPRECATED_LINKKIT
+ _dm_mgr_legacy_thing_created(IOTX_DM_LOCAL_NODE_DEVID);
+#endif
+
+ return SUCCESS_RETURN;
+
+ERROR:
+ if (ctx->mutex) {
+ HAL_MutexDestroy(ctx->mutex);
+ }
+ memset(ctx, 0, sizeof(dm_mgr_ctx));
+ return FAIL_RETURN;
+}
+
+int dm_mgr_deinit(void)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+
+ _dm_mgr_mutex_lock();
+ _dm_mgr_destroy_devlist();
+ _dm_mgr_mutex_unlock();
+
+ if (ctx->mutex) {
+ HAL_MutexDestroy(ctx->mutex);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_device_create(_IN_ int dev_type, _IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ int *devid)
+{
+ int res = 0;
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (product_key == NULL || device_name == NULL ||
+ strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1 ||
+ strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (device_secret != NULL && strlen(device_secret) >= IOTX_DEVICE_SECRET_LEN + 1) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_pkdn(product_key, device_name, &node);
+ if (res == SUCCESS_RETURN) {
+ if (devid) {
+ *devid = node->devid;
+ }
+ return FAIL_RETURN;
+ }
+
+ node = DM_malloc(sizeof(dm_mgr_dev_node_t));
+ if (node == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(node, 0, sizeof(dm_mgr_dev_node_t));
+
+ node->devid = _dm_mgr_next_devid();
+ node->dev_type = dev_type;
+#if defined(DEPRECATED_LINKKIT)
+ node->dev_shadow = NULL;
+ node->tsl_source = IOTX_DM_TSL_SOURCE_CLOUD;
+#endif
+ memcpy(node->product_key, product_key, strlen(product_key));
+ memcpy(node->device_name, device_name, strlen(device_name));
+ if (device_secret != NULL) {
+ memcpy(node->device_secret, device_secret, strlen(device_secret));
+ }
+ node->dev_status = IOTX_DM_DEV_STATUS_AUTHORIZED;
+ INIT_LIST_HEAD(&node->linked_list);
+
+ list_add_tail(&node->linked_list, &ctx->dev_list);
+
+ if (devid) {
+ *devid = node->devid;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_device_destroy(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (node->devid == IOTX_DM_LOCAL_NODE_DEVID) {
+ return FAIL_RETURN;
+ }
+
+ list_del(&node->linked_list);
+
+#if defined(DEPRECATED_LINKKIT)
+ if (node->dev_shadow) {
+ dm_shw_destroy(&node->dev_shadow);
+ }
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+ dm_client_subdev_unsubscribe(node->product_key,node->device_name);
+#endif
+
+ DM_free(node);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_device_number(void)
+{
+ int index = 0;
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ index++;
+ }
+
+ return index;
+}
+
+int dm_mgr_get_devid_by_index(_IN_ int index, _OU_ int *devid)
+{
+ int search_index = 0;
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ if (index < 0 || devid == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ if (search_index == index) {
+ *devid = search_node->devid;
+ return SUCCESS_RETURN;
+ }
+ search_index++;
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_mgr_get_next_devid(_IN_ int devid, _OU_ int *devid_next)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *search_node = NULL;
+ dm_mgr_dev_node_t *next_node = NULL;
+
+ if (devid < 0 || devid_next == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ list_for_each_entry(next_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ if (search_node && search_node->devid == devid) {
+ *devid_next = next_node->devid;
+ return SUCCESS_RETURN;
+ }
+
+ if (next_node->devid == devid) {
+ search_node = next_node;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_mgr_search_device_by_devid(_IN_ int devid, _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1])
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (product_key == NULL || device_name == NULL || device_secret == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memcpy(product_key, node->product_key, strlen(node->product_key));
+ memcpy(device_name, node->device_name, strlen(node->device_name));
+ memcpy(device_secret, node->device_secret, strlen(node->device_secret));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_search_device_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ int *devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (product_key == NULL || device_name == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_pkdn(product_key, device_name, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (devid) {
+ *devid = node->devid;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_search_device_node_by_devid(_IN_ int devid, _OU_ void **node)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ res = _dm_mgr_search_dev_by_devid(devid, &search_node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (node) {
+ *node = (void *)search_node;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_get_dev_type(_IN_ int devid, _OU_ int *dev_type)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || dev_type == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ *dev_type = node->dev_type;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_set_dev_enable(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ node->status = IOTX_DM_DEV_AVAIL_ENABLE;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_set_dev_disable(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ node->status = IOTX_DM_DEV_AVAIL_DISABLE;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_get_dev_avail(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ iotx_dm_dev_avail_t *status)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (product_key == NULL || device_name == NULL || status == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_pkdn(product_key, device_name, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ *status = node->status;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_set_dev_status(_IN_ int devid, _IN_ iotx_dm_dev_status_t status)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ node->dev_status = status;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_get_dev_status(_IN_ int devid, _OU_ iotx_dm_dev_status_t *status)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || status == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ *status = node->dev_status;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_set_device_secret(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1])
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || device_secret == NULL ||
+ strlen(device_secret) >= IOTX_DEVICE_SECRET_LEN + 1) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(node->device_secret, 0, IOTX_DEVICE_SECRET_LEN + 1);
+ memcpy(node->device_secret, device_secret, strlen(device_secret));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_dev_initialized(int devid)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+ const char *fmt = "{\"devid\":%d}";
+
+ message_len = strlen(fmt) + DM_UTILS_UINT32_STRLEN + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, fmt, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_INITIALIZED, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+int dm_mgr_upstream_thing_sub_register(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_SUB_REGISTER;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_thing_sub_register(node->product_key, node->device_name, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_thing_sub_register_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_SUBDEV_REGISTER_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_thing_sub_unregister(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_SUB_UNREGISTER;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_thing_sub_unregister(node->product_key, node->device_name, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_thing_sub_unregister_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_SUBDEV_UNREGISTER_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_thing_topo_add(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_TOPO_ADD;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_thing_topo_add(node->product_key, node->device_name, node->device_secret, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_thing_topo_add_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_TOPO_ADD_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_thing_topo_delete(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_TOPO_DELETE;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_thing_topo_delete(node->product_key, node->device_name, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_thing_topo_delete_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_TOPO_DELETE_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_thing_topo_get(void)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_TOPO_GET;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ res = _dm_mgr_search_dev_by_pkdn(request.product_key, request.device_name, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Params And Method */
+ res = dm_msg_thing_topo_get(&request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = node->devid;
+
+ /* Callback */
+ request.callback = dm_client_thing_topo_get_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_TOPO_GET_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_thing_list_found(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_LIST_FOUND;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_thing_list_found(node->product_key, node->device_name, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_thing_list_found_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_TOPO_ADD_NOTIFY_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_combine_login(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_EXT_SESSION_PREFIX;
+ request.service_name = DM_URI_COMBINE_LOGIN;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_combine_login(node->product_key, node->device_name, node->device_secret, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_combine_login_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_COMBINE_LOGIN_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+int dm_mgr_upstream_combine_logout(_IN_ int devid)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (node->dev_status < IOTX_DM_DEV_STATUS_LOGINED) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_EXT_SESSION_PREFIX;
+ request.service_name = DM_URI_COMBINE_LOGOUT;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Get Params And Method */
+ res = dm_msg_combine_logout(node->product_key, node->device_name, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Msg ID */
+ request.msgid = iotx_report_id();
+
+ /* Get Dev ID */
+ request.devid = devid;
+
+ /* Callback */
+ request.callback = dm_client_combine_logout_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_COMBINE_LOGOUT_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ DM_free(request.params);
+
+ return res;
+}
+
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+int dm_mgr_upstream_thing_firmware_version_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, res1 = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ char *uri = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_OTA_DEVICE_INFORM;
+ request.service_name = NULL;
+ memcpy(request.product_key, node->product_key, strlen(node->product_key));
+ memcpy(request.device_name, node->device_name, strlen(node->device_name));
+
+ /* Request URI */
+ res = dm_utils_service_name(request.service_prefix, request.service_name,
+ request.product_key, request.device_name, &uri);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_info("DM Send Raw Data:");
+ HEXDUMP_INFO(payload, payload_len);
+
+ res = dm_client_publish(uri, (unsigned char *)payload, strlen(payload), dm_client_thing_model_up_raw_reply);
+
+ if (res < SUCCESS_RETURN || res1 < SUCCESS_RETURN) {
+ dm_log_info("res of pub is %d:", res);
+ DM_free(uri);
+ return FAIL_RETURN;
+ }
+
+ DM_free(uri);
+ return SUCCESS_RETURN;
+}
+#endif
+#endif
+
+int dm_mgr_upstream_thing_model_up_raw(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, res1 = 0;
+ dm_mgr_dev_node_t *node = NULL;
+ char *uri = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_SYS_PREFIX;
+ request.service_name = DM_URI_THING_MODEL_UP_RAW;
+ memcpy(request.product_key, node->product_key, strlen(node->product_key));
+ memcpy(request.device_name, node->device_name, strlen(node->device_name));
+
+ /* Request URI */
+ res = dm_utils_service_name(request.service_prefix, request.service_name,
+ request.product_key, request.device_name, &uri);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_info("DM Send Raw Data:");
+ HEXDUMP_INFO(payload, payload_len);
+
+ res = dm_client_publish(uri, (unsigned char *)payload, strlen(payload), dm_client_thing_model_up_raw_reply);
+#ifdef ALCS_ENABLED
+ res1 = dm_server_send(uri, (unsigned char *)payload, strlen(payload), NULL);
+#endif
+
+ if (res < SUCCESS_RETURN || res1 < SUCCESS_RETURN) {
+ DM_free(uri);
+ return FAIL_RETURN;
+ }
+
+ DM_free(uri);
+ return SUCCESS_RETURN;
+}
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+static int _dm_mgr_upstream_request_assemble(_IN_ int msgid, _IN_ int devid, _IN_ const char *service_prefix,
+ _IN_ const char *service_name,
+ _IN_ char *params, _IN_ int params_len, _IN_ char *method, _OU_ dm_msg_request_t *request)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ request->msgid = msgid;
+ request->devid = devid;
+ request->service_prefix = service_prefix;
+ request->service_name = service_name;
+ memcpy(request->product_key, node->product_key, strlen(node->product_key));
+ memcpy(request->device_name, node->device_name, strlen(node->device_name));
+ request->params = params;
+ request->params_len = params_len;
+ request->method = method;
+
+ return SUCCESS_RETURN;
+}
+#ifdef DEVICE_MODEL_SHADOW
+int dm_mgr_upstream_thing_property_desired_get(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_PROPERTY_DESIRED_GET,
+ payload, payload_len, "thing.property.desired.get", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_property_desired_get_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+ /*TODO */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ int prop_desired_get_reply = 0;
+ res = dm_opt_get(DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY, &prop_desired_get_reply);
+ if (res == SUCCESS_RETURN && prop_desired_get_reply) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_PROPERTY_DESIRED_GET_REPLY, NULL);
+ }
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+
+int dm_mgr_upstream_thing_property_desired_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX,
+ DM_URI_THING_PROPERTY_DESIRED_DELETE,
+ payload, payload_len, "thing.property.desired.delete", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_property_desired_delete_reply;
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ int prop_desired_delete_reply = 0;
+ res = dm_opt_get(DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY, &prop_desired_delete_reply);
+ if (res == SUCCESS_RETURN && prop_desired_delete_reply) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_PROPERTY_DESIRED_DELETE_REPLY, NULL);
+ }
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+#endif
+
+int dm_mgr_upstream_thing_property_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_EVENT_PROPERTY_POST,
+ payload, payload_len, "thing.event.property.post", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_event_post_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_ALL, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ int prop_post_reply = 0;
+ res = dm_opt_get(DM_OPT_DOWNSTREAM_EVENT_POST_REPLY, &prop_post_reply);
+ if (res == SUCCESS_RETURN && prop_post_reply) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY, NULL);
+ }
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+
+#ifdef LOG_REPORT_TO_CLOUD
+static unsigned int log_size = 0;
+int dm_mgr_upstream_thing_log_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len, int force_upload)
+{
+ int res = 0;
+ dm_msg_request_t request;
+ extern REPORT_STATE g_report_status;
+ extern char *g_log_poll;
+
+ if (0 == force_upload) {
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (log_size + payload_len < OVERFLOW_LEN) {
+ log_size = push_log(payload, payload_len);
+ } else {
+ /* it should NOT happen; it means that it is too late to upload log files */
+ reset_log_poll();
+ dm_log_err("it it too late to upload log, reset pool");
+ return FAIL_RETURN;
+ }
+
+ dm_log_info("push log, len is %d, log_size is %d\n", payload_len, log_size);
+ if (!(log_size > REPORT_LEN && DONE == g_report_status)) {
+ return SUCCESS_RETURN;
+ }
+ }
+
+ log_size = add_tail();
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_LOG_POST,
+ g_log_poll, log_size + 1, "thing.log.post", &request);
+
+ if (res != SUCCESS_RETURN) {
+ reset_log_poll();
+ return FAIL_RETURN;
+ }
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+ reset_log_poll();
+ return res;
+}
+#endif
+
+
+
+int dm_mgr_upstream_thing_event_post(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *method,
+ _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, service_name_len = 0;
+ char *service_name = NULL;
+ dm_msg_request_t request;
+
+ if (devid < 0 || identifier == NULL || identifier_len <= 0 ||
+ method == NULL || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ service_name_len = strlen(DM_URI_THING_EVENT_POST) + identifier_len + 1;
+ service_name = DM_malloc(service_name_len);
+ if (service_name == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(service_name, 0, service_name_len);
+ HAL_Snprintf(service_name, service_name_len, DM_URI_THING_EVENT_POST, identifier_len, identifier);
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, service_name,
+ payload, payload_len, method, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_event_post_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_ALL, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ int event_post_reply = 0;
+ res = dm_opt_get(DM_OPT_DOWNSTREAM_EVENT_POST_REPLY, &event_post_reply);
+ if (res == SUCCESS_RETURN && event_post_reply) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY, NULL);
+ }
+ res = request.msgid;
+ }
+#endif
+ DM_free(service_name);
+
+ return res;
+}
+
+
+int dm_mgr_upstream_thing_deviceinfo_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_DEVICEINFO_UPDATE,
+ payload, payload_len, "thing.deviceinfo.update", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_deviceinfo_update_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_DEVICEINFO_UPDATE_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+
+int dm_mgr_upstream_thing_deviceinfo_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0;
+ dm_msg_request_t request;
+
+ if (devid < 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_DEVICEINFO_DELETE,
+ payload, payload_len, "thing.deviceinfo.delete", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_deviceinfo_delete_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_DEVICEINFO_DELETE_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+
+int dm_mgr_upstream_thing_dsltemplate_get(_IN_ int devid)
+{
+ int res = 0;
+ char *params = "{}";
+ int params_len = strlen(params);
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_DSLTEMPLATE_GET,
+ params, params_len, "thing.dsltemplate.get", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_DSLTEMPLATE_GET_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+
+int dm_mgr_upstream_thing_dynamictsl_get(_IN_ int devid)
+{
+ int res = 0;
+ char *params = "{\"nodes\":[\"type\",\"identifier\"],\"addDefault\":false}";
+ int params_len = strlen(params);
+ dm_msg_request_t request;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ res = _dm_mgr_upstream_request_assemble(iotx_report_id(), devid, DM_URI_SYS_PREFIX, DM_URI_THING_DYNAMICTSL_GET,
+ params, params_len, "thing.dynamicTsl.get", &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Callback */
+ request.callback = dm_client_thing_dynamictsl_get_reply;
+
+ /* Send Message To Cloud */
+ res = dm_msg_request(DM_MSG_DEST_CLOUD, &request);
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ if (res == SUCCESS_RETURN) {
+ dm_msg_cache_insert(request.msgid, request.devid, IOTX_DM_EVENT_DSLTEMPLATE_GET_REPLY, NULL);
+ res = request.msgid;
+ }
+#endif
+ return res;
+}
+
+int dm_mgr_upstream_ntp_request(void)
+{
+ int res = 0;
+ const char *ntp_request_fmt = "{\"deviceSendTime\":\"1234\"}";
+ char /* *cloud_payload = NULL, */ *uri = NULL;
+ dm_msg_request_t request;
+
+ memset(&request, 0, sizeof(dm_msg_request_t));
+ request.service_prefix = DM_URI_EXT_NTP_PREFIX;
+ request.service_name = DM_URI_NTP_REQUEST;
+ HAL_GetProductKey(request.product_key);
+ HAL_GetDeviceName(request.device_name);
+
+ /* Request URI */
+ res = dm_utils_service_name(request.service_prefix, request.service_name,
+ request.product_key, request.device_name, &uri);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_client_publish(uri, (unsigned char *)ntp_request_fmt, strlen(ntp_request_fmt), dm_client_ntp_response);
+ if (res != SUCCESS_RETURN) {
+ DM_free(uri); /* DM_free(cloud_payload); */
+ return FAIL_RETURN;
+ }
+
+ DM_free(uri); /* DM_free(cloud_payload); */
+ return SUCCESS_RETURN;
+}
+
+static int _dm_mgr_upstream_response_assemble(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ const char *prefix,
+ _IN_ const char *service_name, _IN_ int code, _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ request->id.value = msgid;
+ request->id.value_length = msgid_len;
+
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = service_name;
+ memcpy(response->product_key, node->product_key, strlen(node->product_key));
+ memcpy(response->device_name, node->device_name, strlen(node->device_name));
+ response->code = code;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_upstream_thing_service_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len, void *ctx)
+{
+ int res = 0, service_name_len = 0;
+ char *service_name = NULL;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ if (devid < 0 || msgid == NULL || msgid_len <= 0 || identifier == NULL || identifier_len <= 0 ||
+ payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Service Name */
+ service_name_len = strlen(DM_URI_THING_SERVICE_RESPONSE) + identifier_len + 1;
+ service_name = DM_malloc(service_name_len);
+ if (service_name == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(service_name, 0, service_name_len);
+ HAL_Snprintf(service_name, service_name_len, DM_URI_THING_SERVICE_RESPONSE, identifier_len, identifier);
+
+ res = _dm_mgr_upstream_response_assemble(devid, msgid, msgid_len, DM_URI_SYS_PREFIX, service_name, code, &request,
+ &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Current Service Name: %s", service_name);
+ if (ctx != NULL) {
+ dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, payload, payload_len, ctx);
+ } else {
+ dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, payload, payload_len, ctx);
+ }
+
+ DM_free(service_name);
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_upstream_thing_property_get_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ iotx_dm_error_code_t code,
+ _IN_ char *payload, _IN_ int payload_len, _IN_ void *ctx)
+{
+ int res = 0;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+ const char *reply_service_name = NULL;
+ dm_msg_dest_type_t reply_msg_type;
+#ifdef ALCS_ENABLED
+ dm_server_alcs_context_t *alcs_context = NULL;
+#endif
+
+ if (devid < 0 || msgid == NULL || msgid_len <= 0 ||
+ payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ /* Send Property Get Response Message To Local */
+ reply_service_name = DM_URI_THING_SERVICE_PROPERTY_GET;
+ reply_msg_type = DM_MSG_DEST_LOCAL;
+
+ /* Send Property Get Response Message To Cloud */
+ if (NULL == ctx) {
+ reply_service_name = DM_URI_THING_SERVICE_PROPERTY_GET_REPLY;
+ reply_msg_type = DM_MSG_DEST_CLOUD;
+ }
+
+ res = _dm_mgr_upstream_response_assemble(devid, msgid, msgid_len, DM_URI_SYS_PREFIX,
+ reply_service_name, code, &request, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Current Service Name: %s", reply_service_name);
+ dm_msg_response(reply_msg_type, &request, &response, payload, payload_len, ctx);
+
+#ifdef ALCS_ENABLED
+ alcs_context = (dm_server_alcs_context_t *)ctx;
+
+ if (alcs_context) {
+ DM_free(alcs_context->ip);
+ DM_free(alcs_context->token);
+ DM_free(alcs_context);
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_upstream_rrpc_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *rrpcid, _IN_ int rrpcid_len, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, service_name_len = 0;
+ const char *rrpc_response_service_name = "rrpc/response/%.*s";
+ char *service_name = NULL;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ if (devid < 0 || msgid == NULL || msgid_len <= 0 ||
+ rrpcid == NULL || rrpcid_len <= 0 || payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Service Name */
+ service_name_len = strlen(rrpc_response_service_name) + rrpcid_len + 1;
+ service_name = DM_malloc(service_name_len);
+ if (service_name == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(service_name, 0, service_name_len);
+ HAL_Snprintf(service_name, service_name_len, rrpc_response_service_name, rrpcid_len, rrpcid);
+
+ res = _dm_mgr_upstream_response_assemble(devid, msgid, msgid_len, DM_URI_SYS_PREFIX, service_name, code, &request,
+ &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Current Service Name: %s", service_name);
+ dm_msg_response(DM_MSG_DEST_ALL, &request, &response, payload, payload_len, NULL);
+
+ DM_free(service_name);
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+#ifdef DEPRECATED_LINKKIT
+int dm_mgr_deprecated_set_tsl_source(_IN_ int devid, _IN_ iotx_dm_tsl_source_t tsl_source)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ node->tsl_source = tsl_source;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_tsl_source(_IN_ int devid, _IN_ iotx_dm_tsl_source_t *tsl_source)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || tsl_source == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ *tsl_source = node->tsl_source;
+
+ return SUCCESS_RETURN;
+}
+
+static int dm_mgr_deprecated_search_devid_by_node(_IN_ dm_mgr_dev_node_t *node, _OU_ int *devid)
+{
+ dm_mgr_ctx *ctx = _dm_mgr_get_ctx();
+ dm_mgr_dev_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &ctx->dev_list, linked_list, dm_mgr_dev_node_t) {
+ if (search_node == node) {
+ /* dm_log_debug("Device Found, node: %p", node); */
+ if (devid) {
+ *devid = search_node->devid;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ dm_log_debug("Device Not Found, node: %p", node);
+ return FAIL_RETURN;
+}
+
+int dm_mgr_deprecated_search_devid_by_device_node(_IN_ void *node, _OU_ int *devid)
+{
+ int res = 0;
+
+ if (node == NULL || devid == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_deprecated_search_devid_by_node((dm_mgr_dev_node_t *)node, devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_set_tsl(int devid, iotx_dm_tsl_type_t tsl_type, const char *tsl, int tsl_len)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (tsl == NULL || tsl_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_create(tsl_type, tsl, tsl_len, &node->dev_shadow);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_property_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_property_data(node->dev_shadow, key, key_len, data);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_service_input_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_service_input_output_data(DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA, node->dev_shadow, key, key_len, data);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_service_output_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_service_input_output_data(DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA, node->dev_shadow, key, key_len,
+ data);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_event_output_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_event_output_data(node->dev_shadow, key, key_len, data);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_data_type(_IN_ void *data, _OU_ dm_shw_data_type_e *type)
+{
+ if (data == NULL || type == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ return dm_shw_get_data_type(data, type);
+}
+
+int dm_mgr_deprecated_get_property_number(_IN_ int devid, _OU_ int *number)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || number == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_property_number(node->dev_shadow, number);
+}
+
+int dm_mgr_deprecated_get_service_number(_IN_ int devid, _OU_ int *number)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || number == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_service_number(node->dev_shadow, number);
+}
+
+int dm_mgr_deprecated_get_event_number(_IN_ int devid, _OU_ int *number)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || number == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_event_number(node->dev_shadow, number);
+}
+
+int dm_mgr_deprecated_get_property_by_index(_IN_ int devid, _IN_ int index, _OU_ void **property)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || index < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_property_by_index(node->dev_shadow, index, property);
+}
+
+int dm_mgr_deprecated_get_service_by_index(_IN_ int devid, _IN_ int index, _OU_ void **service)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || index < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_service_by_index(node->dev_shadow, index, service);
+}
+
+int dm_mgr_deprecated_get_event_by_index(_IN_ int devid, _IN_ int index, _OU_ void **event)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || index < 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_event_by_index(node->dev_shadow, index, event);
+}
+
+int dm_mgr_deprecated_get_service_by_identifier(_IN_ int devid, _IN_ char *identifier, _OU_ void **service)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || identifier == NULL || service == NULL || *service != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_service_by_identifier(node->dev_shadow, identifier, service);
+}
+
+int dm_mgr_deprecated_get_event_by_identifier(_IN_ int devid, _IN_ char *identifier, _OU_ void **event)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || identifier == NULL || event == NULL || *event != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_shw_get_event_by_identifier(node->dev_shadow, identifier, event);
+}
+
+int dm_mgr_deprecated_get_property_identifier(_IN_ void *property, _OU_ char **identifier)
+{
+ if (property == NULL || identifier == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ return dm_shw_get_property_identifier(property, identifier);
+}
+
+int dm_mgr_deprecated_get_service_method(_IN_ void *service, _OU_ char **method)
+{
+ if (service == NULL || method == NULL || *method != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ return dm_shw_get_service_method(service, method);
+}
+
+int dm_mgr_deprecated_get_event_method(_IN_ void *event, _OU_ char **method)
+{
+ if (event == NULL || method == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ return dm_shw_get_event_method(event, method);
+}
+
+int dm_mgr_deprecated_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_set_property_value(node->dev_shadow, key, key_len, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_property_value(node->dev_shadow, key, key_len, value);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_set_event_output_value(node->dev_shadow, key, key_len, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_event_output_value(node->dev_shadow, key, key_len, value);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_set_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_set_service_input_output_value(DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA, node->dev_shadow, key, key_len,
+ value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_service_input_output_value(DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA, node->dev_shadow, key, key_len,
+ value);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_set_service_input_output_value(DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA, node->dev_shadow, key, key_len,
+ value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || key == NULL || key_len <= 0 || value == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_get_service_input_output_value(DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA, node->dev_shadow, key, key_len,
+ value);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_assemble_property(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_assemble_property(node->dev_shadow, identifier, identifier_len, lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_assemble_event_output(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_assemble_event_output(node->dev_shadow, identifier, identifier_len, lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_assemble_service_output(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0;
+ dm_mgr_dev_node_t *node = NULL;
+
+ if (devid < 0 || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_mgr_search_dev_by_devid(devid, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_shw_assemble_service_output(node->dev_shadow, identifier, identifier_len, lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_mgr_deprecated_upstream_thing_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, service_name_len = 0;
+ char *msgid_str = NULL, *service_name = NULL;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ if (devid < 0 || msgid < 0 || identifier == NULL || identifier_len <= 0 ||
+ payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Response Msg ID */
+ res = dm_utils_itoa(msgid, &msgid_str);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ request.id.value = msgid_str;
+ request.id.value_length = strlen(msgid_str);
+
+ /* Service Name */
+ service_name_len = strlen(DM_URI_THING_SERVICE_RESPONSE) + identifier_len + 1;
+ service_name = DM_malloc(service_name_len);
+ if (service_name == NULL) {
+ DM_free(msgid_str);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(service_name, 0, service_name_len);
+ HAL_Snprintf(service_name, service_name_len, DM_URI_THING_SERVICE_RESPONSE, identifier_len, identifier);
+
+ res = _dm_mgr_upstream_response_assemble(devid, msgid_str, strlen(msgid_str), DM_URI_SYS_PREFIX, service_name, code,
+ &request,
+ &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Current Service Name: %s", service_name);
+ dm_msg_response(DM_MSG_DEST_ALL, &request, &response, payload, payload_len, NULL);
+
+ DM_free(msgid_str);
+ DM_free(service_name);
+ return SUCCESS_RETURN;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_manager.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_manager.h
new file mode 100644
index 00000000..40a222f9
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_manager.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_MANAGER_H_
+#define _DM_MANAGER_H_
+
+#include "iotx_dm_internal.h"
+
+typedef struct {
+ int devid;
+ int dev_type;
+#if defined(DEPRECATED_LINKKIT)
+ dm_shw_t *dev_shadow;
+ iotx_dm_tsl_source_t tsl_source;
+#endif
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
+ iotx_dm_dev_avail_t status;
+ iotx_dm_dev_status_t dev_status;
+ struct list_head linked_list;
+} dm_mgr_dev_node_t;
+
+typedef struct {
+ void *mutex;
+ int global_devid;
+ struct list_head dev_list;
+} dm_mgr_ctx;
+
+int dm_mgr_init(void);
+int dm_mgr_deinit(void);
+int dm_mgr_device_create(_IN_ int dev_type, _IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ int *devid);
+int dm_mgr_device_destroy(_IN_ int devid);
+int dm_mgr_device_number(void);
+int dm_mgr_get_devid_by_index(_IN_ int index, _OU_ int *devid);
+int dm_mgr_get_next_devid(_IN_ int devid, _OU_ int *devid_next);
+int dm_mgr_search_device_by_devid(_IN_ int devid, _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
+int dm_mgr_search_device_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ int *devid);
+int dm_mgr_search_device_node_by_devid(_IN_ int devid, _OU_ void **node);
+
+int dm_mgr_get_dev_type(_IN_ int devid, _OU_ int *dev_type);
+int dm_mgr_set_dev_enable(_IN_ int devid);
+int dm_mgr_set_dev_disable(_IN_ int devid);
+int dm_mgr_get_dev_avail(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ iotx_dm_dev_avail_t *status);
+int dm_mgr_set_dev_status(_IN_ int devid, _IN_ iotx_dm_dev_status_t status);
+int dm_mgr_get_dev_status(_IN_ int devid, _OU_ iotx_dm_dev_status_t *status);
+int dm_mgr_set_device_secret(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
+int dm_mgr_dev_initialized(int devid);
+int dm_mgr_upstream_thing_property_desired_get(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int dm_mgr_upstream_thing_property_desired_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+
+#ifdef DEVICE_MODEL_GATEWAY
+ int dm_mgr_upstream_thing_sub_register(_IN_ int devid);
+ int dm_mgr_upstream_thing_sub_unregister(_IN_ int devid);
+ int dm_mgr_upstream_thing_topo_add(_IN_ int devid);
+ int dm_mgr_upstream_thing_topo_delete(_IN_ int devid);
+ int dm_mgr_upstream_thing_topo_get(void);
+ int dm_mgr_upstream_thing_list_found(_IN_ int devid);
+ int dm_mgr_upstream_combine_login(_IN_ int devid);
+ int dm_mgr_upstream_combine_logout(_IN_ int devid);
+#endif
+int dm_mgr_upstream_thing_model_up_raw(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+int dm_mgr_upstream_thing_property_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+#ifdef LOG_REPORT_TO_CLOUD
+ int dm_mgr_upstream_thing_log_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len, int force_update);
+#endif
+int dm_mgr_upstream_thing_event_post(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *method,
+ _IN_ char *payload, _IN_ int payload_len);
+int dm_mgr_upstream_thing_deviceinfo_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int dm_mgr_upstream_thing_deviceinfo_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int dm_mgr_upstream_thing_dsltemplate_get(_IN_ int devid);
+int dm_mgr_upstream_thing_dynamictsl_get(_IN_ int devid);
+int dm_mgr_upstream_ntp_request(void);
+int dm_mgr_upstream_thing_service_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len, void *ctx);
+int dm_mgr_upstream_thing_property_get_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ iotx_dm_error_code_t code,
+ _IN_ char *payload, _IN_ int payload_len, _IN_ void *ctx);
+int dm_mgr_upstream_rrpc_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *rrpcid, _IN_ int rrpcid_len, _IN_ char *payload, _IN_ int payload_len);
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+ int dm_mgr_upstream_thing_firmware_version_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+#endif
+#endif
+#ifdef DEPRECATED_LINKKIT
+int dm_mgr_deprecated_set_tsl_source(_IN_ int devid, _IN_ iotx_dm_tsl_source_t tsl_source);
+int dm_mgr_deprecated_get_tsl_source(_IN_ int devid, _IN_ iotx_dm_tsl_source_t *tsl_source);
+int dm_mgr_deprecated_search_devid_by_device_node(_IN_ void *node, _OU_ int *devid);
+int dm_mgr_deprecated_set_tsl(int devid, iotx_dm_tsl_type_t tsl_type, const char *tsl, int tsl_len);
+int dm_mgr_deprecated_get_property_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+int dm_mgr_deprecated_get_service_input_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+int dm_mgr_deprecated_get_service_output_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+int dm_mgr_deprecated_get_event_output_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+int dm_mgr_deprecated_get_data_type(_IN_ void *property, _OU_ dm_shw_data_type_e *type);
+int dm_mgr_deprecated_get_property_number(_IN_ int devid, _OU_ int *number);
+int dm_mgr_deprecated_get_service_number(_IN_ int devid, _OU_ int *number);
+int dm_mgr_deprecated_get_event_number(_IN_ int devid, _OU_ int *number);
+int dm_mgr_deprecated_get_property_by_index(_IN_ int devid, _IN_ int index, _OU_ void **property);
+int dm_mgr_deprecated_get_service_by_index(_IN_ int devid, _IN_ int index, _OU_ void **service);
+int dm_mgr_deprecated_get_event_by_index(_IN_ int devid, _IN_ int index, _OU_ void **event);
+int dm_mgr_deprecated_get_service_by_identifier(_IN_ int devid, _IN_ char *identifier, _OU_ void **service);
+int dm_mgr_deprecated_get_event_by_identifier(_IN_ int devid, _IN_ char *identifier, _OU_ void **event);
+int dm_mgr_deprecated_get_property_identifier(_IN_ void *property, _OU_ char **identifier);
+int dm_mgr_deprecated_get_service_method(_IN_ void *service, _OU_ char **method);
+int dm_mgr_deprecated_get_event_method(_IN_ void *event, _OU_ char **method);
+int dm_mgr_deprecated_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int dm_mgr_deprecated_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int dm_mgr_deprecated_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int dm_mgr_deprecated_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int dm_mgr_deprecated_set_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int dm_mgr_deprecated_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int dm_mgr_deprecated_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int dm_mgr_deprecated_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int dm_mgr_deprecated_assemble_property(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite);
+int dm_mgr_deprecated_assemble_event_output(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite);
+int dm_mgr_deprecated_assemble_service_output(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite);
+int dm_mgr_deprecated_upstream_thing_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len);
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message.c
new file mode 100644
index 00000000..eb66391c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message.c
@@ -0,0 +1,2547 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_dm_internal.h"
+
+static dm_msg_ctx_t g_dm_msg_ctx;
+
+static dm_msg_ctx_t *_dm_msg_get_ctx(void)
+{
+ return &g_dm_msg_ctx;
+}
+
+int dm_msg_init(void)
+{
+ dm_msg_ctx_t *ctx = _dm_msg_get_ctx();
+ memset(ctx, 0, sizeof(dm_msg_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_deinit(void)
+{
+ dm_msg_ctx_t *ctx = _dm_msg_get_ctx();
+ memset(ctx, 0, sizeof(dm_msg_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+int _dm_msg_send_to_user(iotx_dm_event_types_t type, char *message)
+{
+ int res = 0;
+ dm_ipc_msg_t *dipc_msg = NULL;
+
+ dipc_msg = DM_malloc(sizeof(dm_ipc_msg_t));
+ if (dipc_msg == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(dipc_msg, 0, sizeof(dm_ipc_msg_t));
+
+ dipc_msg->type = type;
+ dipc_msg->data = message;
+
+ res = dm_ipc_msg_insert((void *)dipc_msg);
+ if (res != SUCCESS_RETURN) {
+ DM_free(dipc_msg);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_SEND_MSG_TIMEOUT_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_send_msg_timeout_to_user(int msg_id, int devid, iotx_dm_event_types_t type)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+
+ message_len = strlen(DM_MSG_SEND_MSG_TIMEOUT_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len + 1);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_SEND_MSG_TIMEOUT_FMT, msg_id, IOTX_DM_ERR_CODE_TIMEOUT, devid);
+
+ res = _dm_msg_send_to_user(type, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_uri_parse_pkdn(_IN_ char *uri, _IN_ int uri_len, _IN_ int start_deli, _IN_ int end_deli,
+ _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0, start = 0, end = 0, slice = 0;
+
+ if (uri == NULL || uri_len <= 0 || product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) || (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(uri, uri_len, DM_URI_SERVICE_DELIMITER, start_deli, &start);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_memtok(uri, uri_len, DM_URI_SERVICE_DELIMITER, start_deli + 1, &slice);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_memtok(uri, uri_len, DM_URI_SERVICE_DELIMITER, end_deli, &end);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* dm_log_debug("URI Product Key: %.*s, Device Name: %.*s", slice - start - 1, uri + start + 1, end - slice - 1,
+ uri + slice + 1); */
+
+ memcpy(product_key, uri + start + 1, slice - start - 1);
+ memcpy(device_name, uri + slice + 1, end - slice - 1);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_request_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_request_payload_t *request)
+{
+ lite_cjson_t lite;
+
+ if (payload == NULL || payload_len <= 0 || request == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_ID, strlen(DM_MSG_KEY_ID), cJSON_String, &request->id) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_VERSION, strlen(DM_MSG_KEY_VERSION), cJSON_String,
+ &request->version) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_METHOD, strlen(DM_MSG_KEY_METHOD), cJSON_String,
+ &request->method) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_PARAMS, strlen(DM_MSG_KEY_PARAMS), cJSON_Invalid,
+ &request->params) != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Current Request Message ID: %.*s", request->id.value_length, request->id.value);
+ dm_log_debug("Current Request Message Version: %.*s", request->version.value_length, request->version.value);
+ dm_log_debug("Current Request Message Method: %.*s", request->method.value_length, request->method.value);
+ dm_log_debug("Current Request Message Params: %.*s", request->params.value_length, request->params.value);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_response_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_response_payload_t *response)
+{
+ lite_cjson_t lite, lite_message;
+
+ if (payload == NULL || payload_len <= 0 || response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_ID, strlen(DM_MSG_KEY_ID), cJSON_String, &response->id) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_CODE, strlen(DM_MSG_KEY_CODE), cJSON_Number,
+ &response->code) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_DATA, strlen(DM_MSG_KEY_DATA), cJSON_Invalid,
+ &response->data) != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Current Request Message ID: %.*s", response->id.value_length, response->id.value);
+ dm_log_debug("Current Request Message Code: %d", response->code.value_int);
+ dm_log_debug("Current Request Message Data: %.*s", response->data.value_length, response->data.value);
+
+ memset(&lite_message, 0, sizeof(lite_cjson_t));
+ if (dm_utils_json_object_item(&lite, DM_MSG_KEY_MESSAGE, strlen(DM_MSG_KEY_MESSAGE), cJSON_Invalid,
+ &response->message) == SUCCESS_RETURN) {
+ dm_log_debug("Current Request Message Desc: %.*s", response->message.value_length, response->message.value);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_REQUEST[] DM_READ_ONLY = "{\"id\":\"%d\",\"version\":\"%s\",\"params\":%.*s,\"method\":\"%s\"}";
+int dm_msg_request(dm_msg_dest_type_t type, _IN_ dm_msg_request_t *request)
+{
+ int res = 0, payload_len = 0;
+ char *payload = NULL, *uri = NULL;
+ lite_cjson_t lite;
+
+ if (request == NULL || request->params == NULL || request->method == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Request URI */
+ res = dm_utils_service_name(request->service_prefix, request->service_name,
+ request->product_key, request->device_name, &uri);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ payload_len = strlen(DM_MSG_REQUEST) + 10 + strlen(DM_MSG_VERSION) + request->params_len + strlen(
+ request->method) + 1;
+ payload = DM_malloc(payload_len);
+ if (payload == NULL) {
+ DM_free(uri);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(payload, 0, payload_len);
+ HAL_Snprintf(payload, payload_len, DM_MSG_REQUEST, request->msgid,
+ DM_MSG_VERSION, request->params_len, request->params, request->method);
+
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, payload_len, &lite);
+ if (res < SUCCESS_RETURN) {
+ dm_log_info("Wrong JSON Format, URI: %s, Payload: %s", uri, payload);
+ DM_free(uri);
+ DM_free(payload);
+ return FAIL_RETURN;
+ }
+
+ dm_log_info("DM Send Message, URI: %s, Payload: %s", uri, payload);
+
+ if (type & DM_MSG_DEST_CLOUD) {
+ dm_client_publish(uri, (unsigned char *)payload, strlen(payload), request->callback);
+ }
+
+#ifdef ALCS_ENABLED
+ if (type & DM_MSG_DEST_LOCAL) {
+ dm_server_send(uri, (unsigned char *)payload, strlen(payload), NULL);
+ }
+#endif
+
+ DM_free(uri);
+ DM_free(payload);
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_RESPONSE_WITH_DATA[] DM_READ_ONLY = "{\"id\":\"%.*s\",\"code\":%d,\"data\":%.*s}";
+int dm_msg_response(dm_msg_dest_type_t type, _IN_ dm_msg_request_payload_t *request, _IN_ dm_msg_response_t *response,
+ _IN_ char *data, _IN_ int data_len, _IN_ void *user_data)
+{
+ int res = 0, payload_len = 0;
+ char *uri = NULL, *payload = NULL;
+ lite_cjson_t lite;
+
+ if (request == NULL || response == NULL || data == NULL || data_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Response URI */
+ res = dm_utils_service_name(response->service_prefix, response->service_name,
+ response->product_key, response->device_name, &uri);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Response Payload */
+ payload_len = strlen(DM_MSG_RESPONSE_WITH_DATA) + request->id.value_length + DM_UTILS_UINT32_STRLEN + data_len + 1;
+ payload = DM_malloc(payload_len);
+ if (payload == NULL) {
+ DM_free(uri);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(payload, 0, payload_len);
+ HAL_Snprintf(payload, payload_len, DM_MSG_RESPONSE_WITH_DATA,
+ request->id.value_length, request->id.value, response->code, data_len, data);
+
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, payload_len, &lite);
+ if (res < SUCCESS_RETURN) {
+ dm_log_info("Wrong JSON Format, URI: %s, Payload: %s", uri, payload);
+ DM_free(uri);
+ DM_free(payload);
+ return FAIL_RETURN;
+ }
+
+ dm_log_info("Send URI: %s, Payload: %s", uri, payload);
+
+ if (type & DM_MSG_DEST_CLOUD) {
+ dm_client_publish(uri, (unsigned char *)payload, strlen(payload), NULL);
+ }
+
+#ifdef ALCS_ENABLED
+ if (type & DM_MSG_DEST_LOCAL) {
+ char *end = NULL;
+ do {
+ if (strlen(uri) < 6) {
+ break;
+ }
+ end = uri + strlen(uri) - 6;
+ if (strstr(end, "_reply") != 0) {
+ *end = '\0';
+ }
+ dm_server_send(uri, (unsigned char *)payload, strlen(payload), user_data);
+ } while (0);
+
+ }
+#endif
+
+ DM_free(uri);
+ DM_free(payload);
+
+ return SUCCESS_RETURN;
+}
+
+
+const char DM_MSG_THING_MODEL_DOWN_FMT[] DM_READ_ONLY = "{\"devid\":%d,\"payload\":\"%.*s\"}";
+int dm_msg_thing_model_down_raw(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, devid = 0, message_len = 0;
+ char *hexstr = NULL, *message = NULL;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_hex_to_str((unsigned char *)payload, payload_len, &hexstr);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ message_len = strlen(DM_MSG_THING_MODEL_DOWN_FMT) + DM_UTILS_UINT32_STRLEN + strlen(hexstr) + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ DM_free(hexstr);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_THING_MODEL_DOWN_FMT, devid, strlen(hexstr), hexstr);
+ DM_free(hexstr);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_MODEL_DOWN_RAW, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+
+const char DM_MSG_THING_MODEL_UP_RAW_REPLY_FMT[] DM_READ_ONLY = "{\"devid\":%d,\"payload\":\"%.*s\"}";
+int dm_msg_thing_model_up_raw_reply(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], char *payload, int payload_len)
+{
+ int res = 0, devid = 0, message_len = 0;
+ char *hexstr = NULL, *message = NULL;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_hex_to_str((unsigned char *)payload, payload_len, &hexstr);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ message_len = strlen(DM_MSG_THING_MODEL_DOWN_FMT) + DM_UTILS_UINT32_STRLEN + strlen(hexstr) + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ DM_free(hexstr);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_THING_MODEL_DOWN_FMT, devid, strlen(hexstr), hexstr);
+ DM_free(hexstr);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_MODEL_UP_RAW_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+#ifndef DEPRECATED_LINKKIT
+#ifdef LOG_REPORT_TO_CLOUD
+ const char DM_MSG_PROPERTY_SET_FMT[] DM_READ_ONLY = "{\"devid\":%d,\"payload\":%.*s,\"msgid\":%.*s}";
+#else
+ const char DM_MSG_PROPERTY_SET_FMT[] DM_READ_ONLY = "{\"devid\":%d,\"payload\":%.*s}";
+#endif
+int dm_msg_property_set(int devid, dm_msg_request_payload_t *request)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+
+ message_len = strlen(DM_MSG_PROPERTY_SET_FMT) + DM_UTILS_UINT32_STRLEN + request->params.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+#ifdef LOG_REPORT_TO_CLOUD
+ HAL_Snprintf(message, message_len, DM_MSG_PROPERTY_SET_FMT, devid, request->params.value_length, request->params.value,
+ request->id.value_length, request->id.value);
+#else
+ HAL_Snprintf(message, message_len, DM_MSG_PROPERTY_SET_FMT, devid, request->params.value_length, request->params.value);
+#endif
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_PROPERTY_SET, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_PROPERTY_GET_FMT[] DM_READ_ONLY =
+ "{\"id\":\"%.*s\",\"devid\":%d,\"payload\":%.*s,\"ctx\":\"%s\"}";
+int dm_msg_property_get(_IN_ int devid, _IN_ dm_msg_request_payload_t *request, _IN_ void *ctx)
+{
+ int res = 0, message_len = 0;
+ uintptr_t ctx_addr_num = (uintptr_t)ctx;
+ char *ctx_addr_str = NULL, *message = NULL;
+
+ ctx_addr_str = DM_malloc(sizeof(uintptr_t) * 2 + 1);
+ if (ctx_addr_str == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(ctx_addr_str, 0, sizeof(uintptr_t) * 2 + 1);
+
+ /* dm_log_debug("ctx: %p", ctx);
+ dm_log_debug("ctx_addr_num: %0x016llX", ctx_addr_num); */
+ infra_hex2str((unsigned char *)&ctx_addr_num, sizeof(uintptr_t), ctx_addr_str);
+ /* dm_log_debug("ctx_addr_str: %s", ctx_addr_str); */
+
+ message_len = strlen(DM_MSG_THING_PROPERTY_GET_FMT) + request->id.value_length + DM_UTILS_UINT32_STRLEN +
+ request->params.value_length + strlen(ctx_addr_str) + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ DM_free(ctx_addr_str);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_THING_PROPERTY_GET_FMT, request->id.value_length, request->id.value, devid,
+ request->params.value_length, request->params.value, ctx_addr_str);
+
+ DM_free(ctx_addr_str);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_PROPERTY_GET, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_SERVICE_REQUEST_FMT[] DM_READ_ONLY =
+ "{\"id\":\"%.*s\",\"devid\":%d,\"serviceid\":\"%.*s\",\"payload\":%.*s,\"ctx\":\"%s\"}";
+int dm_msg_thing_service_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ char *identifier, int identifier_len, dm_msg_request_payload_t *request, _IN_ void *ctx)
+{
+ int res = 0, devid = 0, message_len = 0;
+ char *message = NULL;
+ uintptr_t ctx_addr_num = (uintptr_t)ctx;
+ char *ctx_addr_str = NULL;
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+#ifdef LOG_REPORT_TO_CLOUD
+ if (0 == strncmp(identifier, "SetProfilerOptions", identifier_len)) {
+ extern void parse_switch_info(const char *input, int len);
+ parse_switch_info(request->params.value, request->params.value_length);
+ return SUCCESS_RETURN;
+ }
+#endif
+
+ ctx_addr_str = DM_malloc(sizeof(uintptr_t) * 2 + 1);
+ if (ctx_addr_str == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(ctx_addr_str, 0, sizeof(uintptr_t) * 2 + 1);
+ infra_hex2str((unsigned char *)&ctx_addr_num, sizeof(uintptr_t), ctx_addr_str);
+
+ message_len = strlen(DM_MSG_SERVICE_REQUEST_FMT) + request->id.value_length + DM_UTILS_UINT32_STRLEN + identifier_len +
+ request->params.value_length + strlen(ctx_addr_str) + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ DM_free(ctx_addr_str);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_SERVICE_REQUEST_FMT, request->id.value_length, request->id.value, devid,
+ identifier_len, identifier,
+ request->params.value_length, request->params.value, ctx_addr_str);
+
+ DM_free(ctx_addr_str);
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_THING_SERVICE_REQUEST, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+const char DM_MSG_EVENT_RRPC_REQUEST_FMT[] DM_READ_ONLY =
+ "{\"id\":\"%.*s\",\"devid\":%d,\"serviceid\":\"%.*s\",\"rrpcid\":\"%.*s\",\"payload\":%.*s}";
+int dm_msg_rrpc_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ char *rrpcid, int rrpcid_len, dm_msg_request_payload_t *request)
+{
+ int res = 0, devid = 0, message_len = 0;
+ int service_offset = 0, serviceid_len = 0;
+ char *serviceid = NULL, *message = NULL;
+
+ /* Get Devid */
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Get Service ID */
+ res = dm_utils_memtok(request->method.value, request->method.value_length, '.', 2, &service_offset);
+ if (res != SUCCESS_RETURN || service_offset >= request->method.value_length - 1) {
+ return FAIL_RETURN;
+ }
+ serviceid_len = request->method.value_length - service_offset - 1;
+ serviceid = request->method.value + service_offset + 1;
+ /* dm_log_info("Current RRPC Service ID: %.*s", serviceid_len, serviceid); */
+
+ /* Send Message To User */
+ message_len = strlen(DM_MSG_EVENT_RRPC_REQUEST_FMT) + request->id.value_length + DM_UTILS_UINT32_STRLEN + serviceid_len
+ + rrpcid_len +
+ request->params.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_RRPC_REQUEST_FMT, request->id.value_length, request->id.value, devid,
+ serviceid_len, serviceid, rrpcid_len, rrpcid,
+ request->params.value_length, request->params.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_RRPC_REQUEST, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_PROPERTY_POST_REPLY_FMT[] DM_READ_ONLY =
+ "{\"id\":%d,\"code\":%d,\"devid\":%d,\"payload\":%.*s}";
+int dm_msg_thing_event_property_post_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id = 0, message_len = 0, payload_len = 0;
+ char *message = NULL, *payload = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ if ((strlen("success") == response->message.value_length) &&
+ (memcmp("success", response->message.value, response->message.value_length) == 0)) {
+ payload = response->data.value;
+ payload_len = response->data.value_length;
+ } else {
+ payload = response->message.value;
+ payload_len = response->message.value_length;
+ }
+
+ message_len = strlen(DM_MSG_EVENT_PROPERTY_POST_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + payload_len +
+ 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_PROPERTY_POST_REPLY_FMT, id, response->code.value_int, devid,
+ payload_len, payload);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_SPECIFIC_POST_REPLY_FMT[] DM_READ_ONLY =
+ "{\"id\":%d,\"code\":%d,\"devid\":%d,\"eventid\":\"%.*s\",\"payload\":\"%.*s\"}";
+int dm_msg_thing_event_post_reply(_IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id = 0, message_len = 0;
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_SPECIFIC_POST_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + strlen(
+ identifier) + response->message.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_SPECIFIC_POST_REPLY_FMT, id, response->code.value_int, devid,
+ identifier_len, identifier, response->message.value_length, response->message.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_EVENT_SPECIFIC_POST_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+#ifdef DEVICE_MODEL_SHADOW
+const char DM_MSG_EVENT_PROPERTY_DESIRED_GET_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"data\":%.*s}";
+int dm_msg_thing_property_desired_get_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, id = 0, message_len = 0;
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_PROPERTY_DESIRED_GET_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 2 + 1 +
+ response->data.value_length;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_PROPERTY_DESIRED_GET_REPLY_FMT, id, response->code.value_int,
+ response->data.value_length, response->data.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_PROPERTY_DESIRED_GET_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_PROPERTY_DESIRED_DELETE_REPLY_FMT[] DM_READ_ONLY =
+ "{\"id\":%d,\"code\":%d,\"data\":%.*s,\"devid\":%d}";
+int dm_msg_thing_property_desired_delete_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, id = 0, devid = 0, message_len = 0;
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_PROPERTY_DESIRED_DELETE_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1 +
+ response->data.value_length;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_PROPERTY_DESIRED_DELETE_REPLY_FMT, id, response->code.value_int,
+ response->data.value_length, response->data.value, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_PROPERTY_DESIRED_DELETE_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+
+const char DM_MSG_EVENT_DEVICEINFO_UPDATE_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_thing_deviceinfo_update_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id = 0, message_len = 0;
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_DEVICEINFO_UPDATE_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_DEVICEINFO_UPDATE_REPLY_FMT, id, response->code.value_int, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_DEVICEINFO_UPDATE_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_DEVICEINFO_DELETE_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_thing_deviceinfo_delete_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id = 0, message_len = 0;
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_DEVICEINFO_DELETE_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_DEVICEINFO_DELETE_REPLY_FMT, id, response->code.value_int, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_DEVICEINFO_DELETE_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_thing_dsltemplate_get_reply(dm_msg_response_payload_t *response)
+{
+#ifdef DEPRECATED_LINKKIT
+ int res = 0, devid = 0, id = 0;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ dm_mgr_deprecated_set_tsl(devid, IOTX_DM_TSL_TYPE_ALINK, (const char *)response->data.value,
+ response->data.value_length);
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_thing_dynamictsl_get_reply(dm_msg_response_payload_t *response)
+{
+#ifdef DEPRECATED_LINKKIT
+ int res = 0, devid = 0, id = 0;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ dm_mgr_deprecated_set_tsl(devid, IOTX_DM_TSL_TYPE_ALINK, (const char *)response->data.value,
+ response->data.value_length);
+ dm_mgr_dev_initialized(devid);
+#endif
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_NTP_RESPONSE_FMT[] DM_READ_ONLY = "{\"utc\":\"%.*s\"}";
+int dm_msg_ntp_response(char *payload, int payload_len)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+ lite_cjson_t lite, lite_item_server_send_time;
+ const char *serverSendTime = "serverSendTime";
+
+ if (payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite) != SUCCESS_RETURN ||
+ dm_utils_json_object_item(&lite, serverSendTime, strlen(serverSendTime), cJSON_String,
+ &lite_item_server_send_time) != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* dm_log_debug("NTP Time In String: %.*s", lite_item_server_send_time.value_length, lite_item_server_send_time.value); */
+
+ /* Send Message To User */
+ message_len = strlen(DM_MSG_THING_NTP_RESPONSE_FMT) + DM_UTILS_UINT32_STRLEN + lite_item_server_send_time.value_length +
+ 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_THING_NTP_RESPONSE_FMT, lite_item_server_send_time.value_length,
+ lite_item_server_send_time.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_NTP_RESPONSE, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_ext_error_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0;
+ lite_cjson_t lite, lite_item_pk, lite_item_dn;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_json_parse(response->data.value, response->data.value_length, cJSON_Invalid, &lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_PRODUCT_KEY, strlen(DM_MSG_KEY_PRODUCT_KEY), cJSON_Invalid, &lite_item_pk);
+ dm_utils_json_object_item(&lite, DM_MSG_KEY_DEVICE_NAME, strlen(DM_MSG_KEY_DEVICE_NAME), cJSON_Invalid, &lite_item_dn);
+ if (lite_item_pk.type != cJSON_String || lite_item_dn.type != cJSON_String) {
+ return FAIL_RETURN;
+ }
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+ memcpy(device_name, lite_item_dn.value, lite_item_dn.value_length);
+
+ /* Get Device Id */
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Login again if error code is 520 */
+ if (response->code.value_int == IOTX_DM_ERR_CODE_NO_ACTIVE_SESSION) {
+ dm_log_err("log in again test\r\n");
+#ifdef DEVICE_MODEL_GATEWAY
+ dm_mgr_upstream_combine_login(devid);
+#endif
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+const char DM_MSG_TOPO_ADD_NOTIFY_USER_PAYLOAD[] DM_READ_ONLY =
+ "{\"result\":%d,\"devid\":%d,\"product_key\":\"%s\",\"device_name\":\"%s\"}";
+int dm_msg_topo_add_notify(_IN_ char *payload, _IN_ int payload_len)
+{
+ int ret = SUCCESS_RETURN, res = 0, index = 0, devid = 0, message_len = 0;
+ lite_cjson_t lite, lite_item, lite_item_pk, lite_item_dn;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char *message = NULL;
+
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, payload_len, &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_array(&lite)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ for (index = 0; index < lite.size; index++) {
+ devid = 0;
+ message_len = 0;
+ message = NULL;
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ memset(&lite_item_pk, 0, sizeof(lite_cjson_t));
+ memset(&lite_item_dn, 0, sizeof(lite_cjson_t));
+ memset(product_key, 0, IOTX_PRODUCT_KEY_LEN + 1);
+ memset(device_name, 0, IOTX_DEVICE_NAME_LEN + 1);
+
+ res = lite_cjson_array_item(&lite, index, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ ret = FAIL_RETURN;
+ continue;
+ }
+
+ res = lite_cjson_object_item(&lite_item, DM_MSG_KEY_PRODUCT_KEY, strlen(DM_MSG_KEY_PRODUCT_KEY), &lite_item_pk);
+ if (res != SUCCESS_RETURN) {
+ ret = FAIL_RETURN;
+ continue;
+ }
+
+ res = lite_cjson_object_item(&lite_item, DM_MSG_KEY_DEVICE_NAME, strlen(DM_MSG_KEY_DEVICE_NAME), &lite_item_dn);
+ if (res != SUCCESS_RETURN) {
+ ret = FAIL_RETURN;
+ continue;
+ }
+
+ /* dm_log_debug("Current Product Key: %.*s, Device Name: %.*s",
+ lite_item_pk.value_length, lite_item_pk.value,
+ lite_item_dn.value_length, lite_item_dn.value); */
+
+ if (lite_item_pk.value_length >= IOTX_PRODUCT_KEY_LEN + 1 ||
+ lite_item_dn.value_length >= IOTX_DEVICE_NAME_LEN + 1) {
+ ret = FAIL_RETURN;
+ continue;
+ }
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+ memcpy(device_name, lite_item_dn.value, lite_item_dn.value_length);
+
+ res = dm_mgr_device_create(IOTX_DM_DEVICE_SUBDEV, product_key, device_name, NULL, &devid);
+ if (res != SUCCESS_RETURN) {
+ ret = FAIL_RETURN;
+ }
+
+ /* Send To User */
+ message_len = strlen(DM_MSG_TOPO_ADD_NOTIFY_USER_PAYLOAD) + 20 +
+ strlen(product_key) + strlen(device_name) + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ ret = DM_MEMORY_NOT_ENOUGH;
+ continue;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_TOPO_ADD_NOTIFY_USER_PAYLOAD, res, devid, product_key, device_name);
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_TOPO_ADD_NOTIFY, message);
+ if (res != SUCCESS_RETURN) {
+ ret = FAIL_RETURN;
+ DM_free(message);
+ }
+
+ }
+
+ return ret;
+}
+
+const char DM_MSG_EVENT_THING_DISABLE_FMT[] DM_READ_ONLY = "{\"devid\":%d}";
+int dm_msg_thing_disable(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0, devid = 0, message_len = 0;
+ char *message = NULL;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_set_dev_disable(devid);
+
+ message_len = strlen(DM_MSG_EVENT_THING_DISABLE_FMT) + DM_UTILS_UINT32_STRLEN + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_THING_DISABLE_FMT, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_THING_DISABLE, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_THING_ENABLE_FMT[] DM_READ_ONLY = "{\"devid\":%d}";
+int dm_msg_thing_enable(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0, devid = 0, message_len = 0;
+ char *message = NULL;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_set_dev_enable(devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ message_len = strlen(DM_MSG_EVENT_THING_ENABLE_FMT) + DM_UTILS_UINT32_STRLEN + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_THING_ENABLE_FMT, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_THING_ENABLE, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_THING_DELETE_FMT[] DM_READ_ONLY =
+ "{\"res\":%d,\"productKey\":\"%s\",\"deviceName\":\"%s\",\"devid\":%d}";
+int dm_msg_thing_delete(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0, message_len = 0, devid = 0;
+ char *message = NULL;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res == SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_device_destroy(devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ message_len = strlen(DM_MSG_EVENT_THING_DELETE_FMT) + strlen(product_key) + strlen(device_name) + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_THING_DELETE_FMT, res, product_key, device_name, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_THING_DELETE, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_thing_gateway_permit(_IN_ char *payload, _IN_ int payload_len)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+ lite_cjson_t lite;
+
+ if (payload == NULL || payload_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = lite_cjson_parse(payload, payload_len, &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ message_len = payload_len + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memcpy(message, payload, payload_len);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_GATEWAY_PERMIT, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_SUBDEV_REGISTER_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_thing_sub_register_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, index = 0, message_len = 0, devid = 0;
+ lite_cjson_t lite, lite_item, lite_item_pk, lite_item_dn, lite_item_ds;
+ char *message = NULL;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+ char temp_id[DM_UTILS_UINT32_STRLEN] = {0};
+
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = lite_cjson_parse(response->data.value, response->data.value_length, &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_array(&lite)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ for (index = 0; index < lite.size; index++) {
+ devid = 0;
+ message_len = 0;
+ message = NULL;
+ memset(temp_id, 0, DM_UTILS_UINT32_STRLEN);
+ memset(product_key, 0, IOTX_PRODUCT_KEY_LEN + 1);
+ memset(device_name, 0, IOTX_DEVICE_NAME_LEN + 1);
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ memset(&lite_item_pk, 0, sizeof(lite_cjson_t));
+ memset(&lite_item_dn, 0, sizeof(lite_cjson_t));
+ memset(&lite_item_ds, 0, sizeof(lite_cjson_t));
+
+ /* dm_log_debug("Current Index: %d", index); */
+ /* Item */
+ res = lite_cjson_array_item(&lite, index, &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ continue;
+ }
+
+ /* Product Key */
+ res = lite_cjson_object_item(&lite_item, DM_MSG_KEY_PRODUCT_KEY, strlen(DM_MSG_KEY_PRODUCT_KEY), &lite_item_pk);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_pk)) {
+ continue;
+ }
+ /* dm_log_debug("Current Product Key: %.*s", lite_item_pk.value_length, lite_item_pk.value); */
+
+ /* Device Name */
+ res = lite_cjson_object_item(&lite_item, DM_MSG_KEY_DEVICE_NAME, strlen(DM_MSG_KEY_DEVICE_NAME), &lite_item_dn);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_dn)) {
+ continue;
+ }
+ /* dm_log_debug("Current Device Name: %.*s", lite_item_dn.value_length, lite_item_dn.value); */
+
+ /* Device Secret */
+ res = lite_cjson_object_item(&lite_item, DM_MSG_KEY_DEVICE_SECRET, strlen(DM_MSG_KEY_DEVICE_SECRET), &lite_item_ds);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_ds)) {
+ continue;
+ }
+ /* dm_log_debug("Current Device Secret: %.*s", lite_item_ds.value_length, lite_item_ds.value); */
+
+ /* Get Device ID */
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+ memcpy(device_name, lite_item_dn.value, lite_item_dn.value_length);
+ memcpy(device_secret, lite_item_ds.value, lite_item_ds.value_length);
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ /* Update State Machine */
+ if (response->code.value_int == IOTX_DM_ERR_CODE_SUCCESS) {
+ dm_mgr_set_dev_status(devid, IOTX_DM_DEV_STATUS_REGISTERED);
+ }
+
+ /* Set Device Secret */
+ res = dm_mgr_set_device_secret(devid, device_secret);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ /* Send Message To User */
+ memcpy(temp_id, response->id.value, response->id.value_length);
+ message_len = strlen(DM_MSG_EVENT_SUBDEV_REGISTER_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 2 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ dm_log_warning("Memory Not Enough");
+ continue;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_SUBDEV_REGISTER_REPLY_FMT, atoi(temp_id), response->code.value_int,
+ devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_SUBDEV_REGISTER_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_SUBDEV_UNREGISTER_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_thing_sub_unregister_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id, message_len = 0;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+ char *message = NULL;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_SUBDEV_UNREGISTER_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_SUBDEV_UNREGISTER_REPLY_FMT, id, response->code.value_int, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_SUBDEV_UNREGISTER_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_THING_TOPO_ADD_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_thing_topo_add_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id = 0, message_len = 0;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+ char *message = NULL;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+
+ /* Update State Machine */
+ if (response->code.value_int == IOTX_DM_ERR_CODE_SUCCESS) {
+ dm_mgr_set_dev_status(node->devid, IOTX_DM_DEV_STATUS_ATTACHED);
+ }
+
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_THING_TOPO_ADD_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_THING_TOPO_ADD_REPLY_FMT, id, response->code.value_int, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_TOPO_ADD_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_THING_TOPO_DELETE_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_thing_topo_delete_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, devid = 0, id = 0, message_len = 0;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+ char *message = NULL;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ dm_msg_cache_node_t *node = NULL;
+#endif
+
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ res = dm_msg_cache_search(id, &node);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ devid = node->devid;
+
+ /* Update State Machine */
+ if (response->code.value_int == IOTX_DM_ERR_CODE_SUCCESS) {
+ dm_mgr_set_dev_status(node->devid, IOTX_DM_DEV_STATUS_ATTACHED);
+ }
+
+#endif
+
+ message_len = strlen(DM_MSG_EVENT_THING_TOPO_DELETE_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_THING_TOPO_DELETE_REPLY_FMT, id, response->code.value_int, devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_TOPO_DELETE_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_TOPO_GET_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d,\"topo\":%.*s}";
+int dm_msg_topo_get_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, id = 0, message_len = 0;
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Message ID */
+ if (response->id.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(int_id, response->id.value, response->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+ message_len = strlen(DM_MSG_TOPO_GET_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + response->data.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_TOPO_GET_REPLY_FMT, id, response->code.value_int, IOTX_DM_LOCAL_NODE_DEVID,
+ response->data.value_length,
+ response->data.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_TOPO_GET_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_thing_list_found_reply(dm_msg_response_payload_t *response)
+{
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_COMBINE_LOGIN_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_combine_login_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, message_len = 0, devid = 0;
+ char *message = NULL;
+ lite_cjson_t lite, lite_item_pk, lite_item_dn;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char temp_id[DM_UTILS_UINT32_STRLEN] = {0};
+
+ if (response == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ /* Parse JSON */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(response->data.value, response->data.value_length, &lite);
+ if (res != SUCCESS_RETURN) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ /* Parse Product Key */
+ res = lite_cjson_object_item(&lite, DM_MSG_KEY_PRODUCT_KEY, strlen(DM_MSG_KEY_PRODUCT_KEY), &lite_item_pk);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_pk)
+ || lite_item_pk.value_length >= IOTX_PRODUCT_KEY_LEN + 1) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+
+ /* Parse Device Name */
+ res = lite_cjson_object_item(&lite, DM_MSG_KEY_DEVICE_NAME, strlen(DM_MSG_KEY_DEVICE_NAME), &lite_item_dn);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_dn)
+ || lite_item_dn.value_length >= IOTX_DEVICE_NAME_LEN + 1) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ memcpy(device_name, lite_item_dn.value, lite_item_dn.value_length);
+
+ /* Get Device Id */
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Update State Machine */
+ if (response->code.value_int == IOTX_DM_ERR_CODE_SUCCESS) {
+ dm_mgr_set_dev_status(devid, IOTX_DM_DEV_STATUS_LOGINED);
+ }
+
+ /* Message ID */
+ memcpy(temp_id, response->id.value, response->id.value_length);
+
+ message_len = strlen(DM_MSG_EVENT_COMBINE_LOGIN_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_COMBINE_LOGIN_REPLY_FMT, atoi(temp_id), response->code.value_int,
+ devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_COMBINE_LOGIN_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ if (response->code.value_int != IOTX_DM_ERR_CODE_SUCCESS) {
+ return SUCCESS_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_EVENT_COMBINE_LOGOUT_REPLY_FMT[] DM_READ_ONLY = "{\"id\":%d,\"code\":%d,\"devid\":%d}";
+int dm_msg_combine_logout_reply(dm_msg_response_payload_t *response)
+{
+ int res = 0, message_len = 0, devid = 0;
+ char *message = NULL;
+ lite_cjson_t lite, lite_item_pk, lite_item_dn;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char temp_id[DM_UTILS_UINT32_STRLEN] = {0};
+
+ if (response == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Parse JSON */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(response->data.value, response->data.value_length, &lite);
+ if (res != SUCCESS_RETURN) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ /* Parse Product Key */
+ res = lite_cjson_object_item(&lite, DM_MSG_KEY_PRODUCT_KEY, strlen(DM_MSG_KEY_PRODUCT_KEY), &lite_item_pk);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_pk)
+ || lite_item_pk.value_length >= IOTX_PRODUCT_KEY_LEN + 1) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+
+ /* Parse Device Name */
+ res = lite_cjson_object_item(&lite, DM_MSG_KEY_DEVICE_NAME, strlen(DM_MSG_KEY_DEVICE_NAME), &lite_item_dn);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_dn)
+ || lite_item_dn.value_length >= IOTX_DEVICE_NAME_LEN + 1) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ memcpy(device_name, lite_item_dn.value, lite_item_dn.value_length);
+
+ /* Get Device Id */
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Update State Machine */
+ if (response->code.value_int == IOTX_DM_ERR_CODE_SUCCESS) {
+ dm_mgr_set_dev_status(devid, IOTX_DM_DEV_STATUS_ATTACHED);
+ }
+
+ /* Message ID */
+ memcpy(temp_id, response->id.value, response->id.value_length);
+
+ message_len = strlen(DM_MSG_EVENT_COMBINE_LOGOUT_REPLY_FMT) + DM_UTILS_UINT32_STRLEN * 3 + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_EVENT_COMBINE_LOGOUT_REPLY_FMT, atoi(temp_id), response->code.value_int,
+ devid);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_COMBINE_LOGOUT_REPLY, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#endif
+
+#ifdef ALCS_ENABLED
+const char DM_MSG_DEV_CORE_SERVICE_DEV[] DM_READ_ONLY =
+ "{\"devices\":{\"addr\":\"%s\",\"port\":%d,\"pal\":\"linkkit-ica\",\"profile\":%s}}";
+int dm_msg_dev_core_service_dev(char **payload, int *payload_len)
+{
+ int res = 0, index = 0, search_devid = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+ char ip_addr[16] = {0};
+ char *device_array = NULL;
+ lite_cjson_item_t *lite_array = NULL, *lite_object = NULL;
+ uint16_t port = 5683;
+
+ if (payload == NULL || *payload != NULL || payload_len == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ lite_array = lite_cjson_create_array();
+ if (lite_array == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ /* Get Product Key And Device Name Of All Device */
+ for (index = 0; index < dm_mgr_device_number(); index++) {
+ search_devid = 0;
+ lite_object = NULL;
+ memset(product_key, 0, IOTX_PRODUCT_KEY_LEN + 1);
+ memset(device_name, 0, IOTX_DEVICE_NAME_LEN + 1);
+ memset(device_secret, 0, IOTX_DEVICE_SECRET_LEN + 1);
+
+ res = dm_mgr_get_devid_by_index(index, &search_devid);
+ if (res != SUCCESS_RETURN) {
+ lite_cjson_delete(lite_array);
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_search_device_by_devid(search_devid, product_key, device_name, device_secret);
+ if (res != SUCCESS_RETURN) {
+ lite_cjson_delete(lite_array);
+ return FAIL_RETURN;
+ }
+
+ lite_object = lite_cjson_create_object();
+ if (lite_object == NULL) {
+ lite_cjson_delete(lite_array);
+ return FAIL_RETURN;
+ }
+ lite_cjson_add_string_to_object(lite_object, "productKey", product_key);
+ lite_cjson_add_string_to_object(lite_object, "deviceName", device_name);
+ lite_cjson_add_item_to_array(lite_array, lite_object);
+ }
+
+ device_array = lite_cjson_print_unformatted(lite_array);
+ lite_cjson_delete(lite_array);
+ if (device_array == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ HAL_Wifi_Get_IP(ip_addr, 0);
+
+ *payload_len = strlen(DM_MSG_DEV_CORE_SERVICE_DEV) + strlen(ip_addr) + DM_UTILS_UINT16_STRLEN + strlen(
+ device_array) + 1;
+ *payload = DM_malloc(*payload_len);
+ if (*payload == NULL) {
+ HAL_Free(device_array);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*payload, 0, *payload_len);
+ HAL_Snprintf(*payload, *payload_len, DM_MSG_DEV_CORE_SERVICE_DEV, ip_addr, port, device_array);
+ DM_free(device_array);
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+int dm_msg_cloud_connected(void)
+{
+ return _dm_msg_send_to_user(IOTX_DM_EVENT_CLOUD_CONNECTED, NULL);
+}
+
+int dm_msg_cloud_disconnect(void)
+{
+ return _dm_msg_send_to_user(IOTX_DM_EVENT_CLOUD_DISCONNECT, NULL);
+}
+
+int dm_msg_cloud_reconnect(void)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ HAL_GetProductKey(product_key);
+ HAL_GetDeviceName(device_name);
+
+ /* Send To User */
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_CLOUD_RECONNECT, NULL);
+
+ return res;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+const char DM_MSG_THING_SUB_REGISTER_METHOD[] DM_READ_ONLY = "thing.sub.register";
+const char DM_MSG_THING_SUB_REGISTER_PARAMS[] DM_READ_ONLY = "[{\"productKey\":\"%s\",\"deviceName\":\"%s\"}]";
+int dm_msg_thing_sub_register(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request)
+{
+ int params_len = 0;
+ char *params = NULL;
+
+ if (request == NULL || product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ (strlen(request->product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(request->device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ params_len = strlen(DM_MSG_THING_SUB_REGISTER_PARAMS) + strlen(product_key) + strlen(device_name) + 1;
+ params = DM_malloc(params_len);
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_THING_SUB_REGISTER_PARAMS, product_key, device_name);
+
+ /* Get Params */
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ /* Get Method */
+ request->method = (char *)DM_MSG_THING_SUB_REGISTER_METHOD;
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_SUB_UNREGISTER_METHOD[] DM_READ_ONLY = "thing.sub.unregister";
+const char DM_MSG_THING_SUB_UNREGISTER_PARAMS[] DM_READ_ONLY = "[{\"productKey\":\"%s\",\"deviceName\":\"%s\"}]";
+int dm_msg_thing_sub_unregister(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request)
+{
+ int params_len = 0;
+ char *params = NULL;
+
+ if (request == NULL || product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ (strlen(request->product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(request->device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ params_len = strlen(DM_MSG_THING_SUB_UNREGISTER_PARAMS) + strlen(product_key) + strlen(device_name) + 1;
+ params = DM_malloc(params_len);
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_THING_SUB_UNREGISTER_PARAMS, product_key, device_name);
+
+ /* Get Params */
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ /* Get Method */
+ request->method = (char *)DM_MSG_THING_SUB_UNREGISTER_METHOD;
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_TOPO_ADD_SIGN_SOURCE[] DM_READ_ONLY = "clientId%sdeviceName%sproductKey%stimestamp%s";
+const char DM_MSG_THING_TOPO_ADD_METHOD[] DM_READ_ONLY = "thing.topo.add";
+const char DM_MSG_THING_TOPO_ADD_PARAMS[] DM_READ_ONLY =
+ "[{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"signmethod\":\"%s\",\"sign\":\"%s\",\"timestamp\":\"%s\",\"clientId\":\"%s\"}]";
+int dm_msg_thing_topo_add(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ dm_msg_request_t *request)
+{
+ char *params = NULL;
+ int params_len = 0;
+ char timestamp[DM_UTILS_UINT64_STRLEN] = {0};
+ char client_id[IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 1] = {0};
+ char *sign_source = NULL;
+ int sign_source_len = 0;
+ char *sign_method = DM_MSG_SIGN_METHOD_HMACSHA1;
+ char sign[65] = {0};
+
+
+ if (request == NULL || product_key == NULL ||
+ device_name == NULL || device_secret == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ (strlen(device_secret) >= IOTX_DEVICE_SECRET_LEN + 1) ||
+ (strlen(request->product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(request->device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* TimeStamp */
+ HAL_Snprintf(timestamp, DM_UTILS_UINT64_STRLEN, "%llu", (unsigned long long)HAL_UptimeMs());
+ /* dm_log_debug("Time Stamp: %s", timestamp); */
+
+ /* Client ID */
+ HAL_Snprintf(client_id, IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 1, "%s.%s", product_key, device_name);
+
+ /* Sign */
+ sign_source_len = strlen(DM_MSG_THING_TOPO_ADD_SIGN_SOURCE) + strlen(client_id) +
+ strlen(device_name) + strlen(product_key) + strlen(timestamp) + 1;
+ sign_source = DM_malloc(sign_source_len);
+ if (sign_source == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(sign_source, 0, sign_source_len);
+ HAL_Snprintf(sign_source, sign_source_len, DM_MSG_THING_TOPO_ADD_SIGN_SOURCE, client_id,
+ device_name, product_key, timestamp);
+
+ /* dm_log_debug("Sign Srouce: %s", sign_source); */
+#if 0
+ if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACMD5) == 0) {
+ utils_hmac_md5(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+ } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA1) == 0) {
+ utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+ } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA256) == 0) {
+ utils_hmac_sha256(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+ } else {
+ DM_free(sign_source);
+ return FAIL_RETURN;
+ }
+#else
+ utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+#endif
+ DM_free(sign_source);
+ /* dm_log_debug("Sign : %s", sign); */
+
+ /* Params */
+ request->method = (char *)DM_MSG_THING_TOPO_ADD_METHOD;
+ params_len = strlen(DM_MSG_THING_TOPO_ADD_PARAMS) + strlen(product_key) + strlen(device_name) +
+ strlen(sign_method) + strlen(sign) + strlen(timestamp) + strlen(client_id) + 1;
+ params = DM_malloc(params_len);
+
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_THING_TOPO_ADD_PARAMS, product_key, device_name,
+ sign_method, sign, timestamp, client_id);
+
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_TOPO_DELETE_METHOD[] DM_READ_ONLY = "thing.topo.delete";
+const char DM_MSG_THING_TOPO_DELETE_PARAMS[] DM_READ_ONLY = "[{\"productKey\":\"%s\",\"deviceName\":\"%s\"}]";
+int dm_msg_thing_topo_delete(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request)
+{
+ char *params = NULL;
+ int params_len = 0;
+
+ if (request == NULL || product_key == NULL ||
+ device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ (strlen(request->product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(request->device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Params */
+ request->method = (char *)DM_MSG_THING_TOPO_DELETE_METHOD;
+ params_len = strlen(DM_MSG_THING_TOPO_DELETE_PARAMS) + strlen(product_key) + strlen(device_name) + 1;
+ params = DM_malloc(params_len);
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_THING_TOPO_DELETE_PARAMS, product_key, device_name);
+
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_TOPO_GET_METHOD[] DM_READ_ONLY = "thing.topo.get";
+const char DM_MSG_THING_TOPO_GET_PARAMS[] DM_READ_ONLY = "{}";
+int dm_msg_thing_topo_get(_OU_ dm_msg_request_t *request)
+{
+ char *params = NULL;
+ int params_len = 0;
+
+ /* Params */
+ request->method = (char *)DM_MSG_THING_TOPO_GET_METHOD;
+ params_len = strlen(DM_MSG_THING_TOPO_GET_PARAMS) + 1;
+ params = DM_malloc(params_len);
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ memcpy(params, DM_MSG_THING_TOPO_GET_PARAMS, strlen(DM_MSG_THING_TOPO_GET_PARAMS));
+
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_THING_LIST_FOUND_METHOD[] DM_READ_ONLY = "thing.list.found";
+const char DM_MSG_THING_LIST_FOUND_PARAMS[] DM_READ_ONLY = "[{\"productKey\":\"%s\",\"deviceName\":\"%s\"}]";
+int dm_msg_thing_list_found(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request)
+{
+ char *params = NULL;
+ int params_len = 0;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ request == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Params */
+ request->method = (char *)DM_MSG_THING_LIST_FOUND_METHOD;
+ params_len = strlen(DM_MSG_THING_LIST_FOUND_PARAMS) + strlen(product_key) + strlen(device_name) + 1;
+ params = DM_malloc(params_len);
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_THING_LIST_FOUND_PARAMS, product_key, device_name);
+
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ return SUCCESS_RETURN;
+}
+
+
+const char DM_MSG_COMBINE_LOGIN_SIGN_SOURCE[] DM_READ_ONLY = "clientId%sdeviceName%sproductKey%stimestamp%s";
+const char DM_MSG_COMBINE_LOGIN_METHOD[] DM_READ_ONLY = "combine.login";
+const char DM_MSG_COMBINE_LOGIN_PARAMS[] DM_READ_ONLY =
+ "{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\",\"timestamp\":\"%s\",\"signMethod\":\"%s\",\"sign\":\"%s\",\"cleanSession\":\"%s\"}";
+int dm_msg_combine_login(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ dm_msg_request_t *request)
+{
+ char *params = NULL;
+ int params_len = 0;
+ char timestamp[DM_UTILS_UINT64_STRLEN] = {0};
+ char client_id[IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 1] = {0};
+ char *sign_source = NULL;
+ int sign_source_len = 0;
+ char *sign_method = DM_MSG_SIGN_METHOD_HMACSHA1;
+ char sign[64] = {0};
+
+
+ if (request == NULL || product_key == NULL ||
+ device_name == NULL || device_secret == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ (strlen(device_secret) >= IOTX_DEVICE_SECRET_LEN + 1) ||
+ (strlen(request->product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(request->device_name) >= IOTX_DEVICE_NAME_LEN + 1)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* TimeStamp */
+ HAL_Snprintf(timestamp, DM_UTILS_UINT64_STRLEN, "%llu", (unsigned long long)HAL_UptimeMs());
+ /* dm_log_debug("Time Stamp: %s", timestamp); */
+
+ /* Client ID */
+ HAL_Snprintf(client_id, IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 1, "%s.%s", product_key, device_name);
+
+ /* Sign */
+ sign_source_len = strlen(DM_MSG_COMBINE_LOGIN_SIGN_SOURCE) + strlen(client_id) +
+ strlen(device_name) + strlen(product_key) + strlen(timestamp) + 1;
+ sign_source = DM_malloc(sign_source_len);
+ if (sign_source == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(sign_source, 0, sign_source_len);
+ HAL_Snprintf(sign_source, sign_source_len, DM_MSG_COMBINE_LOGIN_SIGN_SOURCE, client_id,
+ device_name, product_key, timestamp);
+
+ /* dm_log_debug("Sign Srouce: %s", sign_source); */
+#if 0
+ if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACMD5) == 0) {
+ utils_hmac_md5(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+ } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA1) == 0) {
+ utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+ } else if (strcmp(sign_method, DM_MSG_SIGN_METHOD_HMACSHA256) == 0) {
+ utils_hmac_sha256(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+ } else {
+ DM_free(sign_source);
+ return FAIL_RETURN;
+ }
+#else
+ utils_hmac_sha1(sign_source, strlen(sign_source), sign, device_secret, strlen(device_secret));
+#endif
+ DM_free(sign_source);
+ /* dm_log_debug("Sign : %s", sign); */
+
+ /* Params */
+ request->method = (char *)DM_MSG_COMBINE_LOGIN_METHOD;
+ params_len = strlen(DM_MSG_COMBINE_LOGIN_PARAMS) + strlen(product_key) + strlen(device_name) +
+ strlen(sign_method) + strlen(sign) + strlen(timestamp) + strlen(client_id) + 1;
+ params = DM_malloc(params_len);
+
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_COMBINE_LOGIN_PARAMS, product_key, device_name,
+ client_id, timestamp, sign_method, sign, "true");
+
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ return SUCCESS_RETURN;
+}
+
+const char DM_MSG_COMBINE_LOGOUT_METHOD[] DM_READ_ONLY = "combine.logout";
+const char DM_MSG_COMBINE_LOGOUT_PARAMS[] DM_READ_ONLY = "{\"productKey\":\"%s\",\"deviceName\":\"%s\"}";
+int dm_msg_combine_logout(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request)
+{
+ char *params = NULL;
+ int params_len = 0;
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ request == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Params */
+ request->method = (char *)DM_MSG_COMBINE_LOGOUT_METHOD;
+ params_len = strlen(DM_MSG_COMBINE_LOGOUT_PARAMS) + strlen(product_key) + strlen(device_name) + 1;
+ params = DM_malloc(params_len);
+
+ if (params == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(params, 0, params_len);
+ HAL_Snprintf(params, params_len, DM_MSG_COMBINE_LOGOUT_PARAMS, product_key, device_name);
+
+ request->params = params;
+ request->params_len = strlen(request->params);
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+#ifdef DEPRECATED_LINKKIT
+typedef enum {
+ DM_MSG_PROPERTY_SET,
+ DM_MSG_SERVICE_SET
+} dm_msg_set_type_t;
+typedef int (*dm_get_shadow_data)(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+typedef int (*dm_set_shadow_data)(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+
+static int _dm_msg_set_number(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root);
+static int _dm_msg_set_string(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root);
+static int _dm_msg_set_object(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root);
+static int _dm_msg_set_array(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root);
+
+
+static int _dm_msg_set_number(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e data_type;
+ dm_get_shadow_data get_shadow_data_func = (type == DM_MSG_PROPERTY_SET) ? (dm_mgr_deprecated_get_property_data) :
+ (dm_mgr_deprecated_get_service_input_data);
+ dm_set_shadow_data set_shadow_data_func = (type == DM_MSG_PROPERTY_SET) ? (dm_mgr_deprecated_set_property_value) :
+ (dm_mgr_deprecated_set_service_input_value);
+
+ /* dm_log_debug("Current Key: %s", key); */
+
+ res = get_shadow_data_func(devid, key, strlen(key), &data);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &data_type);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* dm_log_debug("Current Type: %d", data_type); */
+ switch (data_type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ res = set_shadow_data_func(devid, key, strlen(key), &root->value_int, 0);
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value_float = (float)root->value_double;
+ res = set_shadow_data_func(devid, key, strlen(key), &value_float, 0);
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ res = set_shadow_data_func(devid, key, strlen(key), &root->value_double, 0);
+ }
+ break;
+ default:
+ dm_log_warning("Unkonwn Number Type");
+ break;
+ }
+
+ return res;
+}
+
+static int _dm_msg_set_string(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root)
+{
+ int res = 0;
+ void *data = NULL;
+ dm_shw_data_type_e data_type;
+ dm_get_shadow_data get_shadow_data_func = (type == DM_MSG_PROPERTY_SET) ? (dm_mgr_deprecated_get_property_data) :
+ (dm_mgr_deprecated_get_service_input_data);
+ dm_set_shadow_data set_shadow_data_func = (type == DM_MSG_PROPERTY_SET) ? (dm_mgr_deprecated_set_property_value) :
+ (dm_mgr_deprecated_set_service_input_value);
+
+ /* dm_log_debug("Current Key: %s", key); */
+
+ res = get_shadow_data_func(devid, key, strlen(key), &data);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_get_data_type(data, &data_type);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* dm_log_debug("Current Type: %d", data_type); */
+
+ switch (data_type) {
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ res = set_shadow_data_func(devid, key, strlen(key), root->value, root->value_length);
+ }
+ break;
+ default:
+ dm_log_warning("Unkonwn String Type");
+ break;
+ }
+
+ return res;
+}
+
+static int _dm_msg_set_object(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_item_key;
+ lite_cjson_t lite_item_value;
+ char *new_key = NULL;
+ int new_key_len = 0;
+
+ for (index = 0; index < root->size; index++) {
+ res = lite_cjson_object_item_by_index(root, index, &lite_item_key, &lite_item_value);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ /* dm_log_debug("Current Key: %.*s, Value: %.*s",
+ lite_item_key.value_length, lite_item_key.value,
+ lite_item_value.value_length, lite_item_value.value); */
+ /* new_key_len = lite_item_key.value_length + 1; */
+ new_key_len = ((key == NULL) ? (0) : (strlen(key) + 1)) + lite_item_key.value_length + 1;
+ /* dm_log_debug("new_key_len: %d", new_key_len); */
+ new_key = DM_malloc(new_key_len);
+ if (new_key == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(new_key, 0, new_key_len);
+ if (key) {
+ memcpy(new_key, key, strlen(key));
+ new_key[strlen(new_key)] = DM_SHW_KEY_DELIMITER;
+ }
+ memcpy(new_key + strlen(new_key), lite_item_key.value, lite_item_key.value_length);
+ /* dm_log_debug("New Key: %s", new_key); */
+
+ if (lite_cjson_is_object(&lite_item_value)) {
+ res = _dm_msg_set_object(type, devid, new_key, &lite_item_value);
+ }
+ if (lite_cjson_is_array(&lite_item_value)) {
+ res = _dm_msg_set_array(type, devid, new_key, &lite_item_value);
+ }
+ if (lite_cjson_is_number(&lite_item_value)) {
+ res = _dm_msg_set_number(type, devid, new_key, &lite_item_value);
+ }
+ if (lite_cjson_is_string(&lite_item_value)) {
+ res = _dm_msg_set_string(type, devid, new_key, &lite_item_value);
+ }
+
+ DM_free(new_key);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+ return SUCCESS_RETURN;
+}
+
+static int _dm_msg_set_array(dm_msg_set_type_t type, int devid, char *key, lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_item_value;
+ char *ascii_index = NULL;
+ char *new_key = NULL;
+ int new_key_len = 0;
+
+ for (index = 0; index < root->size; index++) {
+
+ res = lite_cjson_array_item(root, index, &lite_item_value);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ /* dm_log_debug("Current Value: %.*s", lite_item_value.value_length, lite_item_value.value); */
+
+ res = dm_utils_itoa(index, &ascii_index);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ /* Original Key '[' Index ']'*/
+ new_key_len = ((key == NULL) ? (0) : (strlen(key) + 1)) + 1 + strlen(ascii_index) + 1 + 1;
+ new_key = DM_malloc(new_key_len);
+ if (new_key == NULL) {
+ DM_free(ascii_index);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(new_key, 0, new_key_len);
+ if (key) {
+ memcpy(new_key, key, strlen(key));
+ }
+ new_key[strlen(new_key)] = '[';
+ memcpy(new_key + strlen(new_key), ascii_index, strlen(ascii_index));
+ new_key[strlen(new_key)] = ']';
+ /* dm_log_debug("New Key: %s", new_key); */
+ DM_free(ascii_index);
+
+ if (lite_cjson_is_object(&lite_item_value)) {
+ res = _dm_msg_set_object(type, devid, new_key, &lite_item_value);
+ }
+ if (lite_cjson_is_array(&lite_item_value)) {
+ res = _dm_msg_set_array(type, devid, new_key, &lite_item_value);
+ }
+ if (lite_cjson_is_number(&lite_item_value)) {
+ res = _dm_msg_set_number(type, devid, new_key, &lite_item_value);
+ }
+ if (lite_cjson_is_string(&lite_item_value)) {
+ res = _dm_msg_set_string(type, devid, new_key, &lite_item_value);
+ }
+
+ DM_free(new_key);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+ const char DM_MSG_PROPERTY_SET_FMT[] DM_READ_ONLY = "{\"devid\":%d,\"payload\":%.*s}";
+#else
+ const char DM_MSG_PROPERTY_SET_FMT[] DM_READ_ONLY = "{\"devid\":%d,\"propertyid\":\"%.*s\"}";
+#endif
+int dm_msg_property_set(int devid, dm_msg_request_payload_t *request)
+{
+ int res = 0, message_len = 0;
+ char *message = NULL;
+#ifndef DEVICE_MODEL_GATEWAY
+ int index = 0;
+ lite_cjson_t lite, lite_item_key, lite_item_value;
+#endif
+ if (request == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+#ifdef DEVICE_MODEL_GATEWAY
+ message_len = strlen(DM_MSG_PROPERTY_SET_FMT) + DM_UTILS_UINT32_STRLEN + request->params.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_PROPERTY_SET_FMT, devid, request->params.value_length, request->params.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_PROPERTY_SET, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ }
+#else
+ /* Parse Root */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(request->params.value, request->params.value_length, &lite);
+ if (res != SUCCESS_RETURN || (!lite_cjson_is_object(&lite) && !lite_cjson_is_array(&lite))) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_info("Property Set, Size: %d", lite.size); */
+
+ if (lite_cjson_is_object(&lite)) {
+ res = _dm_msg_set_object(DM_MSG_PROPERTY_SET, devid, NULL, &lite);
+ }
+
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ for (index = 0; index < lite.size; index++) {
+ memset(&lite_item_key, 0, sizeof(lite_cjson_t));
+ memset(&lite_item_value, 0, sizeof(lite_cjson_t));
+
+ res = lite_cjson_object_item_by_index(&lite, index, &lite_item_key, &lite_item_value);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+
+ message_len = strlen(DM_MSG_PROPERTY_SET_FMT) + DM_UTILS_UINT32_STRLEN + lite_item_key.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_PROPERTY_SET_FMT, devid, lite_item_key.value_length, lite_item_key.value);
+
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_PROPERTY_SET, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ }
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_property_get(_IN_ int devid, _IN_ dm_msg_request_payload_t *request, _IN_ char **payload,
+ _IN_ int *payload_len)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite, lite_item;
+ lite_cjson_item_t *lite_cjson_item = NULL;
+
+ if (devid < 0 || request == NULL || payload == NULL || *payload != NULL || payload_len == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ lite_cjson_item = lite_cjson_create_object();
+ if (lite_cjson_item == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ /* Parse Root */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(request->params.value, request->params.value_length, &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_array(&lite)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_info("Property Get, Size: %d", lite.size); */
+
+ /* Parse Params */
+ for (index = 0; index < lite.size; index++) {
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_array_item(&lite, index, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ lite_cjson_delete(lite_cjson_item);
+ return FAIL_RETURN;
+ }
+
+ if (!lite_cjson_is_string(&lite_item)) {
+ lite_cjson_delete(lite_cjson_item);
+ return FAIL_RETURN;
+ }
+
+ res = dm_mgr_deprecated_assemble_property(devid, lite_item.value, lite_item.value_length, lite_cjson_item);
+ if (res != SUCCESS_RETURN) {
+ lite_cjson_delete(lite_cjson_item);
+ return FAIL_RETURN;
+ }
+ }
+
+ *payload = lite_cjson_print_unformatted(lite_cjson_item);
+ if (*payload == NULL) {
+ lite_cjson_delete(lite_cjson_item);
+ return FAIL_RETURN;
+ }
+ lite_cjson_delete(lite_cjson_item);
+ *payload_len = strlen(*payload);
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+ const char DM_MSG_SERVICE_REQUEST_FMT[] DM_READ_ONLY =
+ "{\"id\":%d,\"devid\":%d,\"serviceid\":\"%.*s\",\"payload\":%.*s}";
+#else
+ const char DM_MSG_SERVICE_REQUEST_FMT[] DM_READ_ONLY = "{\"id\":%d,\"devid\":%d,\"serviceid\":\"%.*s\"}";
+#endif
+int dm_msg_thing_service_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ char *identifier, int identifier_len, dm_msg_request_payload_t *request, _IN_ void *ctx)
+{
+ int res = 0, id = 0, devid = 0, message_len = 0;
+ lite_cjson_t lite;
+#ifndef DEVICE_MODEL_GATEWAY
+ char *key = NULL;
+#endif
+ char *message = NULL;
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+
+ if (product_key == NULL || device_name == NULL ||
+ (strlen(product_key) >= IOTX_PRODUCT_KEY_LEN + 1) ||
+ (strlen(device_name) >= IOTX_DEVICE_NAME_LEN + 1) ||
+ identifier == NULL || identifier_len == 0 || request == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Message ID */
+ memcpy(int_id, request->id.value, request->id.value_length);
+ id = atoi(int_id);
+
+ /* dm_log_debug("Current ID: %d", id); */
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+#ifdef DEVICE_MODEL_GATEWAY
+ message_len = strlen(DM_MSG_SERVICE_REQUEST_FMT) + DM_UTILS_UINT32_STRLEN * 2 + identifier_len +
+ request->params.value_length + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_SERVICE_REQUEST_FMT, id, devid, identifier_len, identifier,
+ request->params.value_length, request->params.value);
+#else
+ key = DM_malloc(identifier_len + 1);
+ if (key == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(key, 0, identifier_len + 1);
+ memcpy(key, identifier, identifier_len);
+
+ /* Parse Root */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(request->params.value, request->params.value_length, &lite);
+ if (res != SUCCESS_RETURN || (!lite_cjson_is_object(&lite) && !lite_cjson_is_array(&lite))) {
+ DM_free(key);
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_info("Service Request, Size: %d", lite.size); */
+
+ if (lite_cjson_is_object(&lite)) {
+ res = _dm_msg_set_object(DM_MSG_SERVICE_SET, devid, key, &lite);
+ }
+ DM_free(key);
+
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ message_len = strlen(DM_MSG_SERVICE_REQUEST_FMT) + DM_UTILS_UINT32_STRLEN * 2 + identifier_len + 1;
+ message = DM_malloc(message_len);
+ if (message == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(message, 0, message_len);
+ HAL_Snprintf(message, message_len, DM_MSG_SERVICE_REQUEST_FMT, id, devid, identifier_len, identifier);
+#endif
+ res = _dm_msg_send_to_user(IOTX_DM_EVENT_THING_SERVICE_REQUEST, message);
+ if (res != SUCCESS_RETURN) {
+ DM_free(message);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message.h
new file mode 100644
index 00000000..a9174403
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_MESSAGE_H_
+#define _DM_MESSAGE_H_
+
+#include "iotx_dm_internal.h"
+
+#define DM_MSG_KEY_ID "id"
+#define DM_MSG_KEY_VERSION "version"
+#define DM_MSG_KEY_METHOD "method"
+#define DM_MSG_KEY_PARAMS "params"
+#define DM_MSG_KEY_CODE "code"
+#define DM_MSG_KEY_DATA "data"
+#define DM_MSG_KEY_MESSAGE "message"
+
+#define DM_MSG_VERSION "1.0"
+
+#define DM_MSG_KEY_PRODUCT_KEY "productKey"
+#define DM_MSG_KEY_DEVICE_NAME "deviceName"
+#define DM_MSG_KEY_DEVICE_SECRET "deviceSecret"
+#define DM_MSG_KEY_TIME "time"
+
+#define DM_MSG_SIGN_METHOD_SHA256 "Sha256"
+#define DM_MSG_SIGN_METHOD_HMACMD5 "hmacMd5"
+#define DM_MSG_SIGN_METHOD_HMACSHA1 "hmacSha1"
+#define DM_MSG_SIGN_METHOD_HMACSHA256 "hmacSha256"
+
+typedef enum {
+ DM_MSG_DEST_CLOUD = 0x01,
+ DM_MSG_DEST_LOCAL = 0x02,
+ DM_MSG_DEST_ALL = 0x03
+} dm_msg_dest_type_t;
+
+typedef struct {
+ const char *uri;
+ unsigned char *payload;
+ unsigned int payload_len;
+ void *context;
+} dm_msg_source_t;
+
+typedef struct {
+ const char *uri_name;
+} dm_msg_dest_t;
+
+typedef struct {
+ lite_cjson_t id;
+ lite_cjson_t version;
+ lite_cjson_t method;
+ lite_cjson_t params;
+} dm_msg_request_payload_t;
+
+typedef struct {
+ lite_cjson_t id;
+ lite_cjson_t code;
+ lite_cjson_t data;
+ lite_cjson_t message;
+} dm_msg_response_payload_t;
+
+typedef struct {
+ int msgid;
+ int devid;
+ const char *service_prefix;
+ const char *service_name;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char *params;
+ int params_len;
+ char *method;
+ iotx_cm_data_handle_cb callback;
+} dm_msg_request_t;
+
+typedef struct {
+ const char *service_prefix;
+ const char *service_name;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ iotx_dm_error_code_t code;
+} dm_msg_response_t;
+
+typedef struct {
+ int id;
+} dm_msg_ctx_t;
+
+
+int dm_msg_init(void);
+int dm_msg_deinit(void);
+int _dm_msg_send_to_user(iotx_dm_event_types_t type, char *message);
+int dm_msg_send_msg_timeout_to_user(int msg_id, int devid, iotx_dm_event_types_t type);
+int dm_msg_uri_parse_pkdn(_IN_ char *uri, _IN_ int uri_len, _IN_ int start_deli, _IN_ int end_deli,
+ _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+int dm_msg_request_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_request_payload_t *request);
+int dm_msg_response_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_response_payload_t *response);
+int dm_msg_request(dm_msg_dest_type_t type, _IN_ dm_msg_request_t *request);
+int dm_msg_response(dm_msg_dest_type_t type, _IN_ dm_msg_request_payload_t *request, _IN_ dm_msg_response_t *response,
+ _IN_ char *data, _IN_ int data_len, _IN_ void *user_data);
+int dm_msg_thing_model_down_raw(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char *payload, _IN_ int payload_len);
+int dm_msg_thing_model_up_raw_reply(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], char *payload, int payload_len);
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+int dm_msg_property_set(int devid, dm_msg_request_payload_t *request);
+#ifndef DEPRECATED_LINKKIT
+int dm_msg_property_get(_IN_ int devid, _IN_ dm_msg_request_payload_t *request, _IN_ void *ctx);
+#else
+int dm_msg_property_get(_IN_ int devid, _IN_ dm_msg_request_payload_t *request, _IN_ char **payload,
+ _IN_ int *payload_len);
+#endif
+int dm_msg_thing_service_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ char *identifier, int identifier_len, dm_msg_request_payload_t *request, _IN_ void *ctx);
+int dm_msg_rrpc_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ char *messageid, int messageid_len, dm_msg_request_payload_t *request);
+int dm_msg_thing_event_property_post_reply(dm_msg_response_payload_t *response);
+int dm_msg_thing_event_post_reply(_IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ dm_msg_response_payload_t *response);
+int dm_msg_thing_deviceinfo_update_reply(dm_msg_response_payload_t *response);
+int dm_msg_thing_property_desired_get_reply(dm_msg_response_payload_t *response);
+int dm_msg_thing_property_desired_delete_reply(dm_msg_response_payload_t *response);
+int dm_msg_thing_deviceinfo_delete_reply(dm_msg_response_payload_t *response);
+int dm_msg_thing_dsltemplate_get_reply(dm_msg_response_payload_t *response);
+int dm_msg_thing_dynamictsl_get_reply(dm_msg_response_payload_t *response);
+int dm_msg_ntp_response(char *payload, int payload_len);
+int dm_msg_ext_error_reply(dm_msg_response_payload_t *response);
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+ int dm_msg_topo_add_notify(_IN_ char *payload, _IN_ int payload_len);
+ int dm_msg_thing_disable(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+ int dm_msg_thing_enable(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+ int dm_msg_thing_delete(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+ int dm_msg_thing_gateway_permit(_IN_ char *payload, _IN_ int payload_len);
+ int dm_msg_thing_sub_register_reply(dm_msg_response_payload_t *response);
+ int dm_msg_thing_sub_unregister_reply(dm_msg_response_payload_t *response);
+ int dm_msg_thing_topo_add_reply(dm_msg_response_payload_t *response);
+ int dm_msg_thing_topo_delete_reply(dm_msg_response_payload_t *response);
+ int dm_msg_topo_get_reply(dm_msg_response_payload_t *response);
+ int dm_msg_thing_list_found_reply(dm_msg_response_payload_t *response);
+ int dm_msg_combine_login_reply(dm_msg_response_payload_t *response);
+ int dm_msg_combine_logout_reply(dm_msg_response_payload_t *response);
+#endif
+#ifdef ALCS_ENABLED
+ int dm_msg_dev_core_service_dev(char **payload, int *payload_len);
+#endif
+int dm_msg_cloud_connected(void);
+int dm_msg_cloud_disconnect(void);
+int dm_msg_cloud_reconnect(void);
+#if 0
+ int dm_msg_found_device(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+ int dm_msg_remove_device(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+ int dm_msg_unregister_result(_IN_ char *uri, _IN_ int result);
+ int dm_msg_send_result(_IN_ char *uri, _IN_ int result);
+ int dm_msg_add_service_result(_IN_ char *uri, _IN_ int result);
+ int dm_msg_remove_service_result(_IN_ char *uri, _IN_ int result);
+#endif
+int dm_msg_register_result(_IN_ char *uri, _IN_ int result);
+
+#ifdef DEVICE_MODEL_GATEWAY
+int dm_msg_thing_sub_register(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request);
+int dm_msg_thing_sub_unregister(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request);
+int dm_msg_thing_topo_add(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ dm_msg_request_t *request);
+int dm_msg_thing_topo_delete(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request);
+int dm_msg_thing_topo_get(_OU_ dm_msg_request_t *request);
+int dm_msg_thing_list_found(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request);
+int dm_msg_combine_login(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ dm_msg_request_t *request);
+int dm_msg_combine_logout(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _OU_ dm_msg_request_t *request);
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message_cache.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message_cache.c
new file mode 100644
index 00000000..7c599130
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message_cache.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+
+dm_msg_cache_ctx_t g_dm_msg_cache_ctx;
+
+dm_msg_cache_ctx_t *_dm_msg_cache_get_ctx(void)
+{
+ return &g_dm_msg_cache_ctx;
+}
+
+static void _dm_msg_cache_mutex_lock(void)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexLock(ctx->mutex);
+ }
+}
+
+static void _dm_msg_cache_mutex_unlock(void)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexUnlock(ctx->mutex);
+ }
+}
+
+int dm_msg_cache_init(void)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+
+ memset(ctx, 0, sizeof(dm_msg_cache_ctx_t));
+
+ /* Create Mutex */
+ ctx->mutex = HAL_MutexCreate();
+ if (ctx->mutex == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ /* Init Message Cache List */
+ INIT_LIST_HEAD(&ctx->dmc_list);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_cache_deinit(void)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ dm_msg_cache_node_t *node = NULL;
+ dm_msg_cache_node_t *next = NULL;
+
+ _dm_msg_cache_mutex_lock();
+ list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
+ list_del(&node->linked_list);
+ if (node->data) {
+ DM_free(node->data);
+ }
+ DM_free(node);
+ _dm_msg_cache_mutex_unlock();
+ }
+ _dm_msg_cache_mutex_unlock();
+
+ if (ctx->mutex) {
+ HAL_MutexDestroy(ctx->mutex);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_cache_insert(int msgid, int devid, iotx_dm_event_types_t type, char *data)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ dm_msg_cache_node_t *node = NULL;
+
+ dm_log_debug("dmc list size: %d", ctx->dmc_list_size);
+ if (ctx->dmc_list_size >= CONFIG_MSGCACHE_QUEUE_MAXLEN) {
+ return FAIL_RETURN;
+ }
+
+ node = DM_malloc(sizeof(dm_msg_cache_node_t));
+ if (node == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(node, 0, sizeof(dm_msg_cache_node_t));
+
+ node->msgid = msgid;
+ node->devid = devid;
+ node->response_type = type;
+ node->data = data;
+ node->ctime = HAL_UptimeMs();
+ INIT_LIST_HEAD(&node->linked_list);
+
+ _dm_msg_cache_mutex_lock();
+ list_add_tail(&node->linked_list, &ctx->dmc_list);
+ ctx->dmc_list_size++;
+ _dm_msg_cache_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_cache_search(_IN_ int msgid, _OU_ dm_msg_cache_node_t **node)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ dm_msg_cache_node_t *search_node = NULL;
+
+ if (msgid <= 0 || node == NULL || *node != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ _dm_msg_cache_mutex_lock();
+ list_for_each_entry(search_node, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
+ if (search_node->msgid == msgid) {
+ *node = search_node;
+ _dm_msg_cache_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ _dm_msg_cache_mutex_unlock();
+ return FAIL_RETURN;
+}
+
+int dm_msg_cache_remove(int msgid)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ dm_msg_cache_node_t *node = NULL;
+ dm_msg_cache_node_t *next = NULL;
+
+ _dm_msg_cache_mutex_lock();
+ list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
+ if (node->msgid == msgid) {
+ list_del(&node->linked_list);
+ if (node->data) {
+ DM_free(node->data);
+ }
+ ctx->dmc_list_size--;
+ DM_free(node);
+ dm_log_debug("Remove Message ID: %d", msgid);
+ _dm_msg_cache_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ _dm_msg_cache_mutex_unlock();
+ return FAIL_RETURN;
+}
+
+void dm_msg_cache_tick(void)
+{
+ dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
+ dm_msg_cache_node_t *node = NULL;
+ dm_msg_cache_node_t *next = NULL;
+ uint64_t current_time = HAL_UptimeMs();
+
+ _dm_msg_cache_mutex_lock();
+ list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
+ if (current_time < node->ctime) {
+ node->ctime = current_time;
+ }
+ if (current_time - node->ctime >= DM_MSG_CACHE_TIMEOUT_MS_DEFAULT) {
+ dm_log_debug("Message ID Timeout: %d", node->msgid);
+ /* Send Timeout Message To User */
+ dm_msg_send_msg_timeout_to_user(node->msgid, node->devid, node->response_type);
+ list_del(&node->linked_list);
+ if (node->data) {
+ DM_free(node->data);
+ }
+ DM_free(node);
+ ctx->dmc_list_size--;
+ }
+ }
+ _dm_msg_cache_mutex_unlock();
+}
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message_cache.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message_cache.h
new file mode 100644
index 00000000..d4892018
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_message_cache.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+#ifndef _DM_MESSAGE_CACHE_H_
+#define _DM_MESSAGE_CACHE_H_
+
+#include "iotx_dm_internal.h"
+
+#define DM_MSG_CACHE_TIMEOUT_MS_DEFAULT (10000)
+
+typedef struct {
+ int msgid;
+ int devid;
+ iotx_dm_event_types_t response_type;
+ char *data;
+ uint64_t ctime;
+ struct list_head linked_list;
+} dm_msg_cache_node_t;
+
+typedef struct {
+ void *mutex;
+ int dmc_list_size;
+ struct list_head dmc_list;
+} dm_msg_cache_ctx_t;
+
+int dm_msg_cache_init(void);
+int dm_msg_cache_deinit(void);
+int dm_msg_cache_insert(int msg_id, int devid, iotx_dm_event_types_t type, char *data);
+int dm_msg_cache_search(_IN_ int msg_id, _OU_ dm_msg_cache_node_t **node);
+int dm_msg_cache_remove(int msg_id);
+void dm_msg_cache_tick(void);
+
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_msg_process.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_msg_process.c
new file mode 100644
index 00000000..f0ed9ce3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_msg_process.c
@@ -0,0 +1,974 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include "iotx_dm_internal.h"
+
+const char DM_URI_SYS_PREFIX[] DM_READ_ONLY = "/sys/%s/%s/";
+const char DM_URI_EXT_SESSION_PREFIX[] DM_READ_ONLY = "/ext/session/%s/%s/";
+const char DM_URI_EXT_NTP_PREFIX[] DM_READ_ONLY = "/ext/ntp/%s/%s/";
+const char DM_URI_EXT_ERROR_PREFIX[] DM_READ_ONLY = "/ext/error/%s/%s";
+const char DM_URI_REPLY_SUFFIX[] DM_READ_ONLY = "_reply";
+const char DM_URI_OTA_DEVICE_INFORM[] DM_READ_ONLY = "/ota/device/inform/%s/%s";
+
+/* From Cloud To Local Request And Response*/
+const char DM_URI_THING_MODEL_DOWN_RAW[] DM_READ_ONLY = "thing/model/down_raw";
+const char DM_URI_THING_MODEL_DOWN_RAW_REPLY[] DM_READ_ONLY = "thing/model/down_raw_reply";
+
+/* From Local To Cloud Request And Response*/
+const char DM_URI_THING_MODEL_UP_RAW[] DM_READ_ONLY = "thing/model/up_raw";
+const char DM_URI_THING_MODEL_UP_RAW_REPLY[] DM_READ_ONLY = "thing/model/up_raw_reply";
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ const char DM_URI_RRPC_REQUEST_WILDCARD[] DM_READ_ONLY = "rrpc/request/+";
+
+ /* From Cloud To Local Request And Response*/
+ const char DM_URI_THING_SERVICE_PROPERTY_SET[] DM_READ_ONLY = "thing/service/property/set";
+ const char DM_URI_THING_SERVICE_PROPERTY_SET_REPLY[] DM_READ_ONLY = "thing/service/property/set_reply";
+ const char DM_URI_THING_SERVICE_PROPERTY_GET[] DM_READ_ONLY = "thing/service/property/get";
+ const char DM_URI_THING_SERVICE_PROPERTY_GET_REPLY[] DM_READ_ONLY = "thing/service/property/get_reply";
+ const char DM_URI_THING_SERVICE_REQUEST_WILDCARD[] DM_READ_ONLY = "thing/service/+";
+ const char DM_URI_THING_SERVICE_REQUEST_WILDCARD2[] DM_READ_ONLY = "thing/service/#";
+ const char DM_URI_THING_SERVICE_REQUEST[] DM_READ_ONLY = "thing/service/%s";
+ const char DM_URI_THING_SERVICE_RESPONSE[] DM_READ_ONLY = "thing/service/%.*s_reply";
+ #ifdef DEVICE_MODEL_SHADOW
+ const char DM_URI_THING_PROPERTY_DESIRED_GET[] DM_READ_ONLY = "thing/property/desired/get";
+ const char DM_URI_THING_PROPERTY_DESIRED_DELETE[] DM_READ_ONLY = "thing/property/desired/delete";
+ const char DM_URI_THING_PROPERTY_DESIRED_GET_REPLY[] DM_READ_ONLY = "thing/property/desired/get_reply";
+ const char DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY[] DM_READ_ONLY = "thing/property/desired/delete_reply";
+ #endif
+ /* From Local To Cloud Request And Response*/
+ #ifdef LOG_REPORT_TO_CLOUD
+ const char DM_URI_THING_LOG_POST[] DM_READ_ONLY = "thing/log/post";
+ #endif
+ const char DM_URI_THING_EVENT_PROPERTY_POST[] DM_READ_ONLY = "thing/event/property/post";
+ const char DM_URI_THING_EVENT_PROPERTY_POST_REPLY[] DM_READ_ONLY = "thing/event/property/post_reply";
+ const char DM_URI_THING_EVENT_POST[] DM_READ_ONLY = "thing/event/%.*s/post";
+ const char DM_URI_THING_EVENT_POST_REPLY[] DM_READ_ONLY = "thing/event/%s/post_reply";
+ const char DM_URI_THING_EVENT_POST_REPLY_WILDCARD[] DM_READ_ONLY = "thing/event/+/post_reply";
+ const char DM_URI_THING_DEVICEINFO_UPDATE[] DM_READ_ONLY = "thing/deviceinfo/update";
+ const char DM_URI_THING_DEVICEINFO_UPDATE_REPLY[] DM_READ_ONLY = "thing/deviceinfo/update_reply";
+ const char DM_URI_THING_DEVICEINFO_DELETE[] DM_READ_ONLY = "thing/deviceinfo/delete";
+ const char DM_URI_THING_DEVICEINFO_DELETE_REPLY[] DM_READ_ONLY = "thing/deviceinfo/delete_reply";
+ const char DM_URI_THING_DSLTEMPLATE_GET[] DM_READ_ONLY = "thing/dsltemplate/get";
+ const char DM_URI_THING_DSLTEMPLATE_GET_REPLY[] DM_READ_ONLY = "thing/dsltemplate/get_reply";
+ const char DM_URI_THING_DYNAMICTSL_GET[] DM_READ_ONLY = "thing/dynamicTsl/get";
+ const char DM_URI_THING_DYNAMICTSL_GET_REPLY[] DM_READ_ONLY = "thing/dynamicTsl/get_reply";
+ const char DM_URI_NTP_REQUEST[] DM_READ_ONLY = "request";
+ const char DM_URI_NTP_RESPONSE[] DM_READ_ONLY = "response";
+#endif
+
+const char DM_URI_DEV_CORE_SERVICE_DEV[] DM_READ_ONLY = "/dev/core/service/dev";
+
+#ifdef DEVICE_MODEL_GATEWAY
+ /* From Cloud To Local Request And Response*/
+ const char DM_URI_THING_TOPO_ADD_NOTIFY[] DM_READ_ONLY = "thing/topo/add/notify";
+ const char DM_URI_THING_TOPO_ADD_NOTIFY_REPLY[] DM_READ_ONLY = "thing/topo/add/notify_reply";
+ const char DM_URI_THING_DELETE[] DM_READ_ONLY = "thing/delete";
+ const char DM_URI_THING_DELETE_REPLY[] DM_READ_ONLY = "thing/delete_reply";
+ const char DM_URI_THING_DISABLE[] DM_READ_ONLY = "thing/disable";
+ const char DM_URI_THING_DISABLE_REPLY[] DM_READ_ONLY = "thing/disable_reply";
+ const char DM_URI_THING_ENABLE[] DM_READ_ONLY = "thing/enable";
+ const char DM_URI_THING_ENABLE_REPLY[] DM_READ_ONLY = "thing/enable_reply";
+ const char DM_URI_THING_GATEWAY_PERMIT[] DM_READ_ONLY = "thing/gateway/permit";
+ const char DM_URI_THING_GATEWAY_PERMIT_REPLY[] DM_READ_ONLY = "thing/gateway/permit_reply";
+
+ /* From Local To Cloud Request And Response*/
+ const char DM_URI_THING_SUB_REGISTER[] DM_READ_ONLY = "thing/sub/register";
+ const char DM_URI_THING_SUB_REGISTER_REPLY[] DM_READ_ONLY = "thing/sub/register_reply";
+ const char DM_URI_THING_SUB_UNREGISTER[] DM_READ_ONLY = "thing/sub/unregister";
+ const char DM_URI_THING_SUB_UNREGISTER_REPLY[] DM_READ_ONLY = "thing/sub/unregister_reply";
+ const char DM_URI_THING_TOPO_ADD[] DM_READ_ONLY = "thing/topo/add";
+ const char DM_URI_THING_TOPO_ADD_REPLY[] DM_READ_ONLY = "thing/topo/add_reply";
+ const char DM_URI_THING_TOPO_DELETE[] DM_READ_ONLY = "thing/topo/delete";
+ const char DM_URI_THING_TOPO_DELETE_REPLY[] DM_READ_ONLY = "thing/topo/delete_reply";
+ const char DM_URI_THING_TOPO_GET[] DM_READ_ONLY = "thing/topo/get";
+ const char DM_URI_THING_TOPO_GET_REPLY[] DM_READ_ONLY = "thing/topo/get_reply";
+ const char DM_URI_THING_LIST_FOUND[] DM_READ_ONLY = "thing/list/found";
+ const char DM_URI_THING_LIST_FOUND_REPLY[] DM_READ_ONLY = "thing/list/found_reply";
+ const char DM_URI_COMBINE_LOGIN[] DM_READ_ONLY = "combine/login";
+ const char DM_URI_COMBINE_LOGIN_REPLY[] DM_READ_ONLY = "combine/login_reply";
+ const char DM_URI_COMBINE_LOGOUT[] DM_READ_ONLY = "combine/logout";
+ const char DM_URI_COMBINE_LOGOUT_REPLY[] DM_READ_ONLY = "combine/logout_reply";
+#endif
+
+int dm_msg_proc_thing_model_down_raw(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ /* Parse Product Key And Device Name */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return dm_msg_thing_model_down_raw(product_key, device_name, (char *)source->payload, source->payload_len);
+}
+
+int dm_msg_proc_thing_model_up_raw_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_MODEL_UP_RAW_REPLY);
+
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_model_up_raw_reply(product_key, device_name, (char *)source->payload, source->payload_len);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+int dm_msg_proc_thing_service_property_set(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0, devid = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_SERVICE_PROPERTY_SET);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res < SUCCESS_RETURN) {
+ return res ;
+ }
+
+ /* Operation */
+ res = dm_msg_property_set(devid, request);
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_service_property_get(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
+ _OU_ unsigned char **data, int *data_len)
+{
+ int res = 0, devid = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_SERVICE_PROPERTY_GET);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res < SUCCESS_RETURN) {
+ return res ;
+ }
+
+ /* Operation */
+#ifndef DEPRECATED_LINKKIT
+ res = dm_msg_property_get(devid, request, source->context);
+#else
+ res = dm_msg_property_get(devid, request, (char **)data, data_len);
+#endif
+
+#ifdef DEPRECATED_LINKKIT
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ if (res != SUCCESS_RETURN) {
+ *data = DM_malloc(strlen("{}") + 1);
+ if (*data == NULL) {
+ return FAIL_RETURN;
+ }
+ memset(*data, 0, strlen("{}") + 1);
+ memcpy(*data, "{}", strlen("{}"));
+
+ *data_len = strlen((char *)*data);
+ }
+#endif
+
+ if (res != SUCCESS_RETURN) {
+ dm_log_err("DM Property Get Failed");
+ }
+
+ return res;
+}
+
+int dm_msg_proc_thing_service_property_post(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_EVENT_PROPERTY_POST);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_service_request(_IN_ dm_msg_source_t *source)
+{
+ int res = 0, serviceid_pos = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ dm_msg_request_payload_t request;
+
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+
+ res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 6, &serviceid_pos);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_info("Service Identifier: %.*s", (int)(strlen(source->uri) - serviceid_pos - 1),
+ source->uri + serviceid_pos + 1);
+
+ /* Parse Product Key And Device Name */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Request */
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ return dm_msg_thing_service_request(product_key, device_name, (char *)source->uri + serviceid_pos + 1,
+ strlen(source->uri) - serviceid_pos - 1, &request, source->context);
+}
+
+int dm_msg_proc_thing_event_post_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0, eventid_start_pos = 0, eventid_end_pos = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 6 + DM_URI_OFFSET,
+ &eventid_start_pos);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 7 + DM_URI_OFFSET,
+ &eventid_end_pos);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_info("Event Id: %.*s", eventid_end_pos - eventid_start_pos - 1, source->uri + eventid_start_pos + 1);
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ if ((strlen("property") == eventid_end_pos - eventid_start_pos - 1) &&
+ (memcmp("property", source->uri + eventid_start_pos + 1, eventid_end_pos - eventid_start_pos - 1) == 0)) {
+ dm_msg_thing_event_property_post_reply(&response);
+ } else {
+ dm_msg_thing_event_post_reply((char *)source->uri + eventid_start_pos + 1, eventid_end_pos - eventid_start_pos - 1,
+ &response);
+ }
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_SHADOW
+int dm_msg_proc_thing_property_desired_get_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_PROPERTY_DESIRED_GET_REPLY);
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_property_desired_get_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_property_desired_delete_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY);
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_property_desired_delete_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+#endif
+
+int dm_msg_proc_thing_deviceinfo_update_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_DEVICEINFO_UPDATE_REPLY);
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_deviceinfo_update_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_deviceinfo_delete_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_DEVICEINFO_DELETE_REPLY);
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_deviceinfo_delete_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_dynamictsl_get_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_DYNAMICTSL_GET_REPLY);
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_dynamictsl_get_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_rrpc_request(_IN_ dm_msg_source_t *source)
+{
+ int res = 0, rrpcid_pos = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ dm_msg_request_payload_t request;
+
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+
+ res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 6, &rrpcid_pos);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_info("Rrpc Id: %.*s", (int)(strlen(source->uri) - rrpcid_pos - 1), source->uri + rrpcid_pos + 1);
+
+ /* Parse Product Key And Device Name */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Request */
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, &request);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ return dm_msg_rrpc_request(product_key, device_name, (char *)source->uri + rrpcid_pos + 1,
+ strlen(source->uri) - rrpcid_pos - 1, &request);
+}
+
+int dm_disp_ntp_response(_IN_ dm_msg_source_t *source)
+{
+ dm_log_info(DM_URI_NTP_RESPONSE);
+
+ /* Operation */
+ return dm_msg_ntp_response((char *)source->payload, source->payload_len);
+}
+
+int dm_disp_ext_error_response(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+ /* char int_id[DM_UTILS_UINT32_STRLEN] = {0}; */
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ return dm_msg_ext_error_reply(&response);
+}
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+int dm_msg_proc_thing_topo_add_notify(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_TOPO_ADD_NOTIFY);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res < SUCCESS_RETURN) {
+ return res ;
+ }
+
+ /* Operation */
+ res = dm_msg_topo_add_notify(request->params.value, request->params.value_length);
+ if (res < SUCCESS_RETURN) {
+ return res ;
+ }
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_disable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_DISABLE);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res != SUCCESS_RETURN) {
+ return res;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_disable(product_key, device_name);
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_enable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_DISABLE);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res != SUCCESS_RETURN) {
+ return res;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_enable(product_key, device_name);
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_delete(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_DELETE);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res != SUCCESS_RETURN) {
+ return res;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_delete(product_key, device_name);
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_gateway_permit(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
+{
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ dm_log_info(DM_URI_THING_DELETE);
+
+ /* Request */
+ res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
+ device_name);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res != SUCCESS_RETURN) {
+ return res;
+ }
+
+ /* Operation */
+ res = dm_msg_thing_gateway_permit(request->params.value, request->params.value_length);
+
+ /* Response */
+ response->service_prefix = DM_URI_SYS_PREFIX;
+ response->service_name = dest->uri_name;
+ memcpy(response->product_key, product_key, strlen(product_key));
+ memcpy(response->device_name, device_name, strlen(device_name));
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_sub_register_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_SUB_REGISTER_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_sub_register_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_sub_unregister_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_SUB_UNREGISTER_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_sub_unregister_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_topo_add_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_TOPO_ADD_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_topo_add_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_topo_delete_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_TOPO_DELETE_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_topo_delete_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_topo_get_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_topo_get_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_thing_list_found_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_thing_list_found_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_combine_login_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_combine_login_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+
+int dm_msg_proc_combine_logout_reply(_IN_ dm_msg_source_t *source)
+{
+ int res = 0;
+ dm_msg_response_payload_t response;
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ char int_id[DM_UTILS_UINT32_STRLEN] = {0};
+#endif
+
+ dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
+
+ memset(&response, 0, sizeof(dm_msg_response_payload_t));
+
+ /* Response */
+ res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Operation */
+ dm_msg_combine_logout_reply(&response);
+
+ /* Remove Message From Cache */
+#if !defined(DM_MESSAGE_CACHE_DISABLED)
+ memcpy(int_id, response.id.value, response.id.value_length);
+ dm_msg_cache_remove(atoi(int_id));
+#endif
+ return SUCCESS_RETURN;
+}
+#endif
+
+#ifdef ALCS_ENABLED
+int dm_msg_proc_thing_dev_core_service_dev(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
+ _OU_ unsigned char **data, int *data_len)
+{
+ int res = 0;
+
+ dm_log_info(DM_URI_DEV_CORE_SERVICE_DEV);
+
+ /* Request */
+ res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
+ if (res < SUCCESS_RETURN) {
+ return res ;
+ }
+
+ /* Operation */
+ res = dm_msg_dev_core_service_dev((char **)data, data_len);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ /* Response */
+ response->service_prefix = NULL;
+ response->service_name = dest->uri_name;
+ response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+
+ return SUCCESS_RETURN;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_msg_process.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_msg_process.h
new file mode 100644
index 00000000..911949b8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_msg_process.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_MSG_PROCESS_H_
+#define _DM_MSG_PROCESS_H_
+
+#define DM_URI_SERVICE_DELIMITER '/'
+
+extern const char DM_URI_SYS_PREFIX[] DM_READ_ONLY;
+extern const char DM_URI_EXT_SESSION_PREFIX[] DM_READ_ONLY;
+extern const char DM_URI_EXT_NTP_PREFIX[] DM_READ_ONLY;
+extern const char DM_URI_EXT_ERROR_PREFIX[] DM_READ_ONLY;
+extern const char DM_URI_REPLY_SUFFIX[] DM_READ_ONLY;
+extern const char DM_URI_OTA_DEVICE_INFORM[] DM_READ_ONLY;
+extern const char DM_URI_THING_PROPERTY_DESIRED_GET[] DM_READ_ONLY;
+extern const char DM_URI_THING_PROPERTY_DESIRED_DELETE[] DM_READ_ONLY;
+extern const char DM_URI_THING_PROPERTY_DESIRED_GET_REPLY[] DM_READ_ONLY;
+extern const char DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY[] DM_READ_ONLY;
+/* From Cloud To Local Request And Response*/
+extern const char DM_URI_THING_MODEL_DOWN_RAW[] DM_READ_ONLY;
+extern const char DM_URI_THING_MODEL_DOWN_RAW_REPLY[] DM_READ_ONLY;
+
+/* From Local To Cloud Request And Response*/
+extern const char DM_URI_THING_MODEL_UP_RAW[] DM_READ_ONLY;
+extern const char DM_URI_THING_MODEL_UP_RAW_REPLY[] DM_READ_ONLY;
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ extern const char DM_URI_RRPC_REQUEST_WILDCARD[] DM_READ_ONLY;
+ /* From Cloud To Local Request And Response*/
+ extern const char DM_URI_THING_SERVICE_PROPERTY_SET[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_PROPERTY_SET_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_PROPERTY_GET[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_PROPERTY_GET_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_REQUEST_WILDCARD[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_REQUEST_WILDCARD2[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_REQUEST[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SERVICE_RESPONSE[] DM_READ_ONLY;
+
+
+ /* From Local To Cloud Request And Response*/
+ extern const char DM_URI_THING_EVENT_PROPERTY_POST[] DM_READ_ONLY;
+ extern const char DM_URI_THING_EVENT_PROPERTY_POST_REPLY[] DM_READ_ONLY;
+ #ifdef LOG_REPORT_TO_CLOUD
+ extern const char DM_URI_THING_LOG_POST[] DM_READ_ONLY;
+ #endif
+ extern const char DM_URI_THING_EVENT_POST[] DM_READ_ONLY;
+ extern const char DM_URI_THING_EVENT_POST_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_EVENT_POST_REPLY_WILDCARD[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DEVICEINFO_UPDATE[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DEVICEINFO_UPDATE_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DEVICEINFO_DELETE[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DEVICEINFO_DELETE_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DSLTEMPLATE_GET[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DSLTEMPLATE_GET_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DYNAMICTSL_GET[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DYNAMICTSL_GET_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_NTP_REQUEST[] DM_READ_ONLY;
+ extern const char DM_URI_NTP_RESPONSE[] DM_READ_ONLY;
+#endif
+
+extern const char DM_URI_DEV_CORE_SERVICE_DEV[] DM_READ_ONLY;
+
+#ifdef DEVICE_MODEL_GATEWAY
+ /* From Cloud To Local Request And Response*/
+ extern const char DM_URI_THING_TOPO_ADD_NOTIFY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_ADD_NOTIFY_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DISABLE[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DISABLE_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_ENABLE[] DM_READ_ONLY;
+ extern const char DM_URI_THING_ENABLE_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DELETE[] DM_READ_ONLY;
+ extern const char DM_URI_THING_DELETE_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_GATEWAY_PERMIT[] DM_READ_ONLY;
+ extern const char DM_URI_THING_GATEWAY_PERMIT_REPLY[] DM_READ_ONLY;
+
+ /* From Local To Cloud Request And Response*/
+ extern const char DM_URI_THING_SUB_REGISTER[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SUB_REGISTER_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SUB_UNREGISTER[] DM_READ_ONLY;
+ extern const char DM_URI_THING_SUB_UNREGISTER_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_ADD[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_ADD_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_DELETE[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_DELETE_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_GET[] DM_READ_ONLY;
+ extern const char DM_URI_THING_TOPO_GET_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_THING_LIST_FOUND[] DM_READ_ONLY;
+ extern const char DM_URI_THING_LIST_FOUND_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_COMBINE_LOGIN[] DM_READ_ONLY;
+ extern const char DM_URI_COMBINE_LOGIN_REPLY[] DM_READ_ONLY;
+ extern const char DM_URI_COMBINE_LOGOUT[] DM_READ_ONLY;
+ extern const char DM_URI_COMBINE_LOGOUT_REPLY[] DM_READ_ONLY;
+#endif
+
+int dm_disp_uri_prefix_split(_IN_ const char *prefix, _IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
+int dm_disp_uri_pkdn_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
+int dm_disp_uri_service_specific_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
+int dm_disp_uri_rrpc_request_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
+int dm_disp_uri_event_specific_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
+
+int dm_msg_proc_thing_model_down_raw(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_model_up_raw_reply(_IN_ dm_msg_source_t *source);
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+int dm_msg_proc_thing_service_property_set(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_service_property_get(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
+ _OU_ unsigned char **data, int *data_len);
+int dm_msg_proc_thing_property_desired_get_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_property_desired_delete_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_service_property_post(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_service_request(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_event_post_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_deviceinfo_update_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_deviceinfo_delete_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_dynamictsl_get_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_rrpc_request(_IN_ dm_msg_source_t *source);
+int dm_disp_ntp_response(_IN_ dm_msg_source_t *source);
+int dm_disp_ext_error_response(_IN_ dm_msg_source_t *source);
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+int dm_msg_proc_thing_topo_add_notify(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_disable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_enable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_delete(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_gateway_permit(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
+int dm_msg_proc_thing_sub_register_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_sub_unregister_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_topo_add_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_topo_delete_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_topo_get_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_thing_list_found_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_combine_login_reply(_IN_ dm_msg_source_t *source);
+int dm_msg_proc_combine_logout_reply(_IN_ dm_msg_source_t *source);
+#endif
+
+#ifdef ALCS_ENABLED
+int dm_msg_proc_thing_dev_core_service_dev(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
+ _OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
+ _OU_ unsigned char **data, int *data_len);
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_opt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_opt.c
new file mode 100644
index 00000000..75ffa8f7
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_opt.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+
+static dm_opt_ctx g_dm_opt = {
+ 0, 0, 1, 1, 1
+};
+
+int dm_opt_set(dm_opt_t opt, void *data)
+{
+ int res = SUCCESS_RETURN;
+
+ if (data == NULL) {
+ return FAIL_RETURN;
+ }
+
+ switch (opt) {
+ case DM_OPT_DOWNSTREAM_PROPERTY_POST_REPLY: {
+ int opt = *(int *)(data);
+ g_dm_opt.prop_post_reply_opt = opt;
+ }
+ break;
+ case DM_OPT_DOWNSTREAM_EVENT_POST_REPLY: {
+ int opt = *(int *)(data);
+ g_dm_opt.event_post_reply_opt = opt;
+ }
+ break;
+ case DM_OPT_UPSTREAM_PROPERTY_SET_REPLY: {
+ int opt = *(int *)(data);
+ g_dm_opt.prop_set_reply_opt = opt;
+ }
+ break;
+#ifdef DEVICE_MODEL_SHADOW
+ case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY: {
+ int opt = *(int *)(data);
+ g_dm_opt.prop_desired_get_reply_opt = opt;
+ }
+ break;
+ case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY: {
+ int opt = *(int *)(data);
+ g_dm_opt.prop_desired_delete_reply_opt = opt;
+ }
+ break;
+#endif
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ return res;
+}
+
+int dm_opt_get(dm_opt_t opt, void *data)
+{
+ int res = SUCCESS_RETURN;
+
+ if (data == NULL) {
+ return FAIL_RETURN;
+ }
+
+ switch (opt) {
+ case DM_OPT_DOWNSTREAM_PROPERTY_POST_REPLY: {
+ *(int *)(data) = g_dm_opt.prop_post_reply_opt;
+ }
+ break;
+ case DM_OPT_DOWNSTREAM_EVENT_POST_REPLY: {
+ *(int *)(data) = g_dm_opt.event_post_reply_opt;
+ }
+ break;
+ case DM_OPT_UPSTREAM_PROPERTY_SET_REPLY: {
+ *(int *)(data) = g_dm_opt.prop_set_reply_opt;
+ }
+ break;
+#ifdef DEVICE_MODEL_SHADOW
+ case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY: {
+ *(int *)(data) = g_dm_opt.prop_desired_delete_reply_opt;
+ }
+ break;
+ case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY: {
+ *(int *)(data) = g_dm_opt.prop_desired_get_reply_opt;
+ }
+ break;
+#endif
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ return res;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_opt.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_opt.h
new file mode 100644
index 00000000..552d846c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_opt.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+#ifndef _DM_OPT_H
+#define _DM_OPT_H
+
+typedef enum {
+ DM_OPT_DOWNSTREAM_PROPERTY_POST_REPLY,
+ DM_OPT_DOWNSTREAM_EVENT_POST_REPLY,
+ DM_OPT_UPSTREAM_PROPERTY_SET_REPLY,
+ DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY,
+ DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY
+} dm_opt_t;
+
+typedef struct {
+ int prop_post_reply_opt;
+ int event_post_reply_opt;
+ int prop_set_reply_opt;
+ int prop_desired_get_reply_opt;
+ int prop_desired_delete_reply_opt;
+} dm_opt_ctx;
+
+int dm_opt_set(dm_opt_t opt, void *data);
+int dm_opt_get(dm_opt_t opt, void *data);
+
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ota.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ota.c
new file mode 100644
index 00000000..6a974dab
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ota.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+
+static dm_ota_ctx_t g_dm_ota_ctx;
+
+static dm_ota_ctx_t *_dm_ota_get_ctx(void)
+{
+ return &g_dm_ota_ctx;
+}
+
+int dm_ota_init(void)
+{
+ dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
+ memset(ctx, 0, sizeof(dm_ota_ctx_t));
+
+ HAL_GetProductKey(ctx->product_key);
+ HAL_GetDeviceName(ctx->device_name);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_ota_sub(void)
+{
+ dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
+ void *handle = NULL;
+
+ /* Init OTA Handle */
+ handle = IOT_OTA_Init(ctx->product_key, ctx->device_name, NULL);
+ if (handle == NULL) {
+ return FAIL_RETURN;
+ }
+
+ ctx->ota_handle = handle;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_ota_deinit(void)
+{
+ dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
+
+ if (ctx->ota_handle) {
+ IOT_OTA_Deinit(ctx->ota_handle);
+ ctx->ota_handle = NULL;
+ }
+
+ return SUCCESS_RETURN;
+}
+#ifdef DEVICE_MODEL_GATEWAY
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+int dm_ota_switch_device(int devid)
+{
+ char pk[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char dn[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char ds[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+ int ret = dm_mgr_search_device_by_devid(devid, pk, dn, ds);
+ void *ota_handle = NULL;
+ int res = -1;
+ dm_ota_ctx_t *ctx = NULL;
+
+ if (SUCCESS_RETURN != ret) {
+ dm_log_err("could not find device by id, ret is %d", ret);
+ return FAIL_RETURN;
+ }
+ dm_log_info("do subdevice ota, pk, dn is %s, %s", pk, dn);
+
+ ota_handle = NULL;
+ res = dm_ota_get_ota_handle(&ota_handle);
+
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* if currently a device is doing OTA, do not interrupt */
+ if (IOT_OTA_IsFetching(ota_handle)) {
+ dm_log_info("OTA is processing, can not switch to another device");
+ return FAIL_RETURN;
+ }
+
+ dm_ota_deinit();
+ ctx = _dm_ota_get_ctx();
+ memset(ctx, 0, sizeof(dm_ota_ctx_t));
+
+ memcpy(ctx->product_key, pk, strlen(pk) + 1);
+ memcpy(ctx->device_name, dn, strlen(dn) + 1);
+ ret = dm_ota_sub();
+ if (ret < 0) {
+ dm_log_err("dm_ota_sub ret is %d, %s, %s\n", ret, pk, dn);
+ }
+ return ret;
+}
+#endif
+#endif
+
+int dm_ota_get_ota_handle(void **handle)
+{
+ dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
+
+ if (handle == NULL || *handle != NULL) {
+ return FAIL_RETURN;
+ }
+
+ if (ctx->ota_handle == NULL) {
+ return FAIL_RETURN;
+ }
+
+ *handle = ctx->ota_handle;
+
+ return SUCCESS_RETURN;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ota.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ota.h
new file mode 100644
index 00000000..8d25e46b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_ota.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_OTA_H_
+#define _DM_OTA_H_
+
+typedef struct {
+ void *ota_handle;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+} dm_ota_ctx_t;
+
+int dm_ota_init(void);
+int dm_ota_sub(void);
+int dm_ota_deinit(void);
+int dm_ota_get_ota_handle(void **handle);
+#ifdef DEVICE_MODEL_GATEWAY
+ #ifdef DEVICE_MODEL_SUBDEV_OTA
+ int dm_ota_switch_device(int devid);
+ #endif
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server.c
new file mode 100644
index 00000000..5735d9fd
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server.c
@@ -0,0 +1,284 @@
+#include "iotx_dm_internal.h"
+
+#ifdef ALCS_ENABLED
+
+#ifdef LOG_REPORT_TO_CLOUD
+ #include "iotx_log_report.h"
+#endif
+static int _dm_server_malloc_context(_IN_ NetworkAddr *remote, _IN_ CoAPMessage *message,
+ _OU_ dm_server_alcs_context_t **context)
+{
+ dm_server_alcs_context_t *alcs_context = NULL;
+
+ alcs_context = DM_malloc(sizeof(dm_server_alcs_context_t));
+ if (alcs_context == NULL) {
+ return FAIL_RETURN;
+ }
+ memset(alcs_context, 0, sizeof(dm_server_alcs_context_t));
+
+ alcs_context->ip = DM_malloc(strlen((char *)remote->addr) + 1);
+ if (alcs_context->ip == NULL) {
+ DM_free(alcs_context);
+ return FAIL_RETURN;
+ }
+ memset(alcs_context->ip, 0, strlen((char *)remote->addr) + 1);
+ memcpy(alcs_context->ip, (char *)remote->addr, strlen((char *)remote->addr) + 1);
+
+ alcs_context->port = remote->port;
+ dm_log_info("alcs_context->ip: %s", alcs_context->ip);
+ dm_log_info("alcs_context->port: %d", alcs_context->port);
+
+ alcs_context->token = DM_malloc(message->header.tokenlen);
+ if (alcs_context->token == NULL) {
+ DM_free(alcs_context->ip);
+ DM_free(alcs_context);
+ return FAIL_RETURN;
+ }
+ memset(alcs_context->token, 0, message->header.tokenlen);
+ memcpy(alcs_context->token, message->token, message->header.tokenlen);
+
+ alcs_context->token_len = message->header.tokenlen;
+
+ *context = alcs_context;
+
+ return SUCCESS_RETURN;
+}
+
+void dm_server_free_context(_IN_ void *ctx)
+{
+ dm_server_alcs_context_t *context = (dm_server_alcs_context_t *)ctx;
+ DM_free(context->ip);
+ DM_free(context->token);
+ DM_free(context);
+}
+
+static dm_server_uri_map_t g_dm_server_uri_map[] = {
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ {DM_URI_THING_SERVICE_PROPERTY_SET, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_property_set },
+ {DM_URI_THING_SERVICE_PROPERTY_GET, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_property_get },
+ {DM_URI_THING_EVENT_PROPERTY_POST, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_property_post },
+ {DM_URI_THING_SERVICE_REQUEST_WILDCARD2, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_request },
+#endif
+ {DM_URI_DEV_CORE_SERVICE_DEV, NULL, IOTX_DM_LOCAL_NO_AUTH, dm_server_thing_dev_core_service_dev },
+};
+
+int dm_server_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0, index = 0, auth = 0;
+ int number = sizeof(g_dm_server_uri_map) / sizeof(dm_server_uri_map_t);
+ char *uri = NULL;
+
+ for (index = 0; index < number; index++) {
+ res = dm_utils_service_name((char *)g_dm_server_uri_map[index].uri_prefix, (char *)g_dm_server_uri_map[index].uri_name,
+ product_key, device_name, &uri);
+ if (res < SUCCESS_RETURN) {
+ index--;
+ continue;
+ }
+
+ auth = (g_dm_server_uri_map[index].auth_type & IOTX_DM_SERVICE_LOCAL_AUTH) ? (IOTX_DM_MESSAGE_AUTH) :
+ (IOTX_DM_MESSAGE_NO_AUTH);
+ res = dm_server_subscribe(uri, (void *)g_dm_server_uri_map[index].callback, auth);
+ if (res < SUCCESS_RETURN) {
+ index--;
+ DM_free(uri);
+ continue;
+ }
+ DM_free(uri);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+void dm_server_alcs_event_handler(void *pcontext, void *phandle, iotx_alcs_event_msg_t *msg)
+{
+
+}
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+void dm_server_thing_service_property_set(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message)
+{
+ int res = 0;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+ dm_server_alcs_context_t *alcs_context = NULL;
+
+ res = _dm_server_malloc_context(remote, message, &alcs_context);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = paths;
+ source.payload = (unsigned char *)message->payload;
+ source.payload_len = message->payloadlen;
+ source.context = alcs_context;
+
+ dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_SET;
+
+ res = dm_msg_proc_thing_service_property_set(&source, &dest, &request, &response);
+ if (res < SUCCESS_RETURN) {
+ dm_server_free_context(alcs_context);
+ return;
+ }
+
+#ifdef LOG_REPORT_TO_CLOUD
+ {
+ extern void send_permance_info(char *input, int input_len, char *comments, int report_format);
+ if (SUCCESS_RETURN == check_target_msg(request.id.value, request.id.value_length)) {
+ send_permance_info(request.id.value, request.id.value_length, "2", 1);
+ }
+ }
+#endif
+
+ dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, "{}", strlen("{}"), (void *)alcs_context);
+ dm_server_free_context(alcs_context);
+}
+
+void dm_server_thing_service_request(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message)
+{
+ int res = 0;
+ dm_msg_source_t source;
+
+ dm_server_alcs_context_t *alcs_context = NULL;
+
+ res = _dm_server_malloc_context(remote, message, &alcs_context);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+
+ source.uri = paths;
+ source.payload = (unsigned char *)message->payload;
+ source.payload_len = message->payloadlen;
+ source.context = alcs_context;
+
+ if (dm_msg_proc_thing_service_request(&source) < 0) {
+ dm_server_free_context(alcs_context);
+ }
+}
+
+void dm_server_thing_service_property_get(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message)
+{
+ int res = 0;
+ dm_server_alcs_context_t *alcs_context = NULL;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+ unsigned char *data = NULL;
+ int data_len = 0;
+
+ res = _dm_server_malloc_context(remote, message, &alcs_context);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = paths;
+ source.payload = (unsigned char *)message->payload;
+ source.payload_len = message->payloadlen;
+ source.context = alcs_context;
+
+ dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_GET;
+
+ dm_msg_proc_thing_service_property_get(&source, &dest, &request, &response, &data, &data_len);
+
+#ifdef DEPRECATED_LINKKIT
+ dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, (char *)data, data_len, alcs_context);
+ DM_free(data);
+ dm_server_free_context(alcs_context);
+#endif
+}
+
+void dm_server_thing_service_property_post(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message)
+{
+ int res = 0;
+ dm_server_alcs_context_t *alcs_context = NULL;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+
+ res = _dm_server_malloc_context(remote, message, &alcs_context);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = paths;
+ source.payload = (unsigned char *)message->payload;
+ source.payload_len = message->payloadlen;
+ source.context = alcs_context;
+
+ dest.uri_name = DM_URI_THING_EVENT_PROPERTY_POST;
+
+ dm_msg_proc_thing_service_property_post(&source, &dest, &request, &response);
+
+ dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, "{}", strlen("{}"), alcs_context);
+ dm_server_free_context(alcs_context);
+}
+
+#endif
+void dm_server_thing_dev_core_service_dev(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message)
+{
+ int res = 0;
+ dm_server_alcs_context_t *alcs_context = NULL;
+ dm_msg_source_t source;
+ dm_msg_dest_t dest;
+ dm_msg_request_payload_t request;
+ dm_msg_response_t response;
+ unsigned char *data = NULL;
+ int data_len = 0;
+
+ res = _dm_server_malloc_context(remote, message, &alcs_context);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ memset(&source, 0, sizeof(dm_msg_source_t));
+ memset(&dest, 0, sizeof(dm_msg_dest_t));
+ memset(&request, 0, sizeof(dm_msg_request_payload_t));
+ memset(&response, 0, sizeof(dm_msg_response_t));
+
+ source.uri = paths;
+ source.payload = (unsigned char *)message->payload;
+ source.payload_len = message->payloadlen;
+ source.context = alcs_context;
+
+ dest.uri_name = DM_URI_DEV_CORE_SERVICE_DEV;
+
+ res = dm_msg_proc_thing_dev_core_service_dev(&source, &dest, &request, &response, &data, &data_len);
+ if (res < SUCCESS_RETURN) {
+ dm_server_free_context(alcs_context);
+ return;
+ }
+
+ dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, (char *)data, data_len, alcs_context);
+
+ if (response.code == IOTX_DM_ERR_CODE_SUCCESS) {
+ DM_free(data);
+ }
+ dm_server_free_context(alcs_context);
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server.h
new file mode 100644
index 00000000..2ada9788
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server.h
@@ -0,0 +1,29 @@
+#ifndef _DM_SERVER_H_
+#define _DM_SERVER_H_
+
+#ifdef ALCS_ENABLED
+typedef struct {
+ const char *uri_name;
+ const char *uri_prefix;
+ int auth_type;
+ CoAPRecvMsgHandler callback;
+} dm_server_uri_map_t;
+
+#define DM_SERVER_ALCS_NO_AUTH (0)
+#define DM_SERVER_ALCS_AUTH (1)
+
+void dm_server_alcs_event_handler(void *pcontext, void *phandle, iotx_alcs_event_msg_t *msg);
+
+int dm_server_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+void dm_server_thing_service_property_set(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message);
+void dm_server_thing_service_property_get(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message);
+void dm_server_thing_service_property_post(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message);
+void dm_server_thing_dev_core_service_dev(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message);
+void dm_server_thing_service_request(CoAPContext *context, const char *paths, NetworkAddr *remote,
+ CoAPMessage *message);
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server_adapter.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server_adapter.c
new file mode 100644
index 00000000..dc827706
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server_adapter.c
@@ -0,0 +1,140 @@
+#include "iotx_dm_internal.h"
+
+#ifdef ALCS_ENABLED
+
+static dm_server_ctx_t g_dm_server_ctx = {0};
+
+static dm_server_ctx_t *dm_server_get_ctx(void)
+{
+ return &g_dm_server_ctx;
+}
+
+int dm_server_open(void)
+{
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+ iotx_alcs_param_t alcs_param;
+ iotx_alcs_event_handle_t event_handle;
+
+ memset(&alcs_param, 0x0, sizeof(iotx_alcs_param_t));
+ memset(&event_handle, 0x0, sizeof(iotx_alcs_event_handle_t));
+
+ alcs_param.group = (char *)DM_SERVER_ALCS_ADDR;
+ alcs_param.port = DM_SERVER_ALCS_PORT;
+ alcs_param.send_maxcount = DM_SERVER_ALCS_SEND_MAXCOUNT;
+ alcs_param.waittime = DM_SERVER_ALCS_WAITTIME;
+ alcs_param.obs_maxcount = DM_SERVER_ALCS_OBS_MAXCOUNT;
+ alcs_param.res_maxcount = DM_SERVER_ALCS_RES_MAXCOUNT;
+ alcs_param.role = IOTX_ALCS_ROLE_CLIENT | IOTX_ALCS_ROLE_SERVER;
+ event_handle.h_fp = dm_server_alcs_event_handler;
+ event_handle.pcontext = NULL;
+
+ alcs_param.handle_event = &event_handle;
+
+ ctx->conn_handle = iotx_alcs_construct(&alcs_param);
+ if (ctx->conn_handle == NULL) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_server_connect(void)
+{
+
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+
+ return iotx_alcs_cloud_init(ctx->conn_handle);
+}
+
+int dm_server_close(void)
+{
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+
+ return iotx_alcs_destroy(&ctx->conn_handle);
+}
+
+int dm_server_send(char *uri, unsigned char *payload, int payload_len, void *context)
+{
+ int res = 0;
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+ iotx_alcs_msg_t alcs_msg;
+ dm_server_alcs_context_t *alcs_context = (dm_server_alcs_context_t *)context;
+
+ memset(&alcs_msg, 0, sizeof(iotx_alcs_msg_t));
+
+ alcs_msg.group_id = 0;
+ alcs_msg.ip = alcs_context ? alcs_context->ip : NULL;
+ alcs_msg.port = alcs_context ? alcs_context->port : 0;
+ alcs_msg.msg_code = (alcs_context && alcs_context->token_len
+ && alcs_context->token) ? ITOX_ALCS_COAP_MSG_CODE_205_CONTENT : ITOX_ALCS_COAP_MSG_CODE_GET;
+ alcs_msg.msg_type = IOTX_ALCS_MESSAGE_TYPE_CON;
+ alcs_msg.uri = uri;
+ alcs_msg.payload = payload;
+ alcs_msg.payload_len = payload_len;
+
+ if (alcs_context == NULL) {
+ res = iotx_alcs_observe_notify(ctx->conn_handle, alcs_msg.uri, alcs_msg.payload_len, alcs_msg.payload);
+ dm_log_info("Send Observe Notify Result %d", res);
+ } else if (alcs_context->ip && alcs_context->port && NULL == alcs_context->token) {
+ res = iotx_alcs_send(ctx->conn_handle, &alcs_msg);
+ dm_log_info("Send Result %d", res);
+ } else if (alcs_context->ip && alcs_context->port && alcs_context->token_len && alcs_context->token) {
+ res = iotx_alcs_send_Response(ctx->conn_handle, &alcs_msg, (uint8_t)alcs_context->token_len,
+ (uint8_t *)alcs_context->token);
+ dm_log_info("Send Response Result %d", res);
+ }
+
+ return res;
+}
+
+int dm_server_subscribe(char *uri, CoAPRecvMsgHandler callback, int auth_type)
+{
+ int res = 0;
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+ iotx_alcs_res_t alcs_res;
+
+ 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;
+ alcs_res.maxage = 60;
+ alcs_res.need_auth = auth_type;
+ alcs_res.callback = callback;
+
+ res = iotx_alcs_register_resource(ctx->conn_handle, &alcs_res);
+
+ dm_log_info("Register Resource Result: %d", res);
+
+ return res;
+}
+
+int dm_server_add_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0;
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+
+ res = iotx_alcs_add_sub_device(ctx->conn_handle, (const char *)product_key, (const char *)device_name);
+ dm_log_info("Add Device Result: %d, Product Key: %s, Device Name: %s", res, product_key, device_name);
+
+ return res;
+}
+
+int dm_server_del_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
+{
+ int res = 0;
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+
+ res = iotx_alcs_remove_sub_device(ctx->conn_handle, (const char *)product_key, (const char *)device_name);
+ dm_log_info("Del Device Result: %d, Product Key: %s, Device Name: %s", res, product_key, device_name);
+
+ return res;
+}
+
+int dm_server_yield(void)
+{
+ dm_server_ctx_t *ctx = dm_server_get_ctx();
+
+ return iotx_alcs_yield(ctx->conn_handle);
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server_adapter.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server_adapter.h
new file mode 100644
index 00000000..bfb49a75
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_server_adapter.h
@@ -0,0 +1,34 @@
+#ifndef _DM_SERVER_ADAPTER_H_
+#define _DM_SERVER_ADAPTER_H_
+
+#ifdef ALCS_ENABLED
+
+#define DM_SERVER_ALCS_ADDR "224.0.1.187"
+#define DM_SERVER_ALCS_PORT (5863)
+#define DM_SERVER_ALCS_SEND_MAXCOUNT (16)
+#define DM_SERVER_ALCS_WAITTIME (200)
+#define DM_SERVER_ALCS_OBS_MAXCOUNT (16)
+#define DM_SERVER_ALCS_RES_MAXCOUNT (255)
+
+typedef struct {
+ void *conn_handle;
+} dm_server_ctx_t;
+
+typedef struct {
+ char *ip;
+ uint16_t port;
+ char *token;
+ int token_len;
+} dm_server_alcs_context_t;
+
+int dm_server_open(void);
+int dm_server_connect(void);
+int dm_server_close(void);
+int dm_server_send(char *uri, unsigned char *payload, int payload_len, void *context);
+int dm_server_subscribe(char *uri, CoAPRecvMsgHandler callback, int auth_type);
+int dm_server_add_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+int dm_server_del_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+int dm_server_yield(void);
+
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_shadow.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_shadow.c
new file mode 100644
index 00000000..0bffa7f1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_shadow.c
@@ -0,0 +1,2535 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_dm_internal.h"
+
+#ifdef DEPRECATED_LINKKIT
+
+/* #define IOTX_DM_TSL_DEVELOP_TEST */
+
+/*****************************Internal Definition*****************************/
+
+typedef int (*dm_shw_data_set)(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+typedef int (*dm_shw_array_set)(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+typedef int (*dm_shw_data_get)(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+typedef int (*dm_shw_array_get)(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+typedef void (*dm_shw_data_free)(_IN_ dm_shw_data_value_t *data_value);
+typedef void (*dm_shw_array_free)(_IN_ dm_shw_data_value_t *data_value);
+typedef void (*dm_shw_data_print)(_IN_ dm_shw_data_value_t *data_value);
+
+typedef struct {
+ dm_shw_data_type_e type;
+ const char *name;
+ dm_shw_data_set func_set;
+ dm_shw_array_set func_array_set;
+ dm_shw_data_get func_get;
+ dm_shw_array_get func_array_get;
+ dm_shw_data_free func_free;
+ dm_shw_array_free func_array_free;
+} dm_shw_data_type_mapping_t;
+
+/* Data Set */
+static int _dm_shw_int_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+static int _dm_shw_float_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+static int _dm_shw_double_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+static int _dm_shw_text_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+static int _dm_shw_enum_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+static int _dm_shw_date_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+static int _dm_shw_bool_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
+
+/* Array Data Set */
+static int _dm_shw_array_int_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+static int _dm_shw_array_float_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+static int _dm_shw_array_double_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+static int _dm_shw_array_text_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+static int _dm_shw_array_enum_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+static int _dm_shw_array_date_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+static int _dm_shw_array_bool_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index);
+
+/* Data Get */
+static int _dm_shw_int_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+static int _dm_shw_float_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+static int _dm_shw_double_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+static int _dm_shw_text_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+static int _dm_shw_enum_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+static int _dm_shw_date_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+static int _dm_shw_bool_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value);
+
+/* Array Data Get */
+static int _dm_shw_array_int_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+static int _dm_shw_array_float_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+static int _dm_shw_array_double_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+static int _dm_shw_array_text_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+static int _dm_shw_array_enum_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+static int _dm_shw_array_date_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+static int _dm_shw_array_bool_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index);
+
+/* Data Free */
+static void _dm_shw_int_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_float_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_double_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_text_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_enum_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_date_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_bool_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_struct_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_property_free(_IN_ dm_shw_data_t *property);
+
+/* Array Data Free */
+static void _dm_shw_array_int_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_float_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_double_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_text_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_enum_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_date_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_bool_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_array_free(_IN_ dm_shw_data_value_t *data_value);
+static void _dm_shw_array_struct_free(_IN_ dm_shw_data_value_t *data_value);
+
+#if 0
+ /* Data Print */
+ static void _dm_shw_int_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_float_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_double_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_text_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_enum_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_date_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_bool_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_array_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_struct_print(_IN_ dm_shw_data_value_t *data_value);
+ static void _dm_shw_property_print(_IN_ dm_shw_data_t *property);
+#endif
+
+/* Data Search */
+static int _dm_shw_data_struct_search(_IN_ dm_shw_data_t *input, _IN_ char *key, _IN_ int key_len,
+ _OU_ dm_shw_data_t **output, _OU_ int *index);
+
+static dm_shw_data_type_mapping_t g_iotx_data_type_mapping[] = {
+ {DM_SHW_DATA_TYPE_NONE, "none", NULL, NULL, NULL, NULL, NULL, NULL },
+ {DM_SHW_DATA_TYPE_INT, "int", _dm_shw_int_set, _dm_shw_array_int_set, _dm_shw_int_get, _dm_shw_array_int_get, _dm_shw_int_free, _dm_shw_array_int_free },
+ {DM_SHW_DATA_TYPE_FLOAT, "float", _dm_shw_float_set, _dm_shw_array_float_set, _dm_shw_float_get, _dm_shw_array_float_get, _dm_shw_float_free, _dm_shw_array_float_free, },
+ {DM_SHW_DATA_TYPE_DOUBLE, "double", _dm_shw_double_set, _dm_shw_array_double_set, _dm_shw_double_get, _dm_shw_array_double_get, _dm_shw_double_free, _dm_shw_array_double_free, },
+ {DM_SHW_DATA_TYPE_TEXT, "text", _dm_shw_text_set, _dm_shw_array_text_set, _dm_shw_text_get, _dm_shw_array_text_get, _dm_shw_text_free, _dm_shw_array_text_free, },
+ {DM_SHW_DATA_TYPE_ENUM, "enum", _dm_shw_enum_set, _dm_shw_array_enum_set, _dm_shw_enum_get, _dm_shw_array_enum_get, _dm_shw_enum_free, _dm_shw_array_enum_free, },
+ {DM_SHW_DATA_TYPE_DATE, "date", _dm_shw_date_set, _dm_shw_array_date_set, _dm_shw_date_get, _dm_shw_array_date_get, _dm_shw_date_free, _dm_shw_array_date_free, },
+ {DM_SHW_DATA_TYPE_BOOL, "bool", _dm_shw_bool_set, _dm_shw_array_bool_set, _dm_shw_bool_get, _dm_shw_array_bool_get, _dm_shw_bool_free, _dm_shw_array_bool_free, },
+ {DM_SHW_DATA_TYPE_ARRAY, "array", NULL, NULL, NULL, NULL, _dm_shw_array_free, _dm_shw_array_array_free, },
+ {DM_SHW_DATA_TYPE_STRUCT, "struct", NULL, NULL, NULL, NULL, _dm_shw_struct_free, _dm_shw_array_struct_free, }
+};
+
+/*****************************************************************************/
+
+static int _dm_shw_data_array_search(_IN_ dm_shw_data_t *input, _IN_ int input_index, _IN_ char *key,
+ _IN_ int key_len, _OU_ dm_shw_data_t **output, _OU_ int *output_index)
+{
+ int res = 0, deli_offset = 0;
+
+ dm_shw_data_value_complex_t *complex_struct = (dm_shw_data_value_complex_t *)input->data_value.value;
+ /* dm_log_debug("Current Key: %s, Len: %d",key,key_len);
+ dm_log_debug("Current Item Identifier: %s",input->identifier); */
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &deli_offset);
+ if (res != SUCCESS_RETURN) {
+ deli_offset = key_len;
+ }
+
+ switch (complex_struct->type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_FLOAT:
+ case DM_SHW_DATA_TYPE_DOUBLE:
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_DATE:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ if (deli_offset != key_len) {
+ return FAIL_RETURN;
+ }
+ if (output) {
+ *output = input;
+ }
+ if (output_index) {
+ *output_index = input_index;
+ }
+ return SUCCESS_RETURN;
+ }
+ break;
+ case DM_SHW_DATA_TYPE_STRUCT: {
+ dm_shw_data_t *search_data = NULL;
+ if (complex_struct->value == NULL) {
+ return FAIL_RETURN;
+ }
+ search_data = (dm_shw_data_t *)complex_struct->value + input_index;
+ return _dm_shw_data_struct_search(search_data, key, deli_offset, output, output_index);
+ }
+ break;
+ default:
+ dm_log_err("Unknown Data Type: %d", complex_struct->type);
+ break;
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _dm_shw_data_struct_search(_IN_ dm_shw_data_t *input, _IN_ char *key,
+ _IN_ int key_len, _OU_ dm_shw_data_t **output, _OU_ int *index)
+{
+ int res = 0, item_index = 0, deli_offset = 0, partial_offset = 0;
+ int partial_input_len = 0, array_input_len = 0, array_index = 0;
+ dm_shw_data_t *data_item = NULL;
+
+ /* dm_log_debug("Current Key: %.*s",key_len,key); */
+
+ dm_shw_data_value_complex_t *complex_struct = (dm_shw_data_value_complex_t *)input->data_value.value;
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &deli_offset);
+ if (res != SUCCESS_RETURN) {
+ deli_offset = key_len;
+ }
+
+ partial_offset = deli_offset;
+ res = dm_utils_strarr_index(key, deli_offset, &partial_input_len, &array_input_len, &array_index);
+ if (res == SUCCESS_RETURN) {
+ /* dm_log_debug("Current Index: %d",array_index); */
+ partial_offset = partial_input_len;
+ }
+
+ for (item_index = 0; item_index < complex_struct->size; item_index++) {
+ data_item = (dm_shw_data_t *)complex_struct->value + item_index;
+ if (strlen(data_item->identifier) != partial_offset ||
+ memcmp(data_item->identifier, key, partial_offset) != 0) {
+ continue;
+ }
+
+ switch (data_item->data_value.type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_FLOAT:
+ case DM_SHW_DATA_TYPE_DOUBLE:
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_DATE:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ if (partial_input_len != 0 || deli_offset != key_len) {
+ return FAIL_RETURN;
+ }
+ if (output) {
+ *output = data_item;
+ }
+ return SUCCESS_RETURN;
+ }
+ break;
+ case DM_SHW_DATA_TYPE_ARRAY: {
+ int key_offset = (deli_offset == key_len) ? (deli_offset - 1) : (deli_offset + 1);
+ int key_len_offset = (deli_offset == key_len) ? (key_len) : (deli_offset + 1);
+ if ((partial_input_len == 0) && (deli_offset == key_len)) {
+ if (output) {
+ *output = data_item;
+ }
+ return SUCCESS_RETURN;
+ }
+ if (partial_input_len == 0) {
+ return FAIL_RETURN;
+ }
+ return _dm_shw_data_array_search(data_item, array_index, key + key_offset, key_len - key_len_offset, output, index);
+ }
+ case DM_SHW_DATA_TYPE_STRUCT: {
+ if (deli_offset == key_len) {
+ if (output) {
+ *output = data_item;
+ }
+ return SUCCESS_RETURN;
+ }
+ if (partial_input_len != 0) {
+ return FAIL_RETURN;
+ }
+ return _dm_shw_data_struct_search(data_item, key + deli_offset + 1, key_len - deli_offset - 1, output, index);
+ }
+ default:
+ dm_log_err("Unknown Data Type");
+ break;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _dm_shw_data_search(_IN_ dm_shw_data_t *input, _IN_ char *key,
+ _IN_ int key_len, _OU_ dm_shw_data_t **output, _OU_ int *index)
+{
+ int res = 0, deli_offset = 0, partial_offset = 0;
+ int partial_input_len = 0, array_input_len = 0, array_index = 0;
+
+ if (input == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &deli_offset);
+ if (res != SUCCESS_RETURN) {
+ deli_offset = key_len;
+ }
+
+ partial_offset = deli_offset;
+ res = dm_utils_strarr_index(key, deli_offset, &partial_input_len, &array_input_len, &array_index);
+ if (res == SUCCESS_RETURN) {
+ /* dm_log_debug("Current Index: %d",array_index); */
+ partial_offset = partial_input_len;
+ }
+
+ /* dm_log_debug("Current Input Identifier: %s",input->identifier);
+ dm_log_debug("Current Compare Key: %.*s",partial_offset,key); */
+
+ if (strlen(input->identifier) != partial_offset ||
+ memcmp(input->identifier, key, partial_offset) != 0) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier Found: %s", input->identifier);
+
+ switch (input->data_value.type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_FLOAT:
+ case DM_SHW_DATA_TYPE_DOUBLE:
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_ENUM:
+ case DM_SHW_DATA_TYPE_DATE:
+ case DM_SHW_DATA_TYPE_BOOL: {
+ if (partial_input_len != 0 || deli_offset != key_len) {
+ return FAIL_RETURN;
+ }
+ if (output) {
+ *output = input;
+ }
+ return SUCCESS_RETURN;
+ }
+ break;
+ case DM_SHW_DATA_TYPE_ARRAY: {
+ int key_offset = (deli_offset == key_len) ? (deli_offset - 1) : (deli_offset + 1);
+ int key_len_offset = (deli_offset == key_len) ? (key_len) : (deli_offset + 1);
+ if ((partial_input_len == 0) && (deli_offset == key_len)) {
+ if (output) {
+ *output = input;
+ }
+ return SUCCESS_RETURN;
+ }
+ if (partial_input_len == 0) {
+ return FAIL_RETURN;
+ }
+ return _dm_shw_data_array_search(input, array_index, key + key_offset, key_len - key_len_offset, output, index);
+ }
+ break;
+ case DM_SHW_DATA_TYPE_STRUCT: {
+ if (deli_offset == key_len) {
+ if (output) {
+ *output = input;
+ }
+ return SUCCESS_RETURN;
+ }
+ if (partial_input_len != 0) {
+ return FAIL_RETURN;
+ }
+ return _dm_shw_data_struct_search(input, key + deli_offset + 1, key_len - deli_offset - 1, output, index);
+ }
+ break;
+ default:
+ dm_log_err("Unknow Data Type");
+ break;
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _dm_shw_property_search(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len,
+ _OU_ dm_shw_data_t **property, _OU_ int *index)
+{
+ int res = 0, item_index = 0;
+ dm_shw_data_t *property_item = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (shadow->property_number == 0 || shadow->properties == NULL) {
+ return DM_TSL_PROPERTY_NOT_EXIST;
+ }
+
+ for (item_index = 0; item_index < shadow->property_number; item_index++) {
+ property_item = shadow->properties + item_index;
+ res = _dm_shw_data_search(property_item, key, key_len, property, index);
+ if (res == SUCCESS_RETURN) {
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _dm_shw_event_output_search(_IN_ dm_shw_data_t *outputdatas, _IN_ int number, _IN_ char *key,
+ _IN_ int key_len, _OU_ dm_shw_data_t **event_data, _OU_ int *index)
+{
+ int res = 0, item_index = 0;
+ dm_shw_data_t *outputdata = NULL;
+
+ if (outputdatas == NULL || number <= 0 || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (item_index = 0; item_index < number; item_index++) {
+ outputdata = outputdatas + item_index;
+ res = _dm_shw_data_search(outputdata, key, key_len, event_data, index);
+ if (res == SUCCESS_RETURN) {
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_event_search(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ dm_shw_event_t **event)
+{
+ int index = 0;
+ dm_shw_event_t *dtsl_event = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->event_number; index++) {
+ dtsl_event = shadow->events + index;
+ if ((strlen(dtsl_event->identifier) == key_len) &&
+ (memcmp(dtsl_event->identifier, key, key_len) == 0)) {
+ /* dm_log_debug("TSL Event Found: %s",dtsl_event->identifier); */
+ if (event) {
+ *event = dtsl_event;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ /* dm_log_debug("TSL Event Not Found: %.*s",key_len,key); */
+
+ return FAIL_RETURN;
+}
+
+static int _dm_shw_service_input_output_search(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_service_t *service,
+ _IN_ char *key, _IN_ int key_len, _OU_ dm_shw_data_t **service_data, _OU_ int *index)
+{
+ int res = 0, item_index = 0, datas_number = 0;
+ dm_shw_data_t *datas = NULL;
+ dm_shw_data_t *data = NULL;
+
+ if (type == DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA) {
+ datas = service->input_datas;
+ datas_number = service->input_data_number;
+ } else {
+ datas = service->output_datas;
+ datas_number = service->output_data_number;
+ }
+
+ for (item_index = 0; item_index < datas_number; item_index++) {
+ data = datas + item_index;
+ res = _dm_shw_data_search(data, key, key_len, service_data, index);
+ if (res == SUCCESS_RETURN) {
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_service_search(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len,
+ _OU_ dm_shw_service_t **service)
+{
+ int index = 0;
+ dm_shw_service_t *dtsl_service = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->service_number; index++) {
+ dtsl_service = shadow->services + index;
+ if ((strlen(dtsl_service->identifier) == key_len) &&
+ (memcmp(dtsl_service->identifier, key, key_len) == 0)) {
+ /* dm_log_debug("TSL Service Found: %s",dtsl_service->identifier); */
+ if (service) {
+ *service = dtsl_service;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ /* dm_log_debug("TSL Service Not Found: %.*s",key_len,key); */
+
+ return FAIL_RETURN;
+}
+
+int dm_shw_create(_IN_ iotx_dm_tsl_type_t type, _IN_ const char *tsl, _IN_ int tsl_len, _OU_ dm_shw_t **shadow)
+{
+ int res = 0;
+
+ if (shadow == NULL || *shadow != NULL || tsl == NULL || tsl_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ switch (type) {
+ case IOTX_DM_TSL_TYPE_ALINK: {
+ res = dm_tsl_alink_create(tsl, tsl_len, shadow);
+ }
+ break;
+ case IOTX_DM_TSL_TYPE_TLV: {
+ /* TODO for yusan*/
+ res = FAIL_RETURN;
+ }
+ break;
+ default:
+ dm_log_err("Unknown TSL Type");
+ res = FAIL_RETURN;
+ break;
+ }
+
+ return res;
+}
+
+int dm_shw_get_property_data(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+
+ if (shadow == NULL || key == NULL || key_len <= 0 || data == NULL || *data != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_shw_property_search(shadow, key, key_len, (dm_shw_data_t **)data, NULL);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_PROPERTY_NOT_EXIST;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_service_input_output_data(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
+ _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+ int offset = 0, array_index = 0;
+ char *pos = NULL;
+ dm_shw_service_t *service = NULL;
+ dm_shw_data_t *service_data = NULL;
+
+ if (type < DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA || type > DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA || shadow == NULL
+ || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &offset);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Key: %.*s", key_len, key);
+
+ res = _dm_shw_service_search(shadow, key, offset, &service);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ pos = key + offset + 1;
+ dm_log_debug("TSL Service input/output Data Search, Event Data ID: %s", pos);
+
+ res = _dm_shw_service_input_output_search(type, service, pos, strlen(pos), &service_data, &array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ if (data) {
+ *data = (void *)service_data;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_event_output_data(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
+{
+ int res = 0;
+ int offset = 0, array_index = 0;
+ char *pos = NULL;
+ dm_shw_event_t *event = NULL;
+ dm_shw_data_t *event_data = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &offset);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Key: %.*s", key_len, key);
+
+ res = _dm_shw_event_search(shadow, key, offset, &event);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ pos = key + offset + 1;
+ /* dm_log_debug("TSL Event Output Data Search, Event Data ID: %s",pos); */
+
+ res = _dm_shw_event_output_search(event->output_datas, event->output_data_number, pos, strlen(pos), &event_data,
+ &array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ if (data) {
+ *data = (void *)event_data;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_data_type(_IN_ void *data, _OU_ dm_shw_data_type_e *type)
+{
+ dm_shw_data_t *data_item = (dm_shw_data_t *)data;
+
+ if (data_item == NULL || type == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (data_item->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ dm_shw_data_value_complex_t *complex_value = (dm_shw_data_value_complex_t *)data_item->data_value.value;
+ *type = complex_value->type;
+ } else {
+ *type = data_item->data_value.type;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_event(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **event)
+{
+ int index = 0;
+ dm_shw_event_t *dtsl_event = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->event_number; index++) {
+ dtsl_event = shadow->events + index;
+ if ((strlen(dtsl_event->identifier) == key_len) &&
+ (memcmp(dtsl_event->identifier, key, key_len) == 0)) {
+ if (event) {
+ *event = (dm_shw_event_t *)dtsl_event;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_shw_get_service(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **service)
+{
+ int index = 0;
+ dm_shw_service_t *dtsl_service = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->event_number; index++) {
+ dtsl_service = shadow->services + index;
+ if ((strlen(dtsl_service->identifier) == key_len) &&
+ (memcmp(dtsl_service->identifier, key, key_len) == 0)) {
+ if (service) {
+ *service = (dm_shw_service_t *)dtsl_service;
+ }
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_shw_get_property_number(_IN_ dm_shw_t *shadow, _OU_ int *number)
+{
+ if (shadow == NULL || number == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *number = shadow->property_number;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_service_number(_IN_ dm_shw_t *shadow, _OU_ int *number)
+{
+ if (shadow == NULL || number == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *number = shadow->service_number;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_event_number(_IN_ dm_shw_t *shadow, _OU_ int *number)
+{
+ if (shadow == NULL || number == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *number = shadow->event_number;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_property_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **property)
+{
+ if (shadow == NULL || index < 0 || index >= shadow->property_number ||
+ property == NULL || *property != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *property = (void *)(shadow->properties + index);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_service_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **service)
+{
+ if (shadow == NULL || index < 0 || index >= shadow->service_number ||
+ service == NULL || *service != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *service = (void *)(shadow->services + index);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_event_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **event)
+{
+ if (shadow == NULL || index < 0 || index >= shadow->event_number ||
+ event == NULL || *event != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *event = (void *)(shadow->events + index);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_service_by_identifier(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _OU_ void **service)
+{
+ int index = 0;
+ dm_shw_service_t *search_service = NULL;
+
+ if (shadow == NULL || identifier == NULL ||
+ service == NULL || *service != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->service_number; index++) {
+ search_service = shadow->services + index;
+ if ((strlen(search_service->identifier) == strlen(identifier)) &&
+ (memcmp(search_service->identifier, identifier, strlen(identifier)) == 0)) {
+ *service = (void *)search_service;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_shw_get_event_by_identifier(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _OU_ void **event)
+{
+ int index = 0;
+ dm_shw_event_t *search_event = NULL;
+
+ if (shadow == NULL || identifier == NULL ||
+ event == NULL || *event != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->event_number; index++) {
+ search_event = shadow->events + index;
+ if ((strlen(search_event->identifier) == strlen(identifier)) &&
+ (memcmp(search_event->identifier, identifier, strlen(identifier)) == 0)) {
+ *event = (void *)search_event;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_shw_get_property_identifier(_IN_ void *property, _OU_ char **identifier)
+{
+ dm_shw_data_t *property_item = (dm_shw_data_t *)property;
+
+ if (property_item == NULL || identifier == NULL || *identifier != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *identifier = property_item->identifier;
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_service_method(_IN_ void *service, _OU_ char **method)
+{
+ int service_method_len = 0;
+ const char *service_method_fmt = "thing.service.%s";
+ dm_shw_service_t *service_item = (dm_shw_service_t *)service;
+
+ if (service_item == NULL || method == NULL || *method != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ service_method_len = (strlen(service_method_fmt) + strlen(service_item->identifier) + 1);
+ *method = DM_malloc(service_method_len);
+ if (*method == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*method, 0, service_method_len);
+ HAL_Snprintf(*method, service_method_len, service_method_fmt, service_item->identifier);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_event_method(_IN_ void *event, _OU_ char **method)
+{
+ int event_method_len = 0;
+ const char *post_identifier = "post";
+ const char *property_identifier = "property";
+ const char *identifier = NULL;
+ const char *event_method_fmt = "thing.event.%s.post";
+ dm_shw_event_t *event_item = (dm_shw_event_t *)event;
+
+ if (event_item == NULL || method == NULL || *method != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* God Damn It Special Case! */
+ if ((strlen(event_item->identifier) == strlen(post_identifier)) &&
+ (memcmp(event_item->identifier, post_identifier, strlen(post_identifier)) == 0)) {
+ identifier = property_identifier;
+ } else {
+ identifier = (const char *)event_item->identifier;
+ }
+
+ event_method_len = (strlen(event_method_fmt) + strlen(identifier) + 1);
+ *method = DM_malloc(event_method_len);
+ if (*method == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*method, 0, event_method_len);
+ HAL_Snprintf(*method, event_method_len, event_method_fmt, identifier);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_int_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ int int_set = (value == NULL) ? (0) : (*(int *)value);
+
+ data_value->value_int = int_set;
+ dm_log_debug("Current Int Value Be Set(Int): %d", data_value->value_int);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_float_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ float float_set = (value == NULL) ? (0) : (*(float *)value);
+
+ data_value->value_float = float_set;
+ dm_log_debug("Current Float Value Be Set(Float): %f", data_value->value_float);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_double_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ double double_set = (value == NULL) ? (0) : (*(double *)value);
+
+ data_value->value_double = double_set;
+ dm_log_debug("Current Double Value Be Set(Double): %f", data_value->value_double);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_text_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ int res = 0;
+ char *value_set = (value == NULL) ? ("NULL") : ((char *)value);
+ int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);
+
+ if (data_value->value) {
+ DM_free(data_value->value);
+ data_value->value = NULL;
+ }
+ res = dm_utils_copy(value_set, value_set_len, &data_value->value, value_set_len + 1);
+ if (res != SUCCESS_RETURN) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ dm_log_debug("Current Text Value Be Set(String): %s", data_value->value);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_enum_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ int enum_set = (value == NULL) ? (0) : (*(int *)value);
+
+ enum_set = (enum_set < 0) ? (0) : (enum_set);
+
+ data_value->value_int = enum_set;
+ dm_log_debug("Current Enum Value Be Set(Enum): %d", data_value->value_int);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_date_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ int res = 0;
+ char *value_set = (value == NULL) ? ("NULL") : ((char *)value);
+ int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);
+
+ if (data_value->value) {
+ DM_free(data_value->value);
+ data_value->value = NULL;
+ }
+ res = dm_utils_copy(value_set, value_set_len, &data_value->value, value_set_len + 1);
+ if (res != SUCCESS_RETURN) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ dm_log_debug("Current Date Value Be Set(String): %s", data_value->value);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_bool_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ int int_set = (value == NULL) ? (0) : (*(int *)value);
+
+ int_set = (int_set == 0) ? (int_set) : ((int_set == 1) ? (int_set) : (0));
+
+ data_value->value_int = int_set;
+ dm_log_debug("Current Bool Value Be Set(Bool): %d", data_value->value_int);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_int_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ int int_set = (value == NULL) ? (0) : (*(int *)value);
+
+ *((int *)(complex_array->value) + index) = int_set;
+ dm_log_debug("Current Array Value Be Set(Int), Index: %d, Value: %d", index, *((int *)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_float_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ float float_set = (value == NULL) ? (0) : (*(float *)value);
+
+ *((float *)(complex_array->value) + index) = float_set;
+ dm_log_debug("Current Array Value Be Set(Float), Index: %d, Value: %f", index,
+ *((float *)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_double_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ double double_set = (value == NULL) ? (0) : (*(double *)value);
+
+ *((double *)(complex_array->value) + index) = double_set;
+ dm_log_debug("Current Array Value Be Set(Double), Index: %d, Value: %f", index,
+ *((double *)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_text_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ int res = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ char *text_set = (value == NULL) ? ("NULL") : ((char *)value);
+ int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);
+
+ if (*((char **)(complex_array->value) + index)) {
+ DM_free(*((char **)(complex_array->value) + index));
+ *((char **)(complex_array->value) + index) = NULL;
+ }
+
+ res = dm_utils_copy(text_set, value_set_len, (void **)((char **)(complex_array->value) + index), value_set_len + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Current Array Value Be Set(Text String), Index: %d, Value: %s", index,
+ *((char **)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_enum_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ int int_set = (value == NULL) ? (0) : (*(int *)value);
+
+ *((int *)(complex_array->value) + index) = int_set;
+ dm_log_debug("Current Array Value Be Set(Enum), Index: %d, Value: %d", index, *((int *)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_date_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ int res = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ char *text_set = (value == NULL) ? ("NULL") : ((char *)value);
+ int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);
+
+ if (*((char **)(complex_array->value) + index)) {
+ DM_free(*((char **)(complex_array->value) + index));
+ *((char **)(complex_array->value) + index) = NULL;
+ }
+
+ res = dm_utils_copy(text_set, value_set_len, (void **)((char **)(complex_array->value) + index), value_set_len + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Current Array Value Be Set(Date String), Index: %d, Value: %s", index,
+ *((char **)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_bool_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+ int int_set = (value == NULL) ? (0) : (*(int *)value);
+
+ *((int *)(complex_array->value) + index) = int_set;
+ dm_log_debug("Current Array Value Be Set(Bool), Index: %d, Value: %d", index, *((int *)(complex_array->value) + index));
+
+ return SUCCESS_RETURN;
+}
+
+
+static int _dm_shw_data_array_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
+ _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array == NULL || index < 0 || index >= complex_array->size) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (g_iotx_data_type_mapping[complex_array->type].func_array_set == NULL) {
+ return FAIL_RETURN;
+ }
+
+ return g_iotx_data_type_mapping[complex_array->type].func_array_set(data_value, value, value_len, index);
+}
+
+static int _dm_shw_data_set(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
+{
+ if (g_iotx_data_type_mapping[data_value->type].func_set == NULL) {
+ return FAIL_RETURN;
+ }
+
+ return g_iotx_data_type_mapping[data_value->type].func_set(data_value, value, value_len);
+}
+
+int dm_shw_set_property_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0, array_index = 0;
+ dm_shw_data_t *data = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Key:%d %s", key_len, key);
+ res = _dm_shw_property_search(shadow, key, key_len, &data, &array_index);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (data->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ dm_log_debug("Current Found Data Index: %d", array_index);
+ res = _dm_shw_data_array_set(&data->data_value, value, value_len, array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_PROPERTY_SET_FAILED;
+ }
+ } else {
+ res = _dm_shw_data_set(&data->data_value, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_PROPERTY_SET_FAILED;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_int_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ *(int *)(value) = data_value->value_int;
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_float_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ *(float *)(value) = data_value->value_float;
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_double_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ *(double *)(value) = data_value->value_double;
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_text_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ int res = 0;
+
+ if (*(char **)value != NULL || data_value->value == NULL) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_copy_direct(data_value->value, strlen(data_value->value), (void **)value, strlen(data_value->value) + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_enum_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ *(int *)(value) = data_value->value_int;
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_date_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ int res = 0;
+
+ if (*(char **)value != NULL || data_value->value == NULL) {
+ return FAIL_RETURN;
+ }
+
+ res = dm_utils_copy_direct(data_value->value, strlen(data_value->value), (void **)value, strlen(data_value->value) + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_bool_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ *(int *)(value) = data_value->value_int;
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_int_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || ((int *)(complex_array->value) + index) == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *((int *)value) = *((int *)(complex_array->value) + index);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_float_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || ((float *)(complex_array->value) + index) == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *((float *)value) = *((float *)(complex_array->value) + index);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_double_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || ((double *)(complex_array->value) + index) == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *((double *)value) = *((double *)(complex_array->value) + index);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_text_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ int res = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || *((char **)(complex_array->value) + index) == NULL || *(char **)value != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_copy_direct(*((char **)(complex_array->value) + index),
+ strlen(*((char **)(complex_array->value) + index)),
+ (void **)value, strlen(*((char **)(complex_array->value) + index)) + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_enum_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || ((int *)(complex_array->value) + index) == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *((int *)value) = *((int *)(complex_array->value) + index);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_date_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ int res = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || *((char **)(complex_array->value) + index) == NULL || *(char **)value != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_copy_direct(*((char **)(complex_array->value) + index),
+ strlen(*((char **)(complex_array->value) + index)),
+ (void **)value, strlen(*((char **)(complex_array->value) + index)) + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_bool_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array->value == NULL || ((int *)(complex_array->value) + index) == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *((int *)value) = *((int *)(complex_array->value) + index);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_data_array_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value, _IN_ int index)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array == NULL || index < 0 || index >= complex_array->size) {
+ return FAIL_RETURN;
+ }
+
+ if (g_iotx_data_type_mapping[complex_array->type].func_array_get == NULL) {
+ return FAIL_RETURN;
+ }
+
+ return g_iotx_data_type_mapping[complex_array->type].func_array_get(data_value, value, index);
+}
+
+static int _dm_shw_data_get(_IN_ dm_shw_data_value_t *data_value, _IN_ void *value)
+{
+ if (g_iotx_data_type_mapping[data_value->type].func_get == NULL) {
+ return FAIL_RETURN;
+ }
+
+ return g_iotx_data_type_mapping[data_value->type].func_get(data_value, value);
+}
+
+int dm_shw_get_property_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void *value)
+{
+ int res = 0, array_index = 0;
+ dm_shw_data_t *data = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = _dm_shw_property_search(shadow, key, key_len, &data, &array_index);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Current Found Data: %s", data->identifier);
+ if (data->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ dm_log_debug("Current Found Data Index: %d", array_index);
+ res = _dm_shw_data_array_get(&data->data_value, value, array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_PROPERTY_GET_FAILED;
+ }
+ } else {
+ res = _dm_shw_data_get(&data->data_value, value);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_PROPERTY_GET_FAILED;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_set_event_output_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len)
+{
+ int res = 0, array_index = 0;
+ int offset = 0;
+ char *pos = NULL;
+ dm_shw_event_t *event = NULL;
+ dm_shw_data_t *event_data = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &offset);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Key: %.*s", key_len, key);
+
+ res = _dm_shw_event_search(shadow, key, offset, &event);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ pos = key + offset + 1;
+ /* dm_log_debug("TSL Event Output Data Search, Event Data ID: %s",pos); */
+
+ res = _dm_shw_event_output_search(event->output_datas, event->output_data_number, pos, strlen(pos), &event_data,
+ &array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ if (event_data->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ res = _dm_shw_data_array_set(&event_data->data_value, value, value_len, array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_SET_FAILED;
+ }
+ } else {
+ res = _dm_shw_data_set(&event_data->data_value, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_SET_FAILED;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_event_output_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+ int offset = 0, array_index = 0;
+ char *pos = NULL;
+ dm_shw_event_t *event = NULL;
+ dm_shw_data_t *event_data = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &offset);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Key: %.*s", key_len, key);
+
+ res = _dm_shw_event_search(shadow, key, offset, &event);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ pos = key + offset + 1;
+ dm_log_debug("TSL Event Output Data Search, Event Data ID: %s", pos);
+
+ res = _dm_shw_event_output_search(event->output_datas, event->output_data_number, pos, strlen(pos), &event_data,
+ &array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_NOT_EXIST;
+ }
+
+ if (event_data->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ res = _dm_shw_data_array_get(&event_data->data_value, value, array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_GET_FAILED;
+ }
+ } else {
+ res = _dm_shw_data_get(&event_data->data_value, value);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_EVENT_GET_FAILED;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_set_service_input_output_value(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
+ _IN_ int key_len, _IN_ void *value, _IN_ int value_len)
+{
+ int res = 0, array_index = 0;
+ int offset = 0;
+ char *pos = NULL;
+ dm_shw_service_t *service = NULL;
+ dm_shw_data_t *service_data = NULL;
+
+ if (type < DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA || type > DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA || shadow == NULL
+ || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &offset);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Key: %.*s", key_len, key);
+
+ res = _dm_shw_service_search(shadow, key, offset, &service);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_NOT_EXIST;
+ }
+
+ pos = key + offset + 1;
+ dm_log_debug("TSL Service Input/Output Data Search, Event Data ID: %s", pos);
+
+ res = _dm_shw_service_input_output_search(type, service, pos, strlen(pos), &service_data, &array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_NOT_EXIST;
+ }
+
+ if (service_data->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ res = _dm_shw_data_array_set(&service_data->data_value, value, value_len, array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_SET_FAILED;
+ }
+ } else {
+ res = _dm_shw_data_set(&service_data->data_value, value, value_len);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_SET_FAILED;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_get_service_input_output_value(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
+ _IN_ int key_len, _IN_ void *value)
+{
+ int res = 0;
+ int offset = 0, array_index = 0;
+ char *pos = NULL;
+ dm_shw_service_t *service = NULL;
+ dm_shw_data_t *service_data = NULL;
+
+ if (shadow == NULL || key == NULL || key_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = dm_utils_memtok(key, key_len, DM_SHW_KEY_DELIMITER, 1, &offset);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("key: %.*s", key_len, key);
+
+ res = _dm_shw_service_search(shadow, key, offset, &service);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_NOT_EXIST;
+ }
+
+ pos = key + offset + 1;
+ dm_log_debug("TSL Service Input/Output Data Search, Event Data ID: %s", pos);
+
+ res = _dm_shw_service_input_output_search(type, service, pos, strlen(pos), &service_data, &array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_NOT_EXIST;
+ }
+
+ if (service_data->data_value.type == DM_SHW_DATA_TYPE_ARRAY) {
+ res = _dm_shw_data_array_get(&service_data->data_value, value, array_index);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_GET_FAILED;
+ }
+ } else {
+ res = _dm_shw_data_get(&service_data->data_value, value);
+ if (res != SUCCESS_RETURN) {
+ return DM_TSL_SERVICE_GET_FAILED;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_int_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ lite_cjson_add_number_to_object(lite, data->identifier, data->data_value.value_int);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_float_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ lite_cjson_add_number_to_object(lite, data->identifier, data->data_value.value_float);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_double_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ lite_cjson_add_number_to_object(lite, data->identifier, data->data_value.value_double);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_string_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ char *value = (data->data_value.value == NULL) ? ("") : (data->data_value.value);
+ lite_cjson_add_string_to_object(lite, data->identifier, value);
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite);
+static int _dm_shw_struct_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite);
+static int _dm_shw_data_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite);
+
+static int _dm_shw_array_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ int res = SUCCESS_RETURN, index = 0;
+ lite_cjson_item_t *array = NULL, *array_item = NULL;
+ dm_shw_data_value_complex_t *complex_array = NULL;
+
+ if (data == NULL || lite == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ complex_array = data->data_value.value;
+
+ if (lite->type == cJSON_Array) {
+ array = lite_cjson_create_object();
+ if (array == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ }
+
+ array_item = lite_cjson_create_array();
+ if (array_item == NULL) {
+ if (array) {
+ lite_cjson_delete(array);
+ }
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ switch (complex_array->type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_BOOL:
+ case DM_SHW_DATA_TYPE_ENUM: {
+ int value = 0;
+ for (index = 0; index < complex_array->size; index++) {
+ value = *((int *)(complex_array->value) + index);
+ lite_cjson_add_item_to_array(array_item, lite_cjson_create_number((double)value));
+ }
+ if (lite->type == cJSON_Array) {
+ lite_cjson_add_item_to_object(array, data->identifier, array_item);
+ lite_cjson_add_item_to_array(lite, array);
+ } else {
+ lite_cjson_add_item_to_object(lite, data->identifier, array_item);
+ lite_cjson_delete(array);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ float value = 0;
+ for (index = 0; index < complex_array->size; index++) {
+ value = *((float *)(complex_array->value) + index);
+ lite_cjson_add_item_to_array(array_item, lite_cjson_create_number((double)value));
+ }
+ if (lite->type == cJSON_Array) {
+ lite_cjson_add_item_to_object(array, data->identifier, array_item);
+ lite_cjson_add_item_to_array(lite, array);
+ } else {
+ lite_cjson_add_item_to_object(lite, data->identifier, array_item);
+ lite_cjson_delete(array);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ double value = 0;
+ for (index = 0; index < complex_array->size; index++) {
+ value = *((double *)(complex_array->value) + index);
+ lite_cjson_add_item_to_array(array_item, lite_cjson_create_number(value));
+ }
+ if (lite->type == cJSON_Array) {
+ lite_cjson_add_item_to_object(array, data->identifier, array_item);
+ lite_cjson_add_item_to_array(lite, array);
+ } else {
+ lite_cjson_add_item_to_object(lite, data->identifier, array_item);
+ lite_cjson_delete(array);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ char *value = NULL;
+ for (index = 0; index < complex_array->size; index++) {
+ value = *((char **)(complex_array->value) + index);
+ value = (value == NULL) ? ("") : (value);
+ lite_cjson_add_item_to_array(array_item, lite_cjson_create_string((const char *)value));
+ }
+ if (lite->type == cJSON_Array) {
+ lite_cjson_add_item_to_object(array, data->identifier, array_item);
+ lite_cjson_add_item_to_array(lite, array);
+ } else {
+ lite_cjson_add_item_to_object(lite, data->identifier, array_item);
+ lite_cjson_delete(array);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_ARRAY: {
+ /* TODO */
+ }
+ break;
+ case DM_SHW_DATA_TYPE_STRUCT: {
+ dm_shw_data_t *array_data = NULL;
+ for (index = 0; index < complex_array->size; index++) {
+ array_data = (dm_shw_data_t *)(complex_array->value) + index;
+ if (array_data) {
+ _dm_shw_struct_insert_json_item(array_data, array_item);
+ }
+ }
+
+ if (lite->type == cJSON_Array) {
+ lite_cjson_add_item_to_object(array, data->identifier, array_item);
+ lite_cjson_add_item_to_array(lite, array);
+ } else {
+ lite_cjson_add_item_to_object(lite, data->identifier, array_item);
+ lite_cjson_delete(array);
+ }
+ }
+ break;
+ default: {
+ lite_cjson_delete(array_item);
+ lite_cjson_delete(array);
+ }
+ break;
+ }
+
+ return res;
+}
+
+static int _dm_shw_struct_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0, index = 0;
+ lite_cjson_item_t *lite_object = NULL, *lite_item = NULL;
+ dm_shw_data_t *current_data = NULL;
+ dm_shw_data_value_complex_t *complex_struct = NULL;
+
+ if (data == NULL || lite == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (lite->type == cJSON_Array) {
+ lite_object = lite_cjson_create_object();
+ if (lite_object == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ }
+
+ lite_item = lite_cjson_create_object();
+ if (lite_item == NULL) {
+ lite_cjson_delete(lite_object);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+
+ complex_struct = data->data_value.value;
+
+ for (index = 0; index < complex_struct->size; index++) {
+ current_data = (dm_shw_data_t *)complex_struct->value + index;
+ _dm_shw_data_insert_json_item(current_data, lite_item);
+ }
+ if (lite->type == cJSON_Array) {
+ if (data->identifier) {
+ lite_cjson_add_item_to_object(lite_object, data->identifier, lite_item);
+ lite_cjson_add_item_to_array(lite, lite_object);
+ } else {
+ lite_cjson_add_item_to_array(lite, lite_item);
+ lite_cjson_delete(lite_object);
+ }
+ } else {
+ if (data->identifier) {
+ lite_cjson_add_item_to_object(lite, data->identifier, lite_item);
+ lite_cjson_delete(lite_object);
+ } else {
+ res = FAIL_RETURN;
+ lite_cjson_delete(lite_item);
+ lite_cjson_delete(lite_object);
+ }
+ }
+
+ return res;
+}
+
+static int _dm_shw_data_insert_json_item(_IN_ dm_shw_data_t *data, _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0;
+ lite_cjson_item_t *data_object = NULL;
+
+ if (data == NULL || lite == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (lite->type == cJSON_Array) {
+ data_object = lite_cjson_create_object();
+ if (data_object == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ }
+
+ switch (data->data_value.type) {
+ case DM_SHW_DATA_TYPE_INT:
+ case DM_SHW_DATA_TYPE_BOOL:
+ case DM_SHW_DATA_TYPE_ENUM: {
+ if (lite->type == cJSON_Array) {
+ res = _dm_shw_int_insert_json_item(data, data_object);
+ if (res == SUCCESS_RETURN) {
+ lite_cjson_add_item_to_array(lite, data_object);
+ }
+ } else {
+ res = _dm_shw_int_insert_json_item(data, lite);
+ lite_cjson_delete(data_object);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ if (lite->type == cJSON_Array) {
+ res = _dm_shw_float_insert_json_item(data, data_object);
+ if (res == SUCCESS_RETURN) {
+ lite_cjson_add_item_to_array(lite, data_object);
+ }
+ } else {
+ res = _dm_shw_float_insert_json_item(data, lite);
+ lite_cjson_delete(data_object);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ if (lite->type == cJSON_Array) {
+ res = _dm_shw_double_insert_json_item(data, data_object);
+ if (res == SUCCESS_RETURN) {
+ lite_cjson_add_item_to_array(lite, data_object);
+ }
+ } else {
+ res = _dm_shw_double_insert_json_item(data, lite);
+ lite_cjson_delete(data_object);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT:
+ case DM_SHW_DATA_TYPE_DATE: {
+ if (lite->type == cJSON_Array) {
+ res = _dm_shw_string_insert_json_item(data, data_object);
+ if (res == SUCCESS_RETURN) {
+ lite_cjson_add_item_to_array(lite, data_object);
+ }
+ } else {
+ res = _dm_shw_string_insert_json_item(data, lite);
+ lite_cjson_delete(data_object);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_ARRAY: {
+ /* dm_log_debug("DM_SHW_DATA_TYPE_ARRAY"); */
+ if (lite->type == cJSON_Array) {
+ res = _dm_shw_array_insert_json_item(data, data_object);
+ if (res == SUCCESS_RETURN) {
+ lite_cjson_add_item_to_array(lite, data_object);
+ }
+ } else {
+ res = _dm_shw_array_insert_json_item(data, lite);
+ lite_cjson_delete(data_object);
+ }
+ }
+ break;
+ case DM_SHW_DATA_TYPE_STRUCT: {
+ /* dm_log_debug("DM_SHW_DATA_TYPE_STRUCT"); */
+ if (lite->type == cJSON_Array) {
+ res = _dm_shw_struct_insert_json_item(data, data_object);
+ if (res == SUCCESS_RETURN) {
+ lite_cjson_add_item_to_array(lite, data_object);
+ }
+ } else {
+ res = _dm_shw_struct_insert_json_item(data, lite);
+ lite_cjson_delete(data_object);
+ }
+ }
+ break;
+ default:
+ lite_cjson_delete(data_object);
+ res = FAIL_RETURN;
+ break;
+ }
+
+ return res;
+}
+
+int dm_shw_assemble_property(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0, index = 0;
+ dm_shw_data_t *property = NULL;
+
+ if (shadow == NULL || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->property_number; index++) {
+ property = shadow->properties + index;
+ if ((strlen(property->identifier) == identifier_len) &&
+ (memcmp(property->identifier, identifier, identifier_len) == 0)) {
+ /* dm_log_debug("Property Found: %.*s",identifier_len,identifier); */
+ break;
+ }
+ }
+
+ if (index == shadow->property_number) {
+ dm_log_debug("Property Not Found: %.*s", identifier_len, identifier);
+ return FAIL_RETURN;
+ }
+
+ res = _dm_shw_data_insert_json_item(property, lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_assemble_event_output(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0, index = 0;
+ dm_shw_data_t *event_outputdata = NULL;
+ dm_shw_event_t *event = NULL;
+
+ if (shadow == NULL || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->event_number; index++) {
+ event = shadow->events + index;
+ if ((strlen(event->identifier) == identifier_len) &&
+ (memcmp(event->identifier, identifier, identifier_len) == 0)) {
+ /* dm_log_debug("Event Found: %.*s",identifier_len,identifier); */
+ break;
+ }
+ }
+
+ if (index == shadow->event_number) {
+ dm_log_debug("Event Not Found: %.*s", identifier_len, identifier);
+ return FAIL_RETURN;
+ }
+
+ for (index = 0; index < event->output_data_number; index++) {
+ event_outputdata = event->output_datas + index;
+
+ res = _dm_shw_data_insert_json_item(event_outputdata, lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_shw_assemble_service_output(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite)
+{
+ int res = 0, index = 0;
+ dm_shw_data_t *service_outputdata = NULL;
+ dm_shw_service_t *service = NULL;
+
+ if (shadow == NULL || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < shadow->service_number; index++) {
+ service = shadow->services + index;
+ if ((strlen(service->identifier) == identifier_len) &&
+ (memcmp(service->identifier, identifier, identifier_len) == 0)) {
+ /* dm_log_debug("Service Found: %.*s",identifier_len,identifier); */
+ break;
+ }
+ }
+
+ if (index == shadow->service_number) {
+ dm_log_debug("Service Not Found: %.*s", identifier_len, identifier);
+ return FAIL_RETURN;
+ }
+
+ for (index = 0; index < service->output_data_number; index++) {
+ service_outputdata = service->output_datas + index;
+
+ res = _dm_shw_data_insert_json_item(service_outputdata, lite);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static void _dm_shw_int_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ /* if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;} */
+}
+
+static void _dm_shw_float_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ /* if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;} */
+}
+
+static void _dm_shw_double_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ /* if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;} */
+}
+
+static void _dm_shw_text_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ if (data_value->value) {
+ DM_free(data_value->value);
+ data_value->value = NULL;
+ }
+}
+
+static void _dm_shw_enum_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ /* if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;} */
+}
+
+static void _dm_shw_date_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ if (data_value->value) {
+ DM_free(data_value->value);
+ data_value->value = NULL;
+ }
+}
+
+static void _dm_shw_bool_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ /* Free Value */
+ /* if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;} */
+}
+
+static void _dm_shw_array_int_free(_IN_ dm_shw_data_value_t *data_value)
+{
+
+}
+
+static void _dm_shw_array_float_free(_IN_ dm_shw_data_value_t *data_value)
+{
+
+}
+
+static void _dm_shw_array_double_free(_IN_ dm_shw_data_value_t *data_value)
+{
+
+}
+
+static void _dm_shw_array_text_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ int index = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ /* Free Value */
+ if (complex_array) {
+ for (index = 0; index < complex_array->size; index++) {
+ if (*((char **)(complex_array->value) + index)) {
+ DM_free(*((char **)(complex_array->value) + index));
+ *((char **)(complex_array->value) + index) = NULL;
+ }
+ }
+ }
+}
+
+static void _dm_shw_array_enum_free(_IN_ dm_shw_data_value_t *data_value)
+{
+
+}
+
+static void _dm_shw_array_date_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ int index = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ /* Free Value */
+ if (complex_array) {
+ for (index = 0; index < complex_array->size; index++) {
+ if (*((char **)(complex_array->value) + index)) {
+ DM_free(*((char **)(complex_array->value) + index));
+ *((char **)(complex_array->value) + index) = NULL;
+ }
+ }
+ }
+}
+
+static void _dm_shw_array_bool_free(_IN_ dm_shw_data_value_t *data_value)
+{
+
+}
+
+static void _dm_shw_array_array_free(_IN_ dm_shw_data_value_t *data_value)
+{
+
+}
+
+static void _dm_shw_array_struct_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ int index = 0;
+ dm_shw_data_t *data = NULL;
+
+ dm_shw_data_value_complex_t *complex_struct = (dm_shw_data_value_complex_t *)data_value->value;
+
+ if (complex_struct) {
+ for (index = 0; index < complex_struct->size; index++) {
+ data = (dm_shw_data_t *)complex_struct->value + index;
+ _dm_shw_property_free(data);
+ }
+ }
+}
+
+static void _dm_shw_array_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ /* Free Value */
+ if (complex_array) {
+ /* dm_log_err("complex_array->type: %d",complex_array->type); */
+ if (g_iotx_data_type_mapping[complex_array->type].func_array_free != NULL) {
+ g_iotx_data_type_mapping[complex_array->type].func_array_free(data_value);
+ }
+ if (complex_array->value) {
+ DM_free(complex_array->value);
+ }
+ DM_free(complex_array);
+ data_value->value = NULL;
+ }
+}
+
+static void _dm_shw_struct_free(_IN_ dm_shw_data_value_t *data_value)
+{
+ int index = 0;
+ dm_shw_data_t *property = NULL;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ /* Free Value */
+ if (complex_array) {
+ for (index = 0; index < complex_array->size; index++) {
+ property = (dm_shw_data_t *)(complex_array->value) + index;
+ _dm_shw_property_free(property);
+ }
+ if (complex_array->value) {
+ DM_free(complex_array->value);
+ }
+ DM_free(complex_array);
+ data_value->value = NULL;
+ }
+}
+
+static void _dm_shw_data_free(dm_shw_data_value_t *data_value)
+{
+ if (g_iotx_data_type_mapping[data_value->type].func_free == NULL) {
+ return;
+ }
+ g_iotx_data_type_mapping[data_value->type].func_free(data_value);
+}
+
+static void _dm_shw_property_free(_IN_ dm_shw_data_t *property)
+{
+ if (property->identifier) {
+ DM_free(property->identifier);
+ }
+ _dm_shw_data_free(&property->data_value);
+}
+
+static void _dm_shw_properties_free(_IN_ dm_shw_data_t *properties, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *property = NULL;
+
+ for (index = 0; index < number; index++) {
+ property = properties + index;
+ _dm_shw_property_free(property);
+ }
+}
+
+static void _dm_shw_event_outputdata_free(_IN_ dm_shw_data_t *outputdata)
+{
+ if (outputdata->identifier) {
+ DM_free(outputdata->identifier);
+ outputdata->identifier = NULL;
+ }
+ _dm_shw_data_free(&outputdata->data_value);
+}
+
+static void _dm_shw_event_outputdatas_free(_IN_ dm_shw_data_t *outputdatas, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *outputdata = NULL;
+
+ for (index = 0; index < number; index++) {
+ outputdata = outputdatas + index;
+ _dm_shw_event_outputdata_free(outputdata);
+ }
+}
+
+static void _dm_shw_event_free(_IN_ dm_shw_event_t *event)
+{
+ if (event->identifier) {
+ DM_free(event->identifier);
+ event->identifier = NULL;
+ }
+ if (event->output_datas) {
+ _dm_shw_event_outputdatas_free(event->output_datas, event->output_data_number);
+ DM_free(event->output_datas);
+ event->output_datas = NULL;
+ }
+}
+
+static void _dm_shw_events_free(_IN_ dm_shw_event_t *events, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_event_t *event = NULL;
+
+ for (index = 0; index < number; index++) {
+ event = events + index;
+ _dm_shw_event_free(event);
+ }
+}
+
+static void _dm_shw_service_outputdata_free(_IN_ dm_shw_data_t *outputdata)
+{
+ if (outputdata->identifier) {
+ DM_free(outputdata->identifier);
+ outputdata->identifier = NULL;
+ }
+ _dm_shw_data_free(&outputdata->data_value);
+}
+
+static void _dm_shw_service_outputdatas_free(_IN_ dm_shw_data_t *outputdatas, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *outputdata = NULL;
+
+ for (index = 0; index < number; index++) {
+ outputdata = outputdatas + index;
+ _dm_shw_service_outputdata_free(outputdata);
+ }
+}
+
+static void _dm_shw_service_inputdata_free(_IN_ dm_shw_data_t *inputdata)
+{
+ if (inputdata->identifier) {
+ DM_free(inputdata->identifier);
+ inputdata->identifier = NULL;
+ }
+ _dm_shw_data_free(&inputdata->data_value);
+}
+
+static void _dm_shw_service_inputdatas_free(_IN_ dm_shw_data_t *inputdatas, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *inputdata = NULL;
+
+ for (index = 0; index < number; index++) {
+ inputdata = inputdatas + index;
+ _dm_shw_service_inputdata_free(inputdata);
+ }
+}
+
+static void _dm_shw_service_free(_IN_ dm_shw_service_t *service)
+{
+ if (service->identifier) {
+ DM_free(service->identifier);
+ service->identifier = NULL;
+ }
+ if (service->output_datas) {
+ _dm_shw_service_outputdatas_free(service->output_datas, service->output_data_number);
+ DM_free(service->output_datas);
+ service->output_datas = NULL;
+ }
+ if (service->input_datas) {
+ _dm_shw_service_inputdatas_free(service->input_datas, service->input_data_number);
+ DM_free(service->input_datas);
+ service->input_datas = NULL;
+ }
+}
+
+static void _dm_shw_services_free(_IN_ dm_shw_service_t *services, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_service_t *service = NULL;
+
+ for (index = 0; index < number; index++) {
+ service = services + index;
+ _dm_shw_service_free(service);
+ }
+}
+
+void dm_shw_destroy(_IN_ dm_shw_t **shadow)
+{
+ if (shadow == NULL || *shadow == NULL) {
+ return;
+ }
+
+ /* Free Properties */
+ if ((*shadow)->properties) {
+ _dm_shw_properties_free((*shadow)->properties, (*shadow)->property_number);
+ DM_free((*shadow)->properties);
+ (*shadow)->properties = NULL;
+ }
+
+ /* Free Events */
+ if ((*shadow)->events) {
+ _dm_shw_events_free((*shadow)->events, (*shadow)->event_number);
+ DM_free((*shadow)->events);
+ (*shadow)->events = NULL;
+ }
+
+ /* Free Services */
+ if ((*shadow)->services) {
+ _dm_shw_services_free((*shadow)->services, (*shadow)->service_number);
+ DM_free((*shadow)->services);
+ (*shadow)->services = NULL;
+ }
+
+ DM_free(*shadow);
+ *shadow = NULL;
+}
+
+#if 0
+static void _dm_shw_int_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %d", data_value->value_int);
+}
+
+static void _dm_shw_float_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %f", data_value->value_float);
+}
+
+static void _dm_shw_double_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %f", data_value->value_double);
+}
+
+static void _dm_shw_text_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %s",
+ ((char *)data_value->value == NULL) ? ("NULL") : ((char *)data_value->value));
+}
+
+static void _dm_shw_enum_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %d", data_value->value_int);
+}
+
+static void _dm_shw_date_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %s",
+ ((char *)data_value->value == NULL) ? ("NULL") : ((char *)data_value->value));
+}
+
+static void _dm_shw_bool_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Value : %d", data_value->value_int);
+}
+
+static void _dm_shw_array_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ int index = 0;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ if (complex_array == NULL) {
+ dm_log_debug("TSL Property Complex Array Not Exist");
+ return;
+ }
+
+ dm_log_debug("TSL Property Size: %d", complex_array->size);
+ dm_log_debug("TSL Property Type: %s", g_iotx_data_type_mapping[complex_array->type].name);
+
+ for (index = 0; index < complex_array->size; index++) {
+ dm_log_debug("TSL Property Array Value Index : %d", index);
+ switch (complex_array->type) {
+ case DM_SHW_DATA_TYPE_INT: {
+ dm_log_debug("TSL Property Value: %d", *((int *)(complex_array->value) + index));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_FLOAT: {
+ dm_log_debug("TSL Property Value: %f", *((float *)(complex_array->value) + index));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_DOUBLE: {
+ dm_log_debug("TSL Property Value: %f", *((double *)(complex_array->value) + index));
+ }
+ break;
+ case DM_SHW_DATA_TYPE_TEXT: {
+ dm_log_debug("TSL Property Value: %s",
+ (*((char **)(complex_array->value) + index) == NULL) ? "NULL" : * ((char **)(data_value->value) + index));
+ }
+ break;
+ default:
+ dm_log_err("Execute Should Not Be Here!");
+ break;
+ }
+ }
+}
+
+static void _dm_shw_struct_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ int index = 0;
+ dm_shw_data_t *property = NULL;
+ dm_shw_data_value_complex_t *complex_array = data_value->value;
+
+ dm_log_debug("TSL Property Struct Size: %d", complex_array->size);
+ if (complex_array->size == 0) {
+ return;
+ }
+
+ for (index = 0; index < complex_array->size; index++) {
+ dm_log_debug("TSL Property Struct Index: %d", index);
+ property = (dm_shw_data_t *)complex_array->value + index;
+ _dm_shw_property_print(property);
+ dm_log_debug("\n");
+ }
+}
+
+static void _dm_shw_data_print(_IN_ dm_shw_data_value_t *data_value)
+{
+ dm_log_debug("TSL Property Type: %s", g_iotx_data_type_mapping[data_value->type].name);
+
+ if (g_iotx_data_type_mapping[data_value->type].func_print == NULL) {
+ return;
+ }
+ g_iotx_data_type_mapping[data_value->type].func_print(data_value);
+}
+
+static void _dm_shw_property_print(_IN_ dm_shw_data_t *property)
+{
+ dm_log_debug("TSL Property Identifier : %s", (property->identifier == NULL) ? ("NULL") : (property->identifier));
+ _dm_shw_data_print(&property->data_value);
+}
+
+static void _dm_shw_properties_print(_IN_ dm_shw_data_t *properties, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *property = NULL;
+
+ if (!properties) {
+ dm_log_debug("TSL Propertie Not Exist");
+ }
+
+ dm_log_debug("TSL Property Number: %d", number);
+ for (index = 0; index < number; index++) {
+ property = properties + index;
+ dm_log_debug("TSL Property Index : %d", index);
+ _dm_shw_property_print(property);
+ dm_log_debug("\n");
+ }
+}
+
+static void _dm_shw_event_outputdata_print(_IN_ dm_shw_data_t *outputdata)
+{
+ dm_log_debug("TSL Event Output Data Identifier : %s",
+ (outputdata->identifier == NULL) ? ("NULL") : (outputdata->identifier));
+ _dm_shw_data_print(&outputdata->data_value);
+}
+
+static void _dm_shw_event_outputdatas_print(_IN_ dm_shw_data_t *outputdatas, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *outputdata = NULL;
+
+ if (!outputdatas) {
+ dm_log_debug("TSL Event Output Data Not Exist");
+ }
+
+ dm_log_debug("TSL Event Output Data Number: %d", number);
+ for (index = 0; index < number; index++) {
+ outputdata = outputdatas + index;
+ dm_log_debug("TSL Event Output Data Index: %d", index);
+ _dm_shw_event_outputdata_print(outputdata);
+ dm_log_debug("\n");
+ }
+}
+
+static void _dm_shw_event_print(_IN_ dm_shw_event_t *event)
+{
+ dm_log_debug("TSL Event Identifier : %s", (event->identifier == NULL) ? ("NULL") : (event->identifier));
+ _dm_shw_event_outputdatas_print(event->output_datas, event->output_data_number);
+}
+
+static void _dm_shw_events_print(_IN_ dm_shw_event_t *events, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_event_t *event = NULL;
+ if (!events) {
+ dm_log_debug("TSL Events: NULL");
+ }
+
+ dm_log_debug("TSL Event Number: %d", number);
+ for (index = 0; index < number; index++) {
+ event = events + index;
+ dm_log_debug("TSL Event Index : %d", index);
+ _dm_shw_event_print(event);
+ dm_log_debug("\n");
+ }
+}
+
+static void _dm_shw_service_outputdata_print(_IN_ dm_shw_data_t *outputdata)
+{
+ dm_log_debug("TSL Service Output Data Identifier : %s",
+ (outputdata->identifier == NULL) ? ("NULL") : (outputdata->identifier));
+ _dm_shw_data_print(&outputdata->data_value);
+}
+
+static void _dm_shw_service_outputdatas_print(_IN_ dm_shw_data_t *outputdatas, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *outputdata = NULL;
+
+ if (!outputdatas) {
+ dm_log_debug("TSL Service Output Data Not Exist");
+ }
+
+ dm_log_debug("TSL Service Output Data Number: %d", number);
+ for (index = 0; index < number; index++) {
+ outputdata = outputdatas + index;
+ dm_log_debug("TSL Service Output Data Index: %d", index);
+ _dm_shw_service_outputdata_print(outputdata);
+ dm_log_debug("\n");
+ }
+}
+
+static void _dm_shw_service_inputdata_get_print(_IN_ dm_shw_data_t *inputdata)
+{
+ dm_log_debug("TSL Service Input Data Identifier : %s",
+ (inputdata->identifier == NULL) ? ("NULL") : (inputdata->identifier));
+}
+
+static void _dm_shw_service_inputdata_print(_IN_ dm_shw_data_t *inputdata)
+{
+ dm_log_debug("TSL Service Input Data Identifier : %s",
+ (inputdata->identifier == NULL) ? ("NULL") : (inputdata->identifier));
+ _dm_shw_data_print(&inputdata->data_value);
+}
+
+static void _dm_shw_service_inputdatas_print(_IN_ dm_shw_service_t *service, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_data_t *inputdata = NULL;
+
+ if (!service->input_datas) {
+ dm_log_debug("TSL Service Output Data Not Exist");
+ }
+
+ dm_log_debug("TSL Service Output Data Number: %d", number);
+ for (index = 0; index < number; index++) {
+ inputdata = service->input_datas + index;
+ dm_log_debug("TSL Service Output Data Index: %d", index);
+ /* There Is A God-Damned Special Case For thing.service.property.get(method)/get(identifier) */
+ if (strcmp(service->identifier, DM_SHW_SPECIAL_SERVICE_GET_IDENTIFIER) == 0) {
+ _dm_shw_service_inputdata_get_print(inputdata);
+ } else {
+ _dm_shw_service_inputdata_print(inputdata);
+ }
+ dm_log_debug("\n");
+ }
+}
+
+static void _dm_shw_service_print(_IN_ dm_shw_service_t *service)
+{
+ dm_log_debug("TSL Service Identifier : %s", (service->identifier == NULL) ? ("NULL") : (service->identifier));
+ _dm_shw_service_outputdatas_print(service->output_datas, service->output_data_number);
+ _dm_shw_service_inputdatas_print(service, service->input_data_number);
+}
+
+static void _dm_shw_services_print(_IN_ dm_shw_service_t *services, _IN_ int number)
+{
+ int index = 0;
+ dm_shw_service_t *service = NULL;
+ if (!services) {
+ dm_log_debug("TSL Serivces: NULL");
+ }
+
+ dm_log_debug("TSL Service Number: %d", number);
+ for (index = 0; index < number; index++) {
+ service = services + index;
+ dm_log_debug("TSL Service Index: %d", index);
+ _dm_shw_service_print(service);
+ dm_log_debug("\n");
+ }
+}
+
+void dm_shw_print(_IN_ dm_shw_t *shadow)
+{
+ dm_log_debug("TSL Profile, Product Key: %s, Device Name: %s", shadow->profile.product_key, shadow->profile.device_name);
+ _dm_shw_properties_print(shadow->properties, shadow->property_number);
+ _dm_shw_events_print(shadow->events, shadow->event_number);
+ _dm_shw_services_print(shadow->services, shadow->service_number);
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_shadow.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_shadow.h
new file mode 100644
index 00000000..3320a8ff
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_shadow.h
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#if defined(DEPRECATED_LINKKIT)
+#ifndef _DM_SHADOW_H_
+#define _DM_SHADOW_H_
+
+#include "iotx_dm_internal.h"
+
+#define DM_SHW_KEY_SCHEMA "schema"
+#define DM_SHW_KEY_LINK "link"
+#define DM_SHW_KEY_PROFILE "profile"
+#define DM_SHW_KEY_PROPERTIES "properties"
+#define DM_SHW_KEY_EVENTS "events"
+#define DM_SHW_KEY_SERVICES "services"
+
+#define DM_SHW_KEY_PROFILE_PK "productKey"
+#define DM_SHW_KEY_PROFILE_DN "deviceName"
+#define DM_SHW_KEY_IDENTIFIER "identifier"
+#define DM_SHW_KEY_NAME "name"
+#define DM_SHW_KEY_DESC "desc"
+#define DM_SHW_KEY_ACCESS_MODE "accessMode"
+#define DM_SHW_KEY_REQUIRED "required"
+#define DM_SHW_KEY_METHOD "method"
+#define DM_SHW_KEY_CALLTYPE "callType"
+#define DM_SHW_KEY_OUTPUTDATA "outputData"
+#define DM_SHW_KEY_INPUTDATA "inputData"
+#define DM_SHW_KEY_DATATYPE "dataType"
+#define DM_SHW_KEY_TYPE "type"
+#define DM_SHW_KEY_SPECS "specs"
+#define DM_SHW_KEY_UNIT "unit"
+#define DM_SHW_KEY_UNITNAME "unitName"
+#define DM_SHW_KEY_MIN "min"
+#define DM_SHW_KEY_MAX "max"
+#define DM_SHW_KEY_LENGTH "length"
+#define DM_SHW_KEY_SIZE "size"
+#define DM_SHW_KEY_ITEM "item"
+
+/* Special Service And Event */
+#define DM_SHW_SPECIAL_SERVICE_SET_IDENTIFIER "set"
+#define DM_SHW_SPECIAL_SERVICE_SET_METHOD "thing.service.property.set"
+#define DM_SHW_SPECIAL_SERVICE_GET_IDENTIFIER "get"
+#define DM_SHW_SPECIAL_SERVICE_GET_METHOD "thing.service.property.get"
+#define DM_SHW_SPECIAL_EVENT_POST_IDENTIFIER "post"
+#define DM_SHW_SPECIAL_EVENT_POST_METHOD "thing.event.property.post"
+
+#define DM_SHW_KEY_DELIMITER '.'
+
+typedef enum {
+ DM_SHW_DATA_TYPE_NONE, /* none */
+ DM_SHW_DATA_TYPE_INT, /* int */
+ DM_SHW_DATA_TYPE_FLOAT, /* float */
+ DM_SHW_DATA_TYPE_DOUBLE, /* double */
+ DM_SHW_DATA_TYPE_TEXT, /* string */
+ DM_SHW_DATA_TYPE_ENUM, /* int */
+ DM_SHW_DATA_TYPE_DATE, /* string */
+ DM_SHW_DATA_TYPE_BOOL, /* bool,0 or 1 */
+ DM_SHW_DATA_TYPE_ARRAY, /* support int, float, double, text */
+ DM_SHW_DATA_TYPE_STRUCT, /* support above 8 data types */
+} dm_shw_data_type_e;
+
+typedef enum {
+ DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA,
+ DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA
+} dm_shw_data_target_e;
+
+typedef struct {
+ dm_shw_data_type_e type;
+ int size;
+ void *value;
+} dm_shw_data_value_complex_t;
+
+typedef struct {
+ dm_shw_data_type_e type;
+ union {
+ int value_int;
+ float value_float;
+ double value_double;
+ void *value; /* string or complex type accroding to data type */
+ };
+} dm_shw_data_value_t;
+
+typedef struct {
+ dm_shw_data_type_e type;
+ int specs_number; /* used when type is enum and struct */
+ void *specs; /* nerver be used by struct */
+} dm_shw_data_type_t;
+
+typedef struct {
+ char *identifier;
+ dm_shw_data_value_t data_value;
+} dm_shw_data_t;
+
+typedef struct {
+ char *identifier;
+ int input_data_number; /* input_data Number */
+ dm_shw_data_t *input_datas; /* input_data array, type is dm_shw_data_t */
+ int output_data_number; /* ouput_data Number */
+ dm_shw_data_t *output_datas; /* output_data array, type is dm_shw_data_t */
+} dm_shw_event_t;
+
+typedef struct {
+ char *identifier; /* synchronized or asynchronized */
+ int input_data_number; /* input_data_number */
+ dm_shw_data_t *input_datas; /* input_data array, type is dm_shw_data_t */
+ int output_data_number; /* ouput_data Number */
+ dm_shw_data_t *output_datas; /* output_data array, type is dm_shw_data_t */
+} dm_shw_service_t;
+
+typedef struct {
+ int property_number;
+ dm_shw_data_t *properties; /* property array, type is dm_shw_data_t */
+ int event_number;
+ dm_shw_event_t *events; /* event array, type is dm_shw_event_t */
+ int service_number;
+ dm_shw_service_t *services; /* service array, type is dm_shw_service_t */
+} dm_shw_t;
+
+/**
+ * @brief Create TSL struct from TSL string.
+ * This function used to parse TSL string into TSL struct.
+ *
+ * @param tsl. The TSL string in JSON format.
+ * @param tsl_len. The length of tsl
+ * @param shadow. The pointer of TSL Struct pointer, will be malloc memory.
+ * This memory should be free by dm_shw_destroy.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_create(_IN_ iotx_dm_tsl_type_t type, _IN_ const char *tsl, _IN_ int tsl_len, _OU_ dm_shw_t **shadow);
+
+/**
+ * @brief Get property from TSL struct.
+ * This function used to get property from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: property_id
+ * array type: property_id(array)[index]
+ * struct type: property_id(struct).property_id or property_id(struct).property_id[index]
+ *
+ * @param key_len. The length of key.
+ * @param property. The property in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_property_data(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+
+int dm_shw_get_service_input_output_data(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
+ _IN_ int key_len, _OU_ void **data);
+
+/**
+ * @brief Get event output data from TSL struct.
+ * This function used to get event output data from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: property_id
+ * array type: property_id(array)[index]
+ * struct type: property_id(struct).property_id or property_id(struct).property_id[index]
+ *
+ * @param key_len. The length of key.
+ * @param property. The property in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event_output_data(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
+
+/**
+ * @brief Get property type from TSL struct.
+ * This function used to get property type from TSL struct.
+ *
+ * @param property. The handle of property.
+ * @param type. The data type of property
+ *
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_data_type(_IN_ void *data, _OU_ dm_shw_data_type_e *type);
+
+/**
+ * @brief Get event from TSL struct.
+ * This function used to get property from TSL struct.
+ *
+ * @param service. The handle of event.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: event_id
+ *
+ * @param key_len. The length of key.
+ * @param property. The event in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **event);
+
+/**
+ * @brief Get service from TSL struct.
+ * This function used to get property from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: service_id
+ *
+ * @param key_len. The length of key.
+ * @param property. The service in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_service(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **service);
+
+/**
+ * @brief Get property number from TSL struct.
+ * This function used to get property number from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param number. The property number in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_property_number(_IN_ dm_shw_t *shadow, _OU_ int *number);
+
+/**
+ * @brief Get service number from TSL struct.
+ * This function used to get property number from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param number. The service number in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_service_number(_IN_ dm_shw_t *shadow, _OU_ int *number);
+
+/**
+ * @brief Get event number from TSL struct.
+ * This function used to get property number from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param number. The event number in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event_number(_IN_ dm_shw_t *shadow, _OU_ int *number);
+
+/**
+ * @brief Get property reference from TSL struct by index.
+ * This function used to get property reference from TSL struct by index.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param index. The index of property
+ * @param property. The property reference in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_property_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **property);
+
+/**
+ * @brief Get service reference from TSL struct by index.
+ * This function used to get service reference from TSL struct by index.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param index. The index of service
+ * @param service. The service reference in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_service_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **service);
+
+/**
+ * @brief Get event reference from TSL struct by index.
+ * This function used to get event reference from TSL struct by index.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param index. The index of event
+ * @param event. The event reference in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **event);
+
+/**
+ * @brief Get service reference from TSL struct by identifier.
+ * This function used to get service reference from TSL struct by identifier.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param identifier. The identifier of event
+ * @param service. The service reference in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_service_by_identifier(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _OU_ void **service);
+
+/**
+ * @brief Get event reference from TSL struct by identifier.
+ * This function used to get event reference from TSL struct by identifier.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ * @param identifier. The identifier of event
+ * @param event. The event reference in TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event_by_identifier(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _OU_ void **event);
+
+/**
+ * @brief Get property identifier from TSL struct by service handle.
+ * This function used to get property identifier from TSL struct by service handle.
+ *
+ * @param service. The handle of property.
+ * @param method. The reference to property identifier in TSL Struct
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_property_identifier(_IN_ void *property, _OU_ char **identifier);
+
+/**
+ * @brief Get service method from TSL struct by service handle.
+ * This function used to get service method from TSL struct by service handle.
+ *
+ * @param service. The handle of service.
+ * @param method. Generate method from service identifier
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_service_method(_IN_ void *service, _OU_ char **method);
+
+/**
+ * @brief Get event method from TSL struct by event handle.
+ * This function used to get event method from TSL struct by event handle.
+ *
+ * @param service. The handle of event.
+ * @param method. Generate method from event identifier
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event_method(_IN_ void *event, _OU_ char **method);
+
+/**
+ * @brief Set Property Value Into TSL Struct.
+ * This function used to set property value into TSL Struct.
+ *
+ * @param tsl. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: property_id
+ * array type: property_id(array)[index]
+ * struct type: property_id(struct).property_id or property_id(struct).property_id[index]
+ *
+ * @param key_len. The length of key
+ * @param value. The value to be set, data type decided by data type of property as follows:
+ * int: int*, float: float*, double: double*,
+ * text: char*, enum: int*, date: char*, bool: int*
+ * attention! value can be NULL to clear property value
+ * @param value_len. The length of value, only be used when type is text or data
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_set_property_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+
+/**
+ * @brief Get Property Value From TSL Struct.
+ * This function used to get property value from TSL Struct.
+ *
+ * @param tsl. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: property_id
+ * array type: property_id(array)[index]
+ * struct type: property_id(struct).property_id or property_id(struct).property_id[index]
+ *
+ * @param key_len. The length of key
+ * @param value. The variable to store value, data type decided by data type of property as follows:
+ * int: int*, float: float*, double: double*,
+ * text: char**, enum: int*, date: char**, bool: int*
+ * attention! value can not be NULL
+ *
+ * @warning if data type is text or date, *value well be end with '\0'.
+ * the memory allocated to *value must be free by user.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_property_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void *value);
+
+/**
+ * @brief Set event output value into TSL struct.
+ * This function used to set event output value into TSL struct.
+ *
+ * @param tsl. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: event_id.event_data_id
+ * array type: event_id.event_data_id(array)[index]
+ * struct type: event_id.event_data_id(struct).property_id
+ * or event_id.event_data_id(struct).property_id[index]
+ *
+ * @param key_len. The length of key
+ * @param value. The value to be set, data type decided by data type of property as follows:
+ * int: int*, float: float*, double: double*,
+ * text: char*, enum: int*, date: char*, bool: int*
+ * attention! value can be NULL to clear property value
+ * @param value_len. The length of value, only be used when type is text or data
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_set_event_output_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+
+/**
+ * @brief Get event output value from TSL struct.
+ * This function used to get event output value from TSL struct.
+ *
+ * @param tsl. The pointer of TSL Struct.
+ * @param key. The property compound string, format decided by data type of property as follows:
+ * int,float,double,text,enum,date,bool type: event_id.event_data_id
+ * array type: event_id.event_data_id(array)[index]
+ * struct type: event_id.event_data_id(struct).property_id
+ * or event_id.event_data_id(struct).property_id[index]
+ *
+ * @param key_len. The length of key
+ * @param value. The variable to store value, data type decided by data type of property as follows:
+ * int: int*, float: float*, double: double*,
+ * text: char**, enum: int*, date: char**, bool: int*
+ * attention! value can not be NULL
+ *
+ * @warning if data type is text or date, *value well be end with '\0'.
+ * the memory allocated to *value must be free by user.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_get_event_output_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+
+int dm_shw_set_service_input_output_value(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
+ _IN_ int key_len, _IN_ void *value, _IN_ int value_len);
+int dm_shw_get_service_input_output_value(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
+ _IN_ int key_len, _IN_ void *value);
+
+/**
+ * @brief Get property payload from TSL struct.
+ * This function used to get property payload from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct
+ * @param identifier. The Property Identifier
+ * @param identifier_len. The Property Identifier Length
+ * @param lite. The pointer to json array where to store property value
+ *
+ * @warning The payload malloc by this function and need to be free manully.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_assemble_property(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite);
+
+/**
+ * @brief Get event output payload from TSL struct.
+ * This function used to get event output payload from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct
+ * @param identifier. The Event Identifier
+ * @param identifier_len. The Event Identifier Length
+ * @param lite. The pointer to json array where to store event output value
+ *
+ * @warning The payload malloc by this function and need to be free manully.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_assemble_event_output(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite);
+
+/**
+ * @brief Get service output payload from TSL struct.
+ * This function used to get service output payload from TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct
+ * @param identifier. The Service Identifier
+ * @param identifier_len. The Service Identifier Length
+ * @param lite. The pointer to json array where to store service output value
+ *
+ * @warning The payload malloc by this function and need to be free manully.
+ *
+ * @return success or fail.
+ *
+ */
+int dm_shw_assemble_service_output(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
+ _IN_ lite_cjson_item_t *lite);
+
+/**
+ * @brief Free TSL struct.
+ * This function used to free TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+void dm_shw_destroy(_IN_ dm_shw_t **shadow);
+
+#if 0
+ /**
+ * @brief Print detailed information of TSL struct.
+ * This function used to print detailed information of TSL struct.
+ *
+ * @param shadow. The pointer of TSL Struct.
+ *
+ * @return success or fail.
+ *
+ */
+ void dm_shw_print(_IN_ dm_shw_t *shadow);
+#endif
+
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_tsl_alink.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_tsl_alink.c
new file mode 100644
index 00000000..cf306b85
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_tsl_alink.c
@@ -0,0 +1,1023 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_dm_internal.h"
+
+#ifdef DEPRECATED_LINKKIT
+
+typedef int (*dm_shw_data_parse)(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+typedef int (*dm_shw_array_parse)(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+
+typedef struct {
+ dm_shw_data_type_e type;
+ const char *name;
+ dm_shw_data_parse func_parse;
+ dm_shw_array_parse func_array_parse;
+} dm_tsl_alink_mapping_t;
+
+/* Data Parse */
+static int _dm_shw_int_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_float_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_double_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_text_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_enum_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_date_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_bool_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_struct_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_property_parse(_IN_ dm_shw_data_t *property, _IN_ lite_cjson_t *root);
+
+/* Array Data Parse */
+static int _dm_shw_array_int_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_float_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_double_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_text_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_enum_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_date_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_bool_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_array_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+static int _dm_shw_array_struct_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root);
+
+static dm_tsl_alink_mapping_t g_dm_tsl_alink_mapping[] = {
+ {DM_SHW_DATA_TYPE_NONE, "none", NULL, NULL },
+ {DM_SHW_DATA_TYPE_INT, "int", _dm_shw_int_parse, _dm_shw_array_int_parse },
+ {DM_SHW_DATA_TYPE_FLOAT, "float", _dm_shw_float_parse, _dm_shw_array_float_parse },
+ {DM_SHW_DATA_TYPE_DOUBLE, "double", _dm_shw_double_parse, _dm_shw_array_double_parse },
+ {DM_SHW_DATA_TYPE_TEXT, "text", _dm_shw_text_parse, _dm_shw_array_text_parse },
+ {DM_SHW_DATA_TYPE_ENUM, "enum", _dm_shw_enum_parse, _dm_shw_array_enum_parse },
+ {DM_SHW_DATA_TYPE_DATE, "date", _dm_shw_date_parse, _dm_shw_array_date_parse },
+ {DM_SHW_DATA_TYPE_BOOL, "bool", _dm_shw_bool_parse, _dm_shw_array_bool_parse },
+ {DM_SHW_DATA_TYPE_ARRAY, "array", _dm_shw_array_parse, _dm_shw_array_array_parse },
+ {DM_SHW_DATA_TYPE_STRUCT, "struct", _dm_shw_struct_parse, _dm_shw_array_struct_parse }
+};
+
+static int _dm_shw_get_type(_IN_ const char *name, _IN_ int name_len, _OU_ dm_shw_data_type_e *type)
+{
+ int index = 0;
+
+ if (name == NULL || name_len <= 0 || type == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < sizeof(g_dm_tsl_alink_mapping) / sizeof(dm_tsl_alink_mapping_t); index++) {
+ if (strlen(g_dm_tsl_alink_mapping[index].name) == name_len &&
+ memcmp(g_dm_tsl_alink_mapping[index].name, name, name_len) == 0) {
+ *type = g_dm_tsl_alink_mapping[index].type;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _dm_shw_int_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_float_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_double_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_text_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_enum_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_date_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_bool_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_int_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(int)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(int)));
+
+ /* Just For Test */
+#ifdef IOTX_DM_TSL_DEVELOP_TEST
+ int index = 0;
+ for (index = 0; index < complex_array->size; index++) {
+ *((int *)(complex_array->value) + index) = index + 1;
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_float_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(float)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(float)));
+
+ /* Just For Test */
+#ifdef IOTX_DM_TSL_DEVELOP_TEST
+ int index = 0;
+ for (index = 0; index < complex_array->size; index++) {
+ *((float *)(complex_array->value) + index) = (float)index + 0.2;
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_double_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(double)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(double)));
+
+ /* Just For Test */
+#ifdef IOTX_DM_TSL_DEVELOP_TEST
+ int index = 0;
+ for (index = 0; index < complex_array->size; index++) {
+ *((double *)(complex_array->value) + index) = (double)index + 0.2;
+ }
+#endif
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_text_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(char *)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(char *)));
+
+#ifdef IOTX_DM_TSL_DEVELOP_TEST
+ int index = 0;
+ char temp[10] = {0};
+ for (index = 0; index < complex_array->size; index++) {
+ memset(temp, 0, sizeof(temp));
+ HAL_Snprintf(temp, sizeof(temp), "%d", index + 1);
+ *((char **)(complex_array->value) + index) = DM_malloc(strlen(temp) + 1);
+ if (*((char **)(complex_array->value) + index) != NULL) {
+ memset(*((char **)(complex_array->value) + index), 0, strlen(temp) + 1);
+ memcpy(*((char **)(complex_array->value) + index), temp, strlen(temp));
+ }
+ }
+#endif
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_enum_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(int)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(int)));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_date_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(char *)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(char *)));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_bool_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(int)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(int)));
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_array_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+#if 0
+ int res = 0;
+ char size_str[DM_UTILS_UINT32_STRLEN] = {0};
+ lite_cjson_t lite_item, lite_type, lite_specs;
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+ dm_shw_data_value_t *data_value_next_level;
+ dm_shw_data_value_complex_t *complex_array_next_level = NULL;
+
+ if (!lite_cjson_is_object(root)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Allocate Memory For Next Level Data Value And Next Level Complex Array */
+ data_value_next_level = DM_malloc(sizeof(dm_shw_data_value_t));
+ if (data_value_next_level == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(data_value_next_level, 0, sizeof(dm_shw_data_value_t));
+ data_value_next_level->type = DM_SHW_DATA_TYPE_ARRAY;
+
+ complex_array_next_level = DM_malloc(sizeof(dm_shw_data_value_complex_t));
+ if (complex_array_next_level == NULL) {
+ DM_free(data_value_next_level);
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array_next_level, 0, sizeof(dm_shw_data_value_complex_t));
+ complex_array->value = (void *)data_value_next_level;
+ data_value_next_level->value = complex_array_next_level;
+
+ /* Parse Size (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_SIZE, strlen(DM_SHW_KEY_SIZE), &lite_item);
+ if (res != SUCCESS_RETURN && !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ if (lite_item.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(size_str, lite_item.value, lite_item.value_length);
+ complex_array_next_level->size = atoi(size_str);
+
+ dm_log_debug("TSL Property Array Array Size: %d", complex_array_next_level->size);
+
+ /* Parse Item And Type (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_ITEM, strlen(DM_SHW_KEY_ITEM), &lite_item);
+ if (res != SUCCESS_RETURN && !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ memset(&lite_type, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite_item, DM_SHW_KEY_TYPE, strlen(DM_SHW_KEY_TYPE), &lite_type);
+ if (res != SUCCESS_RETURN && !lite_cjson_is_string(&lite_type)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = _dm_shw_get_type(lite_type.value, lite_type.value_length, &complex_array_next_level->type);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Parse Specs (Optional) */
+ memset(&lite_specs, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite_item, DM_SHW_KEY_SPECS, strlen(DM_SHW_KEY_SPECS), &lite_specs);
+ if ((complex_array_next_level->type == DM_SHW_DATA_TYPE_ARRAY
+ || complex_array_next_level->type == DM_SHW_DATA_TYPE_STRUCT) &&
+ (res != SUCCESS_RETURN)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ if (g_dm_tsl_alink_mapping[complex_array_next_level->type].func_array_parse == NULL) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("TSL Property Specs Type: %s", g_dm_tsl_alink_mapping[complex_array_next_level->type].name);
+
+ /* Parse Array Type */
+ res = g_dm_tsl_alink_mapping[complex_array->type].func_array_parse(data_value_next_level, &lite_specs);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+#endif
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_struct_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ dm_shw_data_value_complex_t *complex_array = (dm_shw_data_value_complex_t *)data_value->value;
+ dm_shw_data_t *data = NULL;
+
+ if (!lite_cjson_is_array(root) || root->size <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ dm_log_debug("Array Struct Size: %d", complex_array->size);
+ complex_array->value = DM_malloc((complex_array->size) * (sizeof(dm_shw_data_t)));
+ if (complex_array->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array->value, 0, (complex_array->size) * (sizeof(dm_shw_data_t)));
+
+ dm_log_debug("Array Struct Spec Size: %d", root->size);
+ for (index = 0; index < complex_array->size; index++) {
+ data = (dm_shw_data_t *)complex_array->value + index;
+
+ data->data_value.type = DM_SHW_DATA_TYPE_STRUCT;
+
+ res = _dm_shw_struct_parse(&data->data_value, root);
+ if (res != SUCCESS_RETURN) {
+ continue;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_array_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ char size_str[DM_UTILS_UINT32_STRLEN] = {0};
+ lite_cjson_t lite_item, lite_type, lite_specs;
+ dm_shw_data_value_complex_t *complex_array = NULL;
+
+ /* dm_log_debug("DM_SHW_DATA_TYPE_ARRAY"); */
+
+ if (root == NULL || !lite_cjson_is_object(root)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Allocate Memory For Data Type Specs */
+ complex_array = DM_malloc(sizeof(dm_shw_data_value_complex_t));
+ if (complex_array == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_array, 0, sizeof(dm_shw_data_value_complex_t));
+ data_value->value = (void *)complex_array;
+
+ /* Parse Size (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_SIZE, strlen(DM_SHW_KEY_SIZE), &lite_item);
+ if (res != SUCCESS_RETURN && !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ if (lite_item.value_length > DM_UTILS_UINT32_STRLEN) {
+ return FAIL_RETURN;
+ }
+ memcpy(size_str, lite_item.value, lite_item.value_length);
+ complex_array->size = atoi(size_str);
+
+ /* dm_log_debug("TSL Property Array Size: %d",complex_array->size); */
+
+ /* Parse Item And Type (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_ITEM, strlen(DM_SHW_KEY_ITEM), &lite_item);
+ if (res != SUCCESS_RETURN && !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ memset(&lite_type, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite_item, DM_SHW_KEY_TYPE, strlen(DM_SHW_KEY_TYPE), &lite_type);
+ if (res != SUCCESS_RETURN && !lite_cjson_is_string(&lite_type)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = _dm_shw_get_type(lite_type.value, lite_type.value_length, &complex_array->type);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ /* dm_log_debug("TSL Property Array Type: %d",complex_array->type); */
+
+ /* Parse Specs (Optional) */
+ memset(&lite_specs, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite_item, DM_SHW_KEY_SPECS, strlen(DM_SHW_KEY_SPECS), &lite_specs);
+ if ((complex_array->type == DM_SHW_DATA_TYPE_ARRAY || complex_array->type == DM_SHW_DATA_TYPE_STRUCT) &&
+ (res != SUCCESS_RETURN)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ if (g_dm_tsl_alink_mapping[complex_array->type].func_array_parse == NULL) {
+ return FAIL_RETURN;
+ }
+ /* dm_log_debug("TSL Property Specs Type: %s",g_dm_tsl_alink_mapping[complex_array->type].name); */
+
+ /* Parse Array Type */
+ res = g_dm_tsl_alink_mapping[complex_array->type].func_array_parse(data_value, &lite_specs);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_struct_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_item;
+ dm_shw_data_t *property = NULL;
+ dm_shw_data_value_complex_t *complex_struct = NULL;
+
+ /* dm_log_debug("DM_SHW_DATA_TYPE_STRUCT"); */
+
+ if (root == NULL || !lite_cjson_is_array(root) || root->size == 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* dm_log_debug("TSL Property Struct Size: %d",root->size); */
+
+ /* Allocate Memory For Data Type Specs */
+ complex_struct = DM_malloc(sizeof(dm_shw_data_value_complex_t));
+ if (complex_struct == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_struct, 0, sizeof(dm_shw_data_value_complex_t));
+ data_value->value = (void *)complex_struct;
+
+ complex_struct->size = root->size;
+
+ /* Allocate Memory For Multi Identifier */
+ complex_struct->value = DM_malloc((complex_struct->size) * (sizeof(dm_shw_data_t)));
+ if (complex_struct->value == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(complex_struct->value, 0, (complex_struct->size) * (sizeof(dm_shw_data_t)));
+
+ for (index = 0; index < complex_struct->size; index++) {
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ property = (dm_shw_data_t *)complex_struct->value + index;
+ /* dm_log_debug("TSL Property Struct Index: %d",index); */
+
+ res = lite_cjson_array_item(root, index, &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_debug("TSL Property Struct Property: %.*s",lite_item.value_length,lite_item.value); */
+ res = _dm_shw_property_parse(property, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_data_parse(_IN_ dm_shw_data_value_t *data_value, _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ memset(data_value, 0, sizeof(dm_shw_data_value_t));
+
+ /* Parse Type */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_TYPE, strlen(DM_SHW_KEY_TYPE), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ dm_log_debug("TSL Data Type: %.*s", lite_item.value_length, lite_item.value);
+ res = _dm_shw_get_type(lite_item.value, lite_item.value_length, &data_value->type);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Parse Specs */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_SPECS, strlen(DM_SHW_KEY_SPECS), &lite_item);
+ if (res == SUCCESS_RETURN) {
+ /* dm_log_debug("TSL Data Specs: %.*s",lite_item.value_length,lite_item.value); */
+ }
+
+ /* Parse Type And Value */
+ if (g_dm_tsl_alink_mapping[data_value->type].func_parse == NULL) {
+ return FAIL_RETURN;
+ }
+ res = g_dm_tsl_alink_mapping[data_value->type].func_parse(data_value, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_property_parse(_IN_ dm_shw_data_t *property, _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ /* Parse Identifier (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_IDENTIFIER, strlen(DM_SHW_KEY_IDENTIFIER), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = dm_utils_copy(lite_item.value, lite_item.value_length, (void **)(&property->identifier),
+ lite_item.value_length + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier: %s", property->identifier);
+
+ /* Parse DataType */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_DATATYPE, strlen(DM_SHW_KEY_DATATYPE), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_debug("TSL Property Data Type: %.*s",lite_item.value_length,lite_item.value); */
+ res = _dm_shw_data_parse(&property->data_value, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_properties_parse(_IN_ dm_shw_t *shadow, _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_properties, lite_property;
+
+ memset(&lite_properties, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_PROPERTIES, strlen(DM_SHW_KEY_PROPERTIES), &lite_properties);
+ if (res == SUCCESS_RETURN) {
+ if (!lite_cjson_is_array(&lite_properties)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ } else {
+ return SUCCESS_RETURN;
+ }
+
+ dm_log_debug("Number: %d", lite_properties.size);
+ if (lite_properties.size == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ /* Allocate Memory For TSL Properties Struct */
+ shadow->property_number = lite_properties.size;
+ shadow->properties = DM_malloc(sizeof(dm_shw_data_t) * (lite_properties.size));
+ if (shadow->properties == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(shadow->properties, 0, sizeof(dm_shw_data_t) * (lite_properties.size));
+
+ for (index = 0; index < lite_properties.size; index++) {
+ memset(&lite_property, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_array_item(&lite_properties, index, &lite_property);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_property)) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Index: %d", index);
+ _dm_shw_property_parse(shadow->properties + index, &lite_property);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_event_outputdata_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_data_t *event_data,
+ _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ /* Parse Identifier (Madantory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_IDENTIFIER, strlen(DM_SHW_KEY_IDENTIFIER), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = dm_utils_copy(lite_item.value, lite_item.value_length, (void **) & (event_data->identifier),
+ lite_item.value_length + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier: %s", event_data->identifier);
+
+ /* Parse DataType */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_DATATYPE, strlen(DM_SHW_KEY_DATATYPE), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_debug("TSL Output Event Data Type: %.*s",lite_item.value_length,lite_item.value); */
+ res = _dm_shw_data_parse(&event_data->data_value, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_event_outputdatas_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_event_t *event, _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_item;
+ dm_shw_data_t *output_data = NULL;
+
+ dm_log_debug("Number: %d", event->output_data_number);
+ if (event->output_data_number == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ /* Allocate Memory For Output Datas */
+ event->output_datas = DM_malloc((event->output_data_number) * (sizeof(dm_shw_data_t)));
+ if (event->output_datas == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(event->output_datas, 0, (event->output_data_number) * (sizeof(dm_shw_data_t)));
+
+ for (index = 0; index < event->output_data_number; index++) {
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ output_data = event->output_datas + index;
+
+ res = lite_cjson_array_item(root, index, &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Index: %d", index);
+ _dm_shw_event_outputdata_parse(shadow, output_data, &lite_item);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_event_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_event_t *event, _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ /* Parse Identifier (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_IDENTIFIER, strlen(DM_SHW_KEY_IDENTIFIER), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = dm_utils_copy(lite_item.value, lite_item.value_length, (void **)(&event->identifier), lite_item.value_length + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier: %s", event->identifier);
+
+ /* Check If Current Event Id Is Post */
+ if (((strlen(event->identifier) == strlen(DM_SHW_SPECIAL_EVENT_POST_IDENTIFIER)) &&
+ (memcmp(event->identifier, DM_SHW_SPECIAL_EVENT_POST_IDENTIFIER, strlen(DM_SHW_SPECIAL_EVENT_POST_IDENTIFIER)) == 0))) {
+ /* dm_log_info("TSL Special Event Identifier: %s, Ignore It",event->identifier); */
+ return SUCCESS_RETURN;
+ }
+
+ /* Parse Output Data (Madantory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_OUTPUTDATA, strlen(DM_SHW_KEY_OUTPUTDATA), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_array(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ event->output_data_number = lite_item.size;
+ res = _dm_shw_event_outputdatas_parse(shadow, event, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_events_parse(_IN_ dm_shw_t *shadow, _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_events, lite_event;
+
+ memset(&lite_events, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_EVENTS, strlen(DM_SHW_KEY_EVENTS), &lite_events);
+ if (res == SUCCESS_RETURN) {
+ if (!lite_cjson_is_array(&lite_events)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ } else {
+ return SUCCESS_RETURN;
+ }
+
+ dm_log_debug("Number: %d", lite_events.size);
+ if (lite_events.size == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ /* Allocate Memory For TSL Events Struct */
+ shadow->event_number = lite_events.size;
+ shadow->events = DM_malloc(sizeof(dm_shw_event_t) * (lite_events.size));
+ if (shadow->events == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(shadow->events, 0, sizeof(dm_shw_event_t) * (lite_events.size));
+
+ for (index = 0; index < lite_events.size; index++) {
+ memset(&lite_event, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_array_item(&lite_events, index, &lite_event);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_event)) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Index: %d", index);
+ _dm_shw_event_parse(shadow, shadow->events + index, &lite_event);
+ }
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_service_outputdata_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_data_t *service_data,
+ _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ /* Parse Identifier (Madantory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_IDENTIFIER, strlen(DM_SHW_KEY_IDENTIFIER), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = dm_utils_copy(lite_item.value, lite_item.value_length, (void **) & (service_data->identifier),
+ lite_item.value_length + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier: %s", service_data->identifier);
+
+ /* Parse DataType */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_DATATYPE, strlen(DM_SHW_KEY_DATATYPE), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_debug("TSL Output Service Data Type: %.*s",lite_item.value_length,lite_item.value); */
+ res = _dm_shw_data_parse(&service_data->data_value, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_service_outputdatas_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_service_t *service,
+ _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_item;
+ dm_shw_data_t *output_data = NULL;
+
+ dm_log_debug("Number: %d", service->output_data_number);
+ if (service->output_data_number == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ /* Allocate Memory For Output Datas */
+ service->output_datas = DM_malloc((service->output_data_number) * (sizeof(dm_shw_data_t)));
+ if (service->output_datas == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(service->output_datas, 0, (service->output_data_number) * (sizeof(dm_shw_data_t)));
+
+ for (index = 0; index < service->output_data_number; index++) {
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ output_data = service->output_datas + index;
+
+ res = lite_cjson_array_item(root, index, &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Index: %d", index);
+ _dm_shw_service_outputdata_parse(shadow, output_data, &lite_item);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_service_inputdata_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_data_t *input_data,
+ _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ if (!lite_cjson_is_object(root)) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ /* Parse Identifier (Madantory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_IDENTIFIER, strlen(DM_SHW_KEY_IDENTIFIER), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = dm_utils_copy(lite_item.value, lite_item.value_length, (void **) & (input_data->identifier),
+ lite_item.value_length + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier: %s", input_data->identifier);
+
+ /* Parse DataType */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_DATATYPE, strlen(DM_SHW_KEY_DATATYPE), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ /* dm_log_debug("TSL Input Service Data Type: %.*s",lite_item.value_length,lite_item.value); */
+ res = _dm_shw_data_parse(&input_data->data_value, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_service_inputdatas_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_service_t *service,
+ _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_item;
+ dm_shw_data_t *input_data = NULL;
+
+ dm_log_debug("Number: %d", service->input_data_number);
+ if (service->input_data_number == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ /* Allocate Memory For Output Datas */
+ service->input_datas = DM_malloc((service->input_data_number) * (sizeof(dm_shw_data_t)));
+ if (service->input_datas == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(service->input_datas, 0, (service->input_data_number) * (sizeof(dm_shw_data_t)));
+
+ for (index = 0; index < service->input_data_number; index++) {
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ input_data = service->input_datas + index;
+
+ res = lite_cjson_array_item(root, index, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Index: %d", index);
+ _dm_shw_service_inputdata_parse(shadow, input_data, &lite_item);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_service_parse(_IN_ dm_shw_t *shadow, _IN_ dm_shw_service_t *service, _IN_ lite_cjson_t *root)
+{
+ int res = 0;
+ lite_cjson_t lite_item;
+
+ /* Parse Identifier (Mandatory) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_IDENTIFIER, strlen(DM_SHW_KEY_IDENTIFIER), &lite_item);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ res = dm_utils_copy(lite_item.value, lite_item.value_length, (void **)(&service->identifier),
+ lite_item.value_length + 1);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ dm_log_debug("Identifier: %s", service->identifier);
+
+ /* Check If Current Service Id Is Set Or Get */
+ if (((strlen(service->identifier) == strlen(DM_SHW_SPECIAL_SERVICE_SET_IDENTIFIER)) &&
+ (memcmp(service->identifier, DM_SHW_SPECIAL_SERVICE_SET_IDENTIFIER,
+ strlen(DM_SHW_SPECIAL_SERVICE_SET_IDENTIFIER)) == 0)) ||
+ ((strlen(service->identifier) == strlen(DM_SHW_SPECIAL_SERVICE_GET_IDENTIFIER)) &&
+ (memcmp(service->identifier, DM_SHW_SPECIAL_SERVICE_GET_IDENTIFIER,
+ strlen(DM_SHW_SPECIAL_SERVICE_GET_IDENTIFIER)) == 0))) {
+ /* dm_log_info("TSL Special Service Identifier: %s, Ignore It",service->identifier); */
+ return SUCCESS_RETURN;
+ }
+
+ /* Parse Output Data (Optional) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_OUTPUTDATA, strlen(DM_SHW_KEY_OUTPUTDATA), &lite_item);
+ if (res == SUCCESS_RETURN && lite_cjson_is_array(&lite_item)) {
+ service->output_data_number = lite_item.size;
+ res = _dm_shw_service_outputdatas_parse(shadow, service, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+
+ /* Parse Input Data (Optional) */
+ memset(&lite_item, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_INPUTDATA, strlen(DM_SHW_KEY_INPUTDATA), &lite_item);
+ if (res == SUCCESS_RETURN && lite_cjson_is_array(&lite_item)) {
+ service->input_data_number = lite_item.size;
+ res = _dm_shw_service_inputdatas_parse(shadow, service, &lite_item);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _dm_shw_services_parse(_IN_ dm_shw_t *shadow, _IN_ lite_cjson_t *root)
+{
+ int res = 0, index = 0;
+ lite_cjson_t lite_services, lite_service;
+ dm_shw_service_t *service = NULL;
+
+ memset(&lite_services, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(root, DM_SHW_KEY_SERVICES, strlen(DM_SHW_KEY_SERVICES), &lite_services);
+ if (res == SUCCESS_RETURN) {
+ if (!lite_cjson_is_array(&lite_services)) {
+ return DM_JSON_PARSE_FAILED;
+ }
+ } else {
+ return SUCCESS_RETURN;
+ }
+
+ dm_log_debug("Number: %d", lite_services.size);
+ if (lite_services.size == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ /* Allocate Memory For TSL Services Struct */
+ shadow->service_number = lite_services.size;
+ shadow->services = DM_malloc(sizeof(dm_shw_service_t) * (lite_services.size));
+ if (shadow->services == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(shadow->services, 0, sizeof(dm_shw_service_t) * (lite_services.size));
+
+ for (index = 0; index < lite_services.size; index++) {
+ memset(&lite_service, 0, sizeof(lite_cjson_t));
+ service = shadow->services + index;
+
+ res = lite_cjson_array_item(&lite_services, index, &lite_service);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_service)) {
+ return FAIL_RETURN;
+ }
+
+ dm_log_debug("Index: %d", index);
+ _dm_shw_service_parse(shadow, service, &lite_service);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_tsl_alink_create(_IN_ const char *tsl, _IN_ int tsl_len, _OU_ dm_shw_t **shadow)
+{
+ int res = 0;
+ lite_cjson_t lite_root;
+
+ if (shadow == NULL || *shadow != NULL || tsl == NULL || tsl_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *shadow = DM_malloc(sizeof(dm_shw_t));
+ if (*shadow == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*shadow, 0, sizeof(dm_shw_t));
+
+ /* Parse Root */
+ memset(&lite_root, 0, sizeof(lite_root));
+ res = lite_cjson_parse(tsl, tsl_len, &lite_root);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_root)) {
+ DM_free(*shadow);
+ return DM_JSON_PARSE_FAILED;
+ }
+
+ /* Parse Properties (Mandatory) */
+ res = _dm_shw_properties_parse(*shadow, &lite_root);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Parse Events (Mandatory) */
+ res = _dm_shw_events_parse(*shadow, &lite_root);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ /* Parse Services (Mandatory) */
+ res = _dm_shw_services_parse(*shadow, &lite_root);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_tsl_alink.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_tsl_alink.h
new file mode 100644
index 00000000..f73adfae
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_tsl_alink.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#if defined(DEPRECATED_LINKKIT)
+ #ifndef _DM_TSL_ALINK_H_
+ #define _DM_TSL_ALINK_H_
+
+ /**
+ * @brief Create TSL struct from TSL string.
+ * This function used to parse TSL string into TSL struct.
+ *
+ * @param tsl. The TSL string in JSON format.
+ * @param tsl_len. The length of tsl
+ * @param shadow. The pointer of TSL Struct pointer, will be malloc memory.
+ * This memory should be free by dm_shw_destroy.
+ *
+ * @return success or fail.
+ *
+ */
+ int dm_tsl_alink_create(_IN_ const char *tsl, _IN_ int tsl_len, _OU_ dm_shw_t **shadow);
+
+ #endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_utils.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_utils.c
new file mode 100644
index 00000000..fb1f4aec
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_utils.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#include "iotx_dm_internal.h"
+
+int dm_utils_copy_direct(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
+{
+ if (input == NULL || output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *output = HAL_Malloc(output_len);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, output_len);
+ memcpy(*output, input, input_len);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_copy(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
+{
+ if (input == NULL || output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *output = DM_malloc(output_len);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, output_len);
+ memcpy(*output, input, input_len);
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_strarr_index(_IN_ char *input, _IN_ int input_len,
+ _OU_ int *partial_input_len, _OU_ int *array_input_len, _OU_ int *array_index)
+{
+ int index = 0;
+ int deep = 0;
+ char *bracket_pre = NULL;
+ char *bracket_suf = NULL;
+ char array_index_str[10] = {0};
+
+ if (input == NULL || input_len <= 1 || array_index == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < input_len; index++) {
+ switch (input[index]) {
+ case '[': {
+ if (deep != 0) {
+ return FAIL_RETURN;
+ }
+ deep++;
+ if (!bracket_pre) {
+ bracket_pre = (char *)&input[index];
+ }
+ }
+ break;
+ case ']': {
+ if (deep != 1) {
+ return FAIL_RETURN;
+ }
+ deep--;
+ if (input[index - 1] == '[') {
+ return FAIL_RETURN;
+ }
+ if (!bracket_suf) {
+ bracket_suf = (char *)&input[index];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (bracket_pre && bracket_suf && ((bracket_suf - input + 1) == input_len)) {
+ if (partial_input_len) {
+ *partial_input_len = bracket_pre - input;
+ }
+ if (array_input_len) {
+ *array_input_len = bracket_suf - input + 1;
+ }
+
+ /* Get Index */
+ memcpy(array_index_str, bracket_pre + 1, bracket_suf - bracket_pre - 1);
+ *array_index = atoi(array_index_str);
+ return SUCCESS_RETURN;
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_utils_itoa_direct(_IN_ int input, _OU_ char **output)
+{
+ int res = 0;
+ char temp_output[10 + 1] = {0};
+
+ if (output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = HAL_Snprintf(temp_output, 10, "%d", input);
+ if (res < 0) {
+ return FAIL_RETURN;
+ }
+
+ *output = HAL_Malloc(strlen(temp_output) + 1);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, strlen(temp_output) + 1);
+ memcpy(*output, temp_output, strlen(temp_output));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_itoa(_IN_ int input, _OU_ char **output)
+{
+ int res = 0;
+ char temp_output[10 + 1] = {0};
+
+ if (output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = HAL_Snprintf(temp_output, 10, "%d", input);
+ if (res < 0) {
+ return FAIL_RETURN;
+ }
+
+ *output = DM_malloc(strlen(temp_output) + 1);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, strlen(temp_output) + 1);
+ memcpy(*output, temp_output, strlen(temp_output));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_ftoa_direct(_IN_ double input, _OU_ char **output)
+{
+ int res = 0;
+ char temp_output[30 + 1] = {0};
+
+ if (output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = HAL_Snprintf(temp_output, 30, "%f", input);
+ if (res < 0) {
+ return FAIL_RETURN;
+ }
+
+ *output = HAL_Malloc(strlen(temp_output) + 1);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, strlen(temp_output) + 1);
+ memcpy(*output, temp_output, strlen(temp_output));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_ftoa(_IN_ double input, _OU_ char **output)
+{
+ int res = 0;
+ char temp_output[30 + 1] = {0};
+
+ if (output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ res = HAL_Snprintf(temp_output, 30, "%f", input);
+ if (res < 0) {
+ return FAIL_RETURN;
+ }
+
+ *output = DM_malloc(strlen(temp_output) + 1);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, strlen(temp_output) + 1);
+ memcpy(*output, temp_output, strlen(temp_output));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_hex_to_str(_IN_ unsigned char *input, _IN_ int input_len, _OU_ char **output)
+{
+ int index = 0, output_len = 0;
+ unsigned char iter_char = 0;
+
+ if (input == NULL || input_len <= 0 || output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ output_len = input_len * 2;
+ *output = DM_malloc(output_len + 1);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, output_len + 1);
+
+ for (index = 0; index < input_len; index++) {
+ iter_char = (input[index] >> 4) & 0x0F;
+ if (iter_char <= 0x09) {
+ iter_char += '0';
+ } else if (iter_char >= 0x0A && iter_char <= 0x0F) {
+ iter_char += 'A' - 0x0A;
+ }
+ (*output)[index * 2] = iter_char;
+
+ iter_char = (input[index]) & 0x0F;
+ if (iter_char <= 0x09) {
+ iter_char += '0';
+ } else if (iter_char >= 0x0A && iter_char <= 0x0F) {
+ iter_char += 'A' - 0x0A;
+ }
+ (*output)[index * 2 + 1] = iter_char;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_str_to_hex(_IN_ char *input, _IN_ int input_len, _OU_ unsigned char **output, _OU_ int *output_len)
+{
+ int index = 0;
+ char iter_char = 0;
+
+ if (input == NULL || input_len <= 0 || input_len % 2 != 0 ||
+ output == NULL || *output != NULL || output_len == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *output_len = input_len / 2;
+ *output = DM_malloc(*output_len);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, *output_len);
+
+ for (index = 0; index < input_len; index += 2) {
+ if (input[index] >= '0' && input[index] <= '9') {
+ iter_char = input[index] - '0';
+ } else if (input[index] >= 'A' && input[index] <= 'F') {
+ iter_char = input[index] - 'A' + 0x0A;
+ }
+ (*output)[index / 2] |= (iter_char << 4) & 0xF0;
+
+ if (input[index + 1] >= '0' && input[index + 1] <= '9') {
+ iter_char = input[index + 1] - '0';
+ } else if (input[index + 1] >= 'A' && input[index + 1] <= 'F') {
+ iter_char = input[index + 1] - 'A' + 0x0A;
+ }
+ (*output)[index / 2] |= (iter_char) & 0x0F;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_memtok(_IN_ char *input, _IN_ int input_len, _IN_ char delimiter, _IN_ int index, _OU_ int *offset)
+{
+ int item_index = 0;
+ int count = 0;
+
+ if (input == NULL || input_len <= 0 || offset == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (item_index = 0; item_index < input_len; item_index++) {
+ if (input[item_index] == delimiter && (item_index + 1) < input_len) {
+ count++;
+ if (count == index) {
+ *offset = item_index;
+ return SUCCESS_RETURN;
+ }
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+int dm_utils_replace_char(_IN_ char *input, _IN_ int input_len, _IN_ char src, _IN_ char dest)
+{
+ int index = 0;
+
+ if (input == NULL || input_len <= 0) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ for (index = 0; index < input_len; index++) {
+ if (input[index] == src) {
+ input[index] = dest;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_service_name(_IN_ const char *prefix, _IN_ const char *name, _IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ char **service_name)
+{
+ int prefix_len = (prefix == NULL) ? (0) : (strlen(prefix));
+ int name_len = (name == NULL) ? (0) : (strlen(name));
+ int service_name_len = 0;
+ if ((prefix == NULL && name == NULL) || product_key == NULL || device_name == NULL ||
+ service_name == NULL || *service_name != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ service_name_len = prefix_len + name_len + strlen(product_key) + strlen(device_name) + 1;
+ *service_name = DM_malloc(service_name_len);
+ if (*service_name == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*service_name, 0, service_name_len);
+
+ if (prefix != NULL) {
+ HAL_Snprintf(*service_name, service_name_len, prefix, product_key, device_name);
+ }
+
+ if (name != NULL) {
+ memcpy(*service_name + strlen(*service_name), name, name_len);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_uri_add_prefix(_IN_ const char *prefix, _IN_ char *uri, _OU_ char **new_uri)
+{
+ int new_uri_len = 0;
+
+ if (prefix == NULL || uri == NULL || new_uri == NULL || *new_uri != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ new_uri_len = strlen(prefix) + strlen(uri) + 1;
+ *new_uri = DM_malloc(new_uri_len);
+ if (*new_uri == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*new_uri, 0, new_uri_len);
+
+ memcpy(*new_uri, prefix, strlen(prefix));
+ memcpy(*new_uri + strlen(*new_uri), uri, strlen(uri));
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_json_parse(_IN_ const char *payload, _IN_ int payload_len, _IN_ int type, _OU_ lite_cjson_t *lite)
+{
+ int res = 0;
+
+ if (payload == NULL || payload_len <= 0 || type < 0 || lite == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+ memset(lite, 0, sizeof(lite_cjson_t));
+
+ res = lite_cjson_parse(payload, payload_len, lite);
+ if (res != SUCCESS_RETURN) {
+ memset(lite, 0, sizeof(lite_cjson_t));
+ return FAIL_RETURN;
+ }
+
+ if (type != cJSON_Invalid && lite->type != type) {
+ memset(lite, 0, sizeof(lite_cjson_t));
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int dm_utils_json_object_item(_IN_ lite_cjson_t *lite, _IN_ const char *key, _IN_ int key_len, _IN_ int type,
+ _OU_ lite_cjson_t *lite_item)
+{
+ int res = 0;
+
+ if (lite == NULL || lite->type != cJSON_Object || key == NULL || key_len <= 0 || type < 0 || lite_item == NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ if (lite->type != cJSON_Object) {
+ dm_log_err("lite->type != cJSON_Object, %d", lite->type);
+ }
+
+ memset(lite_item, 0, sizeof(lite_cjson_t));
+
+ res = lite_cjson_object_item(lite, key, key_len, lite_item);
+ if (res != SUCCESS_RETURN) {
+ /* dm_log_err(DM_UTILS_LOG_JSON_PARSE_FAILED, lite->value_length, lite->value); */
+ memset(lite_item, 0, sizeof(lite_cjson_t));
+ return FAIL_RETURN;
+ }
+
+ if (type != cJSON_Invalid && lite_item->type != type) {
+ memset(lite_item, 0, sizeof(lite_cjson_t));
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+void *dm_utils_malloc(unsigned int size)
+{
+#ifdef INFRA_MEM_STATS
+ return LITE_malloc(size, MEM_MAGIC, "lite_cjson");
+#else
+ return HAL_Malloc(size);
+#endif
+}
+
+void dm_utils_free(void *ptr)
+{
+#ifdef INFRA_MEM_STATS
+ LITE_free(ptr);
+#else
+ HAL_Free((void *)ptr);
+#endif
+}
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_utils.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_utils.h
new file mode 100644
index 00000000..e84b9ac5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_utils.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _DM_UTILS_H_
+#define _DM_UTILS_H_
+
+#define DM_UTILS_UINT16_STRLEN (5)
+#define DM_UTILS_UINT32_STRLEN (10)
+#define DM_UTILS_UINT64_STRLEN (20)
+
+int dm_utils_copy_direct(void *input, int input_len, void **output, int output_len);
+
+int dm_utils_copy(void *input, int input_len, void **output, int output_len);
+
+/**
+ * @brief search array index in a string.
+ * This function used to search array index in a string.
+ *
+ * @param input. The string to be searched
+ * @param input_len. The length of input
+ * @param partial_input_len. The length of input except [xx]
+ * @param array_input_len. The length of input include [xx]
+ * @param array_index. The array index in [xx]
+ *
+ * @warning input must be type of "xxxxx[xx]"
+ * @return success or fail.
+ *
+ */
+int dm_utils_strarr_index(char *input, int input_len,
+ int *partial_input_len, int *array_input_len, int *array_index);
+
+int dm_utils_itoa_direct(int input, char **output);
+int dm_utils_itoa(int input, char **output);
+int dm_utils_ftoa_direct(double input, char **output);
+int dm_utils_ftoa(double input, char **output);
+int dm_utils_hex_to_str(unsigned char *input, int input_len, char **output);
+int dm_utils_str_to_hex(char *input, int input_len, unsigned char **output, int *output_len);
+int dm_utils_memtok(char *input, int input_len, char delimiter, int index, int *offset);
+int dm_utils_replace_char(char *input, int input_len, char src, char dest);
+int dm_utils_service_name(const char *prefix, const char *name, char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ char device_name[IOTX_DEVICE_NAME_LEN + 1], char **service_name);
+int dm_utils_uri_add_prefix(const char *prefix, char *uri, char **new_uri);
+int dm_utils_json_parse(const char *payload, int payload_len, int type, lite_cjson_t *lite);
+int dm_utils_json_object_item(lite_cjson_t *lite, const char *key, int key_len, int type,
+ lite_cjson_t *lite_item);
+void *dm_utils_malloc(unsigned int size);
+void dm_utils_free(void *ptr);
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_wrapper.h
new file mode 100644
index 00000000..2828a3bc
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/dm_wrapper.h
@@ -0,0 +1,81 @@
+#ifndef _DM_WRAPPER_H_
+#define _DM_WRAPPER_H_
+
+#include "infra_compat.h"
+#include "wrappers_defs.h"
+
+int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1]);
+int HAL_GetProductSecret(char product_secret[IOTX_PRODUCT_SECRET_LEN + 1]);
+int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
+
+void *HAL_MutexCreate(void);
+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);
+uint64_t HAL_UptimeMs(void);
+void HAL_SleepMs(uint32_t ms);
+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, ...);
+
+#ifdef INFRA_LOG
+#include
+int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap);
+#endif
+
+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);
+
+void *HAL_SemaphoreCreate(void);
+void HAL_SemaphoreDestroy(void *sem);
+void HAL_SemaphorePost(void *sem);
+int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
+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);
+int HAL_Kv_Del(const char *key);
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ void HAL_Firmware_Persistence_Start(void);
+ int HAL_Firmware_Persistence_Write(char *buffer, uint32_t length);
+ int HAL_Firmware_Persistence_Stop(void);
+#ifdef SUPPORT_SECURITY_OTA
+ int HAL_Firmware_Check_Rsa_Key(char *buffer, uint32_t length);
+#endif
+#endif
+
+//#ifdef DEPRECATED_LINKKIT
+#if 1
+int HAL_SetProductKey(char *product_key);
+int HAL_SetProductSecret(char *product_secret);
+int HAL_SetDeviceName(char *device_name);
+int HAL_SetDeviceSecret(char *device_secret);
+#endif
+
+#ifdef ALCS_ENABLED
+p_HAL_Aes128_t HAL_Aes128_Init(
+ const uint8_t *key,
+ const uint8_t *iv,
+ AES_DIR_t dir);
+int HAL_Aes128_Cbc_Encrypt(
+ p_HAL_Aes128_t aes,
+ const void *src,
+ size_t blockNum,
+ void *dst);
+int HAL_Aes128_Destroy(p_HAL_Aes128_t aes);
+int HAL_Aes128_Cbc_Decrypt(
+ p_HAL_Aes128_t aes,
+ const void *src,
+ size_t blockNum,
+ void *dst);
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_gateway.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_gateway.c
new file mode 100644
index 00000000..8f38be42
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_gateway.c
@@ -0,0 +1,2532 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#if defined(DEPRECATED_LINKKIT) && defined(DEVICE_MODEL_GATEWAY)
+
+#include "impl_gateway.h"
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define IMPL_GATEWAY_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "impl.gateway")
+ #define IMPL_GATEWAY_FREE(ptr) IMPL_GATEWAY_FREE(ptr)
+#else
+ #define IMPL_GATEWAY_MALLOC(size) HAL_Malloc(size)
+ #define IMPL_GATEWAY_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define impl_gateway_err(...) log_err("impl.gateway", __VA_ARGS__)
+ #define impl_gateway_info(...) log_info("impl.gateway", __VA_ARGS__)
+ #define impl_gateway_debug(...) log_debug("impl.gateway", __VA_ARGS__)
+#else
+ #define impl_gateway_err(...)
+ #define impl_gateway_info(...)
+ #define impl_gateway_debug(...)
+#endif
+
+static linkkit_gateway_legacy_ctx_t g_linkkit_gateway_legacy_ctx = {0};
+
+static linkkit_gateway_legacy_ctx_t *_linkkit_gateway_legacy_get_ctx(void)
+{
+ return &g_linkkit_gateway_legacy_ctx;
+}
+
+static void _linkkit_gateway_mutex_lock(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ if (linkkit_gateway_ctx->mutex) {
+ HAL_MutexLock(linkkit_gateway_ctx->mutex);
+ }
+}
+
+static void _linkkit_gateway_mutex_unlock(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ if (linkkit_gateway_ctx->mutex) {
+ HAL_MutexUnlock(linkkit_gateway_ctx->mutex);
+ }
+}
+
+static void _linkkit_gateway_upstream_mutex_lock(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ if (linkkit_gateway_ctx->upstream_mutex) {
+ HAL_MutexLock(linkkit_gateway_ctx->upstream_mutex);
+ }
+}
+
+static void _linkkit_gateway_upstream_mutex_unlock(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ if (linkkit_gateway_ctx->upstream_mutex) {
+ HAL_MutexUnlock(linkkit_gateway_ctx->upstream_mutex);
+ }
+}
+
+static int _linkkit_gateway_callback_list_insert(int devid, linkkit_cbs_t *callback, void *context)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_dev_callback_node_t *search_node = NULL, *node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->dev_callback_list, linked_list,
+ linkkit_gateway_dev_callback_node_t) {
+ if (search_node->devid == devid) {
+ impl_gateway_info("Device Already Exist: %d", devid);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ node = IMPL_GATEWAY_MALLOC(sizeof(linkkit_gateway_dev_callback_node_t));
+ if (node == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(node, 0, sizeof(linkkit_gateway_dev_callback_node_t));
+ node->devid = devid;
+ node->callback = callback;
+ node->callback_ctx = context;
+ INIT_LIST_HEAD(&node->linked_list);
+
+ list_add(&node->linked_list, &linkkit_gateway_ctx->dev_callback_list);
+
+ return SUCCESS_RETURN;
+}
+
+static int _linkkit_gateway_callback_list_remove(int devid)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_dev_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->dev_callback_list, linked_list,
+ linkkit_gateway_dev_callback_node_t) {
+ if (search_node->devid == devid) {
+ impl_gateway_info("Device Found: %d, Delete It", devid);
+ list_del(&search_node->linked_list);
+ IMPL_GATEWAY_FREE(search_node);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _linkkit_gateway_callback_list_search(int devid, linkkit_gateway_dev_callback_node_t **node)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_dev_callback_node_t *search_node = NULL;
+
+ if (devid < 0 || node == NULL || *node != NULL) {
+ return FAIL_RETURN;
+ }
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->dev_callback_list, linked_list,
+ linkkit_gateway_dev_callback_node_t) {
+ if (search_node->devid == devid) {
+ impl_gateway_info("Device Found: %d", devid);
+ *node = search_node;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static void _linkkit_gateway_callback_list_destroy(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_dev_callback_node_t *search_node = NULL;
+ linkkit_gateway_dev_callback_node_t *next_node = NULL;
+
+ list_for_each_entry_safe(search_node, next_node, &linkkit_gateway_ctx->dev_callback_list, linked_list,
+ linkkit_gateway_dev_callback_node_t) {
+ list_del(&search_node->linked_list);
+ IMPL_GATEWAY_FREE(search_node);
+ }
+}
+
+static int _linkkit_gateway_upstream_sync_callback_list_insert(int msgid, void *semaphore,
+ linkkit_gateway_upstream_sync_callback_node_t **node)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_sync_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->upstream_sync_callback_list, linked_list,
+ linkkit_gateway_upstream_sync_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ impl_gateway_info("Message Already Exist: %d", msgid);
+ return FAIL_RETURN;
+ }
+ }
+
+ search_node = IMPL_GATEWAY_MALLOC(sizeof(linkkit_gateway_upstream_sync_callback_node_t));
+ if (search_node == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(search_node, 0, sizeof(linkkit_gateway_upstream_sync_callback_node_t));
+ search_node->msgid = msgid;
+ search_node->semaphore = semaphore;
+ INIT_LIST_HEAD(&search_node->linked_list);
+
+ list_add(&search_node->linked_list, &linkkit_gateway_ctx->upstream_sync_callback_list);
+ impl_gateway_info("New Message, msgid: %d", msgid);
+
+ *node = search_node;
+ return SUCCESS_RETURN;
+}
+
+static int _linkkit_gateway_upstream_sync_callback_list_remove(int msgid)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_sync_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->upstream_sync_callback_list, linked_list,
+ linkkit_gateway_upstream_sync_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ impl_gateway_info("Message Found: %d, Delete It", msgid);
+ HAL_SemaphoreDestroy(search_node->semaphore);
+ list_del(&search_node->linked_list);
+ IMPL_GATEWAY_FREE(search_node);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _linkkit_gateway_upstream_sync_callback_list_search(int msgid,
+ linkkit_gateway_upstream_sync_callback_node_t **node)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_sync_callback_node_t *search_node = NULL;
+
+ if (node == NULL || *node != NULL) {
+ return FAIL_RETURN;
+ }
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->upstream_sync_callback_list, linked_list,
+ linkkit_gateway_upstream_sync_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ impl_gateway_info("Sync Message Found: %d", msgid);
+ *node = search_node;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static void _linkkit_gateway_upstream_sync_callback_list_destroy(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_sync_callback_node_t *search_node = NULL, *next_node = NULL;
+
+ list_for_each_entry_safe(search_node, next_node, &linkkit_gateway_ctx->upstream_sync_callback_list, linked_list,
+ linkkit_gateway_upstream_sync_callback_node_t) {
+ list_del(&search_node->linked_list);
+ HAL_SemaphoreDestroy(search_node->semaphore);
+ IMPL_GATEWAY_FREE(search_node);
+ }
+}
+
+static int _linkkit_gateway_upstream_async_callback_list_insert(int msgid, int timeout_ms,
+ linkkit_gateway_upstream_async_callback callback, void *context)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_async_callback_node_t *search_node = NULL, *node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->upstream_async_callback_list, linked_list,
+ linkkit_gateway_upstream_async_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ impl_gateway_info("Async Message Already Exist: %d", msgid);
+ return FAIL_RETURN;
+ }
+ }
+
+ node = IMPL_GATEWAY_MALLOC(sizeof(linkkit_gateway_upstream_async_callback_node_t));
+ if (node == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(node, 0, sizeof(linkkit_gateway_upstream_async_callback_node_t));
+ node->msgid = msgid;
+ node->timeout_ms = timeout_ms;
+ node->timestamp_ms = HAL_UptimeMs();
+ node->callback = callback;
+ node->callback_ctx = context;
+
+ INIT_LIST_HEAD(&node->linked_list);
+
+ list_add(&node->linked_list, &linkkit_gateway_ctx->upstream_async_callback_list);
+
+ return SUCCESS_RETURN;
+}
+
+static int _linkkit_gateway_upstream_async_callback_list_remove(int msgid)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_async_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->upstream_async_callback_list, linked_list,
+ linkkit_gateway_upstream_async_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ impl_gateway_info("Async Message Found: %d, Delete It", msgid);
+ list_del(&search_node->linked_list);
+ IMPL_GATEWAY_FREE(search_node);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _linkkit_gateway_upstream_async_callback_list_search(int msgid,
+ linkkit_gateway_upstream_async_callback_node_t **node)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_async_callback_node_t *search_node = NULL;
+
+ if (node == NULL || *node != NULL) {
+ return FAIL_RETURN;
+ }
+
+ list_for_each_entry(search_node, &linkkit_gateway_ctx->upstream_async_callback_list, linked_list,
+ linkkit_gateway_upstream_async_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ impl_gateway_info("Async Message Found: %d", msgid);
+ *node = search_node;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static void _linkkit_gateway_upstream_async_callback_list_destroy(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_async_callback_node_t *search_node = NULL, *next_node = NULL;
+
+ list_for_each_entry_safe(search_node, next_node, &linkkit_gateway_ctx->upstream_async_callback_list, linked_list,
+ linkkit_gateway_upstream_async_callback_node_t) {
+ list_del(&search_node->linked_list);
+ IMPL_GATEWAY_FREE(search_node);
+ }
+}
+
+static void _linkkit_gateway_upstream_callback_remove(int msgid, int code)
+{
+ int res = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *sync_node = NULL;
+ res = _linkkit_gateway_upstream_sync_callback_list_search(msgid, &sync_node);
+ if (res != SUCCESS_RETURN) {
+ linkkit_gateway_upstream_async_callback_node_t *node = NULL;
+ res = _linkkit_gateway_upstream_async_callback_list_search(msgid, &node);
+ if (res == SUCCESS_RETURN) {
+ uint64_t current_time = HAL_UptimeMs();
+ if (current_time - node->timestamp_ms > node->timeout_ms) {
+ if (node->callback) {
+ node->callback(FAIL_RETURN, node->callback_ctx);
+ }
+ } else {
+ if (node->callback) {
+ int return_value = (code == IOTX_DM_ERR_CODE_SUCCESS) ? (SUCCESS_RETURN) : (FAIL_RETURN);
+ impl_gateway_info("Async Message %d Result: %d", msgid, return_value);
+ node->callback(return_value, node->callback_ctx);
+ }
+ }
+ _linkkit_gateway_upstream_async_callback_list_remove(msgid);
+ }
+ } else {
+ sync_node->code = (code == IOTX_DM_ERR_CODE_SUCCESS) ? (SUCCESS_RETURN) : (FAIL_RETURN);
+ impl_gateway_info("Sync Message %d Result: %d", msgid, sync_node->code);
+ HAL_SemaphorePost(sync_node->semaphore);
+ }
+}
+
+linkkit_params_t *linkkit_gateway_get_default_params(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ /* Legacy Parameter */
+ linkkit_gateway_ctx->init_params.maxMsgSize = 20 * 1024;
+ linkkit_gateway_ctx->init_params.maxMsgQueueSize = 16;
+ linkkit_gateway_ctx->init_params.threadPoolSize = 4;
+ linkkit_gateway_ctx->init_params.threadStackSize = 8 * 1024;
+
+ return &linkkit_gateway_ctx->init_params;
+}
+
+int linkkit_gateway_setopt(linkkit_params_t *params, int option, void *value, int value_len)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (params == NULL || value == NULL) {
+ return FAIL_RETURN;
+ }
+
+ switch (option) {
+ case LINKKIT_OPT_MAX_MSG_SIZE: {
+ if (value_len != sizeof(int)) {
+ return FAIL_RETURN;
+ }
+ if (*((int *)value) < 256) {
+ impl_gateway_err("maxMsgSize should not less than 256 bytes\n");
+ return FAIL_RETURN;
+ }
+ linkkit_gateway_ctx->init_params.maxMsgSize = *((int *)value);
+ }
+ break;
+ case LINKKIT_OPT_MAX_MSG_QUEUE_SIZE: {
+ if (value_len != sizeof(int)) {
+ return FAIL_RETURN;
+ }
+ if (*((int *)value) < 1) {
+ impl_gateway_err("maxMsgQueueSize should not less than 1\n");
+ return FAIL_RETURN;
+ }
+ linkkit_gateway_ctx->init_params.maxMsgQueueSize = *((int *)value);
+ }
+ break;
+ case LINKKIT_OPT_THREAD_POOL_SIZE: {
+ if (value_len != sizeof(int)) {
+ return FAIL_RETURN;
+ }
+ if (*((int *)value) < 1) {
+ impl_gateway_err("threadPoolSize should not less than 1\n");
+ return FAIL_RETURN;
+ }
+ linkkit_gateway_ctx->init_params.threadPoolSize = *((int *)value);
+ }
+ break;
+ case LINKKIT_OPT_THREAD_STACK_SIZE: {
+ if (value_len != sizeof(int)) {
+ return FAIL_RETURN;
+ }
+ if (*((int *)value) < 1024) {
+ impl_gateway_err("threadStackSize should not less than 1024\n");
+ return FAIL_RETURN;
+ }
+ linkkit_gateway_ctx->init_params.threadStackSize = *((int *)value);
+ }
+ break;
+ case LINKKIT_OPT_PROPERTY_POST_REPLY:
+ iotx_dm_set_opt(0, value);
+ break;
+ case LINKKIT_OPT_EVENT_POST_REPLY:
+ iotx_dm_set_opt(1, value);
+ break;
+ case LINKKIT_OPT_PROPERTY_SET_REPLY:
+ iotx_dm_set_opt(2, value);
+ break;
+ default:
+ impl_gateway_err("unknow option: %d\n", option);
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_set_event_callback(linkkit_params_t *params, int (*event_cb)(linkkit_event_t *ev, void *ctx),
+ void *ctx)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (params == NULL || event_cb == NULL) {
+ return FAIL_RETURN;
+ }
+
+ linkkit_gateway_ctx->init_params.event_cb = event_cb;
+ linkkit_gateway_ctx->init_params.ctx = ctx;
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_init(linkkit_params_t *initParams)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (initParams == NULL) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_inited == 1) {
+ return FAIL_RETURN;
+ }
+
+ if (initParams->maxMsgSize < 256 ||
+ initParams->maxMsgQueueSize < 1 ||
+ initParams->threadPoolSize < 1 ||
+ initParams->threadStackSize < 1024) {
+ return FAIL_RETURN;
+ }
+ linkkit_gateway_ctx->is_inited = 1;
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_exit(void)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (linkkit_gateway_ctx->is_inited == 0) {
+ return FAIL_RETURN;
+ }
+ linkkit_gateway_ctx->is_inited = 0;
+
+ return SUCCESS_RETURN;
+}
+
+static void _linkkit_gateway_event_callback(iotx_dm_event_types_t type, char *payload)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ impl_gateway_info("Receive Message Type: %d", type);
+ if (payload) {
+ impl_gateway_info("Receive Message: %s", payload);
+ }
+
+ switch (type) {
+ case IOTX_DM_EVENT_CLOUD_CONNECTED: {
+ if (linkkit_gateway_ctx->init_params.event_cb) {
+ linkkit_event_t event;
+
+ memset(&event, 0, sizeof(linkkit_event_t));
+ event.event_type = LINKKIT_EVENT_CLOUD_CONNECTED;
+ linkkit_gateway_ctx->init_params.event_cb(&event, linkkit_gateway_ctx->init_params.ctx);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_CLOUD_DISCONNECT: {
+ if (linkkit_gateway_ctx->init_params.event_cb) {
+ linkkit_event_t event;
+
+ memset(&event, 0, sizeof(linkkit_event_t));
+ event.event_type = LINKKIT_EVENT_CLOUD_DISCONNECTED;
+ linkkit_gateway_ctx->init_params.event_cb(&event, linkkit_gateway_ctx->init_params.ctx);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_SUBDEV_REGISTER_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse JSON */
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite)) {
+ return;
+ }
+
+ /* Parse Message ID */
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_number(&lite_item_id)) {
+ return;
+ }
+ impl_gateway_info("Current Msg ID: %d", lite_item_id.value_int);
+
+ /* Parse Message Code */
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_number(&lite_item_code)) {
+ return;
+ }
+ impl_gateway_info("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_number(&lite_item_devid)) {
+ return;
+ }
+ impl_gateway_info("Current devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_SUBDEV_UNREGISTER_REPLY: {
+
+ }
+ break;
+ case IOTX_DM_EVENT_TOPO_ADD_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse JSON */
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite)) {
+ return;
+ }
+
+ /* Parse Message ID */
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_number(&lite_item_id)) {
+ return;
+ }
+ impl_gateway_info("Current Msg ID: %d", lite_item_id.value_int);
+
+ /* Parse Message Code */
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_number(&lite_item_code)) {
+ return;
+ }
+ impl_gateway_info("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_number(&lite_item_devid)) {
+ return;
+ }
+ impl_gateway_info("Current devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_TOPO_DELETE_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_COMBINE_LOGIN_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_COMBINE_LOGOUT_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_PROPERTY_SET: {
+ int res = 0;
+ linkkit_gateway_dev_callback_node_t *node = NULL;
+ lite_cjson_t lite, lite_item_devid, lite_item_payload;
+ char *params = NULL;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ /* Parse Payload */
+ memset(&lite_item_payload, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD, strlen(LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD),
+ &lite_item_payload);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Payload: %.*", lite_item_payload.value_length, lite_item_payload.value);
+
+ params = IMPL_GATEWAY_MALLOC(lite_item_payload.value_length + 1);
+ if (params == NULL) {
+ return;
+ }
+ memset(params, 0, lite_item_payload.value_length + 1);
+ memcpy(params, lite_item_payload.value, lite_item_payload.value_length);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(lite_item_devid.value_int, &node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (node->callback->set_property) {
+ node->callback->set_property(params, node->callback_ctx);
+ }
+ }
+
+ IMPL_GATEWAY_FREE(params);
+ }
+ break;
+ case IOTX_DM_EVENT_GATEWAY_PERMIT: {
+ int res = 0;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ lite_cjson_t lite, lite_item_pk, lite_item_timeout;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Product Key */
+ memset(&lite_item_pk, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_PRODUCT_KEY,
+ strlen(LINKKIT_GATEWAY_LEGACY_KEY_PRODUCT_KEY), &lite_item_pk);
+ if (res != SUCCESS_RETURN || lite_item_pk.value_length >= IOTX_PRODUCT_KEY_LEN + 1) {
+ return;
+ }
+ impl_gateway_debug("Current Product Key: %.*s", lite_item_pk.value_length, lite_item_pk.value);
+
+ /* Parse Timeout */
+ memset(&lite_item_timeout, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_TIME, strlen(LINKKIT_GATEWAY_LEGACY_KEY_TIME),
+ &lite_item_timeout);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Timeout: %d", lite_item_timeout.value_int);
+
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+
+ if (linkkit_gateway_ctx->init_params.event_cb) {
+ linkkit_event_t event;
+
+ memset(&event, 0, sizeof(linkkit_event_t));
+ event.event_type = LINKKIT_EVENT_SUBDEV_PERMITED;
+ event.event_data.subdev_permited.productKey = product_key;
+ event.event_data.subdev_permited.timeoutSec = lite_item_timeout.value_int;
+ linkkit_gateway_ctx->init_params.event_cb(&event, linkkit_gateway_ctx->init_params.ctx);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_THING_SERVICE_REQUEST: {
+ int res = 0;
+ linkkit_gateway_dev_callback_node_t *node = NULL;
+ lite_cjson_t lite, lite_item_id, lite_item_devid, lite_item_serviceid, lite_item_paylaod;
+ char *identifier = NULL, *input = NULL, *output = NULL;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ /* Parse Serviceid */
+ memset(&lite_item_serviceid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_SERVICEID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_SERVICEID),
+ &lite_item_serviceid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current ServiceID: %.*s", lite_item_serviceid.value_length, lite_item_serviceid.value);
+
+ /* Parse Payload */
+ memset(&lite_item_paylaod, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD, strlen(LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD),
+ &lite_item_paylaod);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Payload: %.*s", lite_item_paylaod.value_length, lite_item_paylaod.value);
+
+ identifier = IMPL_GATEWAY_MALLOC(lite_item_serviceid.value_length + 1);
+ if (identifier == NULL) {
+ return;
+ }
+ memset(identifier, 0, lite_item_serviceid.value_length + 1);
+ memcpy(identifier, lite_item_serviceid.value, lite_item_serviceid.value_length);
+
+ input = IMPL_GATEWAY_MALLOC(lite_item_paylaod.value_length + 1);
+ if (input == NULL) {
+ IMPL_GATEWAY_FREE(identifier);
+ return;
+ }
+ memset(input, 0, lite_item_paylaod.value_length + 1);
+ memcpy(input, lite_item_paylaod.value, lite_item_paylaod.value_length);
+
+
+ output = IMPL_GATEWAY_MALLOC(linkkit_gateway_ctx->init_params.maxMsgSize + 1);
+ if (output == NULL) {
+ IMPL_GATEWAY_FREE(identifier);
+ IMPL_GATEWAY_FREE(input);
+ return;
+ }
+ memset(output, 0, linkkit_gateway_ctx->init_params.maxMsgSize + 1);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(lite_item_devid.value_int, &node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (node->callback->call_service) {
+ res = node->callback->call_service(identifier, input, output, linkkit_gateway_ctx->init_params.maxMsgSize,
+ node->callback_ctx);
+ if (res == SUCCESS_RETURN) {
+ iotx_dm_deprecated_legacy_send_service_response(lite_item_devid.value_int, lite_item_id.value_int, 200,
+ lite_item_serviceid.value,
+ lite_item_serviceid.value_length, output, strlen(output));
+ } else {
+ iotx_dm_deprecated_legacy_send_service_response(lite_item_devid.value_int, lite_item_id.value_int, 202,
+ lite_item_serviceid.value,
+ lite_item_serviceid.value_length, "{}", strlen("{}"));
+ }
+ }
+ }
+
+ IMPL_GATEWAY_FREE(identifier);
+ IMPL_GATEWAY_FREE(input);
+ IMPL_GATEWAY_FREE(output);
+ }
+ break;
+ case IOTX_DM_EVENT_MODEL_DOWN_RAW: {
+ int res = 0;
+ linkkit_gateway_dev_callback_node_t *node = NULL;
+ lite_cjson_t lite, lite_item_devid, lite_item_rawdata;
+ char *output = NULL;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ /* Parse Raw Data */
+ memset(&lite_item_rawdata, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD, strlen(LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD),
+ &lite_item_rawdata);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Raw Data: %.*s", lite_item_rawdata.value_length, lite_item_rawdata.value);
+
+ output = IMPL_GATEWAY_MALLOC(linkkit_gateway_ctx->init_params.maxMsgSize + 1);
+ if (output == NULL) {
+ return;
+ }
+ memset(output, 0, linkkit_gateway_ctx->init_params.maxMsgSize + 1);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(lite_item_devid.value_int, &node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (node->callback->down_rawdata) {
+ res = node->callback->down_rawdata(lite_item_rawdata.value, lite_item_rawdata.value_length, output,
+ linkkit_gateway_ctx->init_params.maxMsgSize, node->callback_ctx);
+ if (res > 0) {
+ iotx_dm_post_rawdata(lite_item_devid.value_int, output, res);
+ }
+ }
+ }
+
+ IMPL_GATEWAY_FREE(output);
+ }
+ break;
+ case IOTX_DM_EVENT_MODEL_UP_RAW_REPLY: {
+ int res = 0;
+ linkkit_gateway_dev_callback_node_t *node = NULL;
+ lite_cjson_t lite, lite_item_devid, lite_item_rawdata;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ /* Parse Raw Data */
+ memset(&lite_item_rawdata, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD, strlen(LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD),
+ &lite_item_rawdata);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Raw Data: %.*s", lite_item_rawdata.value_length, lite_item_rawdata.value);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(lite_item_devid.value_int, &node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (node->callback->post_rawdata_reply) {
+ node->callback->post_rawdata_reply(lite_item_rawdata.value, lite_item_rawdata.value_length, node->callback_ctx);
+ }
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_INITIALIZED: {
+ int res = 0;
+ linkkit_gateway_dev_callback_node_t *node = NULL;
+ lite_cjson_t lite, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(lite_item_devid.value_int, &node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (node->callback->register_complete) {
+ node->callback->register_complete(node->callback_ctx);
+ }
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_EVENT_SPECIFIC_POST_REPLY: {
+ int res = 0;
+ char *eventid = NULL;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid, lite_item_eventid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ /* Parse Property ID */
+ memset(&lite_item_eventid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_EVENTID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_EVENTID),
+ &lite_item_eventid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current EventID: %.*s", lite_item_eventid.value_length, lite_item_eventid.value);
+
+ eventid = IMPL_GATEWAY_MALLOC(lite_item_eventid.value_length + 1);
+ if (eventid == NULL) {
+ return;
+ }
+ memset(eventid, 0, lite_item_eventid.value_length + 1);
+ memcpy(eventid, lite_item_eventid.value, lite_item_eventid.value_length);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ IMPL_GATEWAY_FREE(eventid);
+ }
+ break;
+ case IOTX_DM_EVENT_FOTA_NEW_FIRMWARE: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_version;
+ char *version = NULL;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite)) {
+ return;
+ }
+
+ /* Parse Version */
+ memset(&lite_item_version, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_VERSION, strlen(LINKKIT_GATEWAY_LEGACY_KEY_VERSION),
+ &lite_item_version);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_version)) {
+ return;
+ }
+ impl_gateway_debug("Current Firmware Version: %.*s", lite_item_version.value_length, lite_item_version.value);
+
+ version = IMPL_GATEWAY_MALLOC(lite_item_version.value_length + 1);
+ if (version == NULL) {
+ return;
+ }
+ memset(version, 0, lite_item_version.value_length + 1);
+ memcpy(version, lite_item_version.value, lite_item_version.value_length);
+
+ if (linkkit_gateway_ctx->fota_callback) {
+ linkkit_gateway_ctx->fota_callback(service_fota_callback_type_new_version_detected, version);
+ }
+
+ if (version) {
+ IMPL_GATEWAY_FREE(version);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_DEVICEINFO_UPDATE_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_DEVICEINFO_DELETE_REPLY: {
+ int res = 0;
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid;
+
+ if (payload == NULL) {
+ return;
+ }
+
+ /* Parse Payload */
+ memset(&lite, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_parse(payload, strlen(payload), &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ /* Parse Id */
+ memset(&lite_item_id, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_ID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_ID),
+ &lite_item_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Id: %d", lite_item_id.value_int);
+
+ /* Parse Code */
+ memset(&lite_item_code, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_CODE, strlen(LINKKIT_GATEWAY_LEGACY_KEY_CODE),
+ &lite_item_code);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Code: %d", lite_item_code.value_int);
+
+ /* Parse Devid */
+ memset(&lite_item_devid, 0, sizeof(lite_cjson_t));
+ res = lite_cjson_object_item(&lite, LINKKIT_GATEWAY_LEGACY_KEY_DEVID, strlen(LINKKIT_GATEWAY_LEGACY_KEY_DEVID),
+ &lite_item_devid);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ impl_gateway_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+ break;
+ default: {
+ impl_gateway_info("Not Found Type For Now, Smile");
+ }
+ break;
+ }
+}
+
+static void *_linkkit_gateway_dispatch(void *params)
+{
+ while (1) {
+ iotx_dm_dispatch();
+ HAL_SleepMs(20);
+ }
+ return NULL;
+}
+
+int linkkit_gateway_start(linkkit_cbs_t *cbs, void *ctx)
+{
+ int res = 0, stack_used = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ iotx_dm_init_params_t dm_init_params;
+ linkkit_gateway_dev_callback_node_t *node = NULL;
+
+ if (cbs == NULL) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_inited == 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started) {
+ impl_gateway_info("Linkkit Gateway Already Started");
+ return SUCCESS_RETURN;
+ }
+
+ linkkit_gateway_ctx->is_inited = 1;
+ linkkit_gateway_ctx->is_started = 1;
+
+ /* Create Mutex */
+ linkkit_gateway_ctx->mutex = HAL_MutexCreate();
+ if (linkkit_gateway_ctx->mutex == NULL) {
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ linkkit_gateway_ctx->upstream_mutex = HAL_MutexCreate();
+ if (linkkit_gateway_ctx->upstream_mutex == NULL) {
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Initialize Device Manager */
+ memset(&dm_init_params, 0, sizeof(iotx_dm_init_params_t));
+ dm_init_params.secret_type = IOTX_DM_DEVICE_SECRET_DEVICE;
+ dm_init_params.domain_type = IOTX_DM_CLOUD_DOMAIN_SHANGHAI;
+ dm_init_params.event_callback = _linkkit_gateway_event_callback;
+
+ res = iotx_dm_open();
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+ HAL_MutexDestroy(linkkit_gateway_ctx->upstream_mutex);
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_connect(&dm_init_params);
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+ HAL_MutexDestroy(linkkit_gateway_ctx->upstream_mutex);
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_subscribe(IOTX_DM_LOCAL_NODE_DEVID);
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+ HAL_MutexDestroy(linkkit_gateway_ctx->upstream_mutex);
+ iotx_dm_close();
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ res = HAL_ThreadCreate(&linkkit_gateway_ctx->dispatch_thread, _linkkit_gateway_dispatch, NULL, NULL, &stack_used);
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+ HAL_MutexDestroy(linkkit_gateway_ctx->upstream_mutex);
+ iotx_dm_close();
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Insert Gateway Callback And Callback Context Into Device Callback Linkked List */
+ INIT_LIST_HEAD(&linkkit_gateway_ctx->dev_callback_list);
+
+ res = _linkkit_gateway_callback_list_insert(IOTX_DM_LOCAL_NODE_DEVID, cbs, ctx);
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+ HAL_MutexDestroy(linkkit_gateway_ctx->upstream_mutex);
+ iotx_dm_close();
+ HAL_ThreadDelete(linkkit_gateway_ctx->dispatch_thread);
+ linkkit_gateway_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Init Upstream Callback List */
+ INIT_LIST_HEAD(&linkkit_gateway_ctx->upstream_sync_callback_list);
+ INIT_LIST_HEAD(&linkkit_gateway_ctx->upstream_async_callback_list);
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(IOTX_DM_LOCAL_NODE_DEVID, &node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (node->callback->register_complete) {
+ node->callback->register_complete(node->callback_ctx);
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_stop(int devid)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+ if (devid != IOTX_DM_LOCAL_NODE_DEVID) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ _linkkit_gateway_upstream_mutex_lock();
+ linkkit_gateway_ctx->is_started = 0;
+ HAL_ThreadDelete(linkkit_gateway_ctx->dispatch_thread);
+ iotx_dm_close();
+ HAL_SleepMs(200);
+ _linkkit_gateway_callback_list_destroy();
+ _linkkit_gateway_upstream_sync_callback_list_destroy();
+ _linkkit_gateway_upstream_async_callback_list_destroy();
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ HAL_MutexDestroy(linkkit_gateway_ctx->upstream_mutex);
+ HAL_MutexDestroy(linkkit_gateway_ctx->mutex);
+
+ linkkit_gateway_ctx->mutex = NULL;
+ linkkit_gateway_ctx->upstream_mutex = NULL;
+ memset(&linkkit_gateway_ctx->init_params, 0, sizeof(linkkit_params_t));
+ linkkit_gateway_ctx->dispatch_thread = NULL;
+ linkkit_gateway_ctx->fota_callback = NULL;
+ INIT_LIST_HEAD(&linkkit_gateway_ctx->dev_callback_list);
+ INIT_LIST_HEAD(&linkkit_gateway_ctx->upstream_sync_callback_list);
+ INIT_LIST_HEAD(&linkkit_gateway_ctx->upstream_async_callback_list);
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_subdev_register(char *productKey, char *deviceName, char *deviceSecret)
+{
+ int res = 0, msgid = 0, code = 0, devid = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ void *semaphore = NULL;
+ linkkit_gateway_dev_callback_node_t *dev_callback_node = NULL;
+
+ if (productKey == NULL || strlen(productKey) >= IOTX_PRODUCT_KEY_LEN + 1 ||
+ deviceName == NULL || strlen(deviceName) >= IOTX_DEVICE_NAME_LEN + 1) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_pkdn(productKey, deviceName, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ /* Subdev Delete Topo */
+ res = iotx_dm_subdev_topo_del(devid);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ /* Subdev Register */
+ res = iotx_dm_deprecated_subdev_register(devid, deviceSecret);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ if (res > SUCCESS_RETURN) {
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ msgid = res;
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ }
+
+ /* Subdev Add Topo */
+ res = iotx_dm_subdev_topo_add(devid);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ msgid = res;
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_search(devid, &dev_callback_node);
+ _linkkit_gateway_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (dev_callback_node->callback->register_complete) {
+ dev_callback_node->callback->register_complete(dev_callback_node->callback_ctx);
+ }
+ }
+
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_subdev_unregister(char *productKey, char *deviceName)
+{
+ int res = 0, msgid = 0, code = 0, devid = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+
+ if (productKey == NULL || strlen(productKey) >= IOTX_PRODUCT_KEY_LEN + 1 ||
+ deviceName == NULL || strlen(deviceName) >= IOTX_DEVICE_NAME_LEN + 1) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_pkdn(productKey, deviceName, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ /* Subdev Delete Topo */
+ res = iotx_dm_subdev_topo_del(devid);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_subdev_create(char *productKey, char *deviceName, linkkit_cbs_t *cbs, void *ctx)
+{
+ int res = 0, devid = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (productKey == NULL || strlen(productKey) >= IOTX_PRODUCT_KEY_LEN + 1 ||
+ deviceName == NULL || strlen(deviceName) >= IOTX_DEVICE_NAME_LEN + 1 || cbs == NULL) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_subdev_create(productKey, deviceName, NULL, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_insert(devid, cbs, ctx);
+ if (res != SUCCESS_RETURN) {
+ iotx_dm_subdev_destroy(devid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return devid;
+}
+
+int linkkit_gateway_subdev_destroy(int devid)
+{
+ int res = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ if (devid <= 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_callback_list_remove(devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = iotx_dm_subdev_destroy(devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_subdev_login(int devid)
+{
+ int res = 0, msgid = 0, code = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+
+ if (devid <= 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_subdev_login(devid);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = iotx_dm_subscribe(devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_subdev_logout(int devid)
+{
+ int res = 0, msgid = 0, code = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+
+ if (devid <= 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_subdev_logout(devid);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_get_devinfo(int devid, linkkit_devinfo_t *devinfo)
+{
+ int res = 0, type = 0;
+ iotx_dm_dev_status_t status;
+ iotx_dm_dev_avail_t available;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (devid < 0 || devinfo == NULL) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ memset(devinfo, 0, sizeof(linkkit_devinfo_t));
+ res = iotx_dm_deprecated_legacy_get_pkdn_ptr_by_devid(devid, &(devinfo->productKey), &(devinfo->deviceName));
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_get_device_type(devid, &type);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ if (type == IOTX_DM_DEVICE_GATEWAY) {
+ devinfo->devtype = 0;
+ } else if (type == IOTX_DM_DEVICE_SUBDEV) {
+ devinfo->devtype = 1;
+ } else {
+ impl_gateway_info("wrong device type\n");
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_get_device_status(devid, &status);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ if (status >= IOTX_DM_DEV_STATUS_LOGINED) {
+ devinfo->login = 1;
+ }
+ if (status == IOTX_DM_DEV_STATUS_ONLINE) {
+ devinfo->online = 1;
+ }
+
+ res = iotx_dm_get_device_avail_status(devid, &available);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ devinfo->state = available;
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_trigger_event_json_sync(int devid, char *identifier, char *event, int timeout_ms)
+{
+ int res = 0, msgid = 0, code = 0, event_reply_value = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+
+ if (devid < 0 || identifier == NULL || event == NULL || timeout_ms < 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_get_opt(1, (void *)&event_reply_value);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ if (timeout_ms == 0 || event_reply_value == 0) {
+ res = iotx_dm_post_event(devid, identifier, strlen(identifier), event, strlen(event));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ } else {
+ _linkkit_gateway_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ res = iotx_dm_post_event(devid, identifier, strlen(identifier), event, strlen(event));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, timeout_ms);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_trigger_event_json(int devid, char *identifier, char *event, int timeout_ms,
+ void (*func)(int retval, void *ctx), void *ctx)
+{
+ int res = 0, event_reply_value = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (devid < 0 || identifier == NULL || event == NULL || timeout_ms < 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_get_opt(1, (void *)&event_reply_value);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ impl_gateway_info("event_reply_value: %d", event_reply_value);
+
+ if (timeout_ms == 0 || event_reply_value == 0) {
+ res = iotx_dm_post_event(devid, identifier, strlen(identifier), event, strlen(event));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ } else {
+ _linkkit_gateway_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ res = iotx_dm_post_event(devid, identifier, strlen(identifier), event, strlen(event));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_async_callback_list_insert(res, timeout_ms, func, ctx);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_post_property_json_sync(int devid, char *property, int timeout_ms)
+{
+ int res = 0, msgid = 0, code = 0, property_reply_value = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+
+ if (devid < 0 || property == NULL || timeout_ms < 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_get_opt(0, (void *)&property_reply_value);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ if (timeout_ms == 0 || property_reply_value == 0) {
+ res = iotx_dm_post_property(devid, property, strlen(property));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ } else {
+ _linkkit_gateway_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ res = iotx_dm_post_property(devid, property, strlen(property));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, timeout_ms);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_post_property_json(int devid, char *property, int timeout_ms, void (*func)(int retval, void *ctx),
+ void *ctx)
+{
+ int res = 0, property_reply_value = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (devid < 0 || property == NULL || timeout_ms < 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_get_opt(0, (void *)&property_reply_value);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ if (timeout_ms == 0 || property_reply_value == 0) {
+ res = iotx_dm_post_property(devid, property, strlen(property));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ } else {
+ _linkkit_gateway_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ res = iotx_dm_post_property(devid, property, strlen(property));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_async_callback_list_insert(res, timeout_ms, func, ctx);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_post_rawdata(int devid, void *data, int len)
+{
+ int res = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (devid < 0 || data == NULL || len <= 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_post_rawdata(devid, data, len);
+ _linkkit_gateway_mutex_unlock();
+
+ return res;
+}
+
+int linkkit_gateway_fota_init(handle_service_fota_callback_fp_t callback_fp)
+{
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ linkkit_gateway_ctx->fota_callback = callback_fp;
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_invoke_fota_service(void *data_buf, int data_buf_length)
+{
+ int res = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ res = iotx_dm_fota_perform_sync(data_buf, data_buf_length);
+ _linkkit_gateway_mutex_unlock();
+
+ return res;
+}
+
+int linkkit_gateway_post_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos, int timeout_ms)
+{
+ int res = 0, index = 0, msgid = 0, code = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+ char *payload = NULL;
+ lite_cjson_item_t *lite_array = NULL, *lite_array_item = NULL;
+
+ if (devid < 0 || extinfos == NULL || nb_extinfos <= 0 || timeout_ms < 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ lite_array = lite_cjson_create_array();
+ if (lite_array == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ for (index = 0; index < nb_extinfos; index++) {
+ if (extinfos[index].attrKey == NULL || extinfos[index].attrValue == NULL) {
+ lite_cjson_delete(lite_array);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ lite_array_item = lite_cjson_create_object();
+ if (lite_array_item == NULL) {
+ lite_cjson_delete(lite_array);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ lite_cjson_add_string_to_object(lite_array_item, "attrKey", extinfos[index].attrKey);
+ lite_cjson_add_string_to_object(lite_array_item, "attrValue", extinfos[index].attrValue);
+ lite_cjson_add_item_to_array(lite_array, lite_array_item);
+ }
+
+ payload = lite_cjson_print_unformatted(lite_array);
+ if (payload == NULL) {
+ lite_cjson_delete(lite_array);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ lite_cjson_delete(lite_array);
+
+ if (timeout_ms == 0) {
+ res = iotx_dm_deviceinfo_update(devid, payload, strlen(payload));
+ IMPL_GATEWAY_FREE(payload);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ } else {
+ _linkkit_gateway_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ res = iotx_dm_deviceinfo_update(devid, payload, strlen(payload));
+ if (res < SUCCESS_RETURN) {
+ IMPL_GATEWAY_FREE(payload);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+ IMPL_GATEWAY_FREE(payload);
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, timeout_ms);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_delete_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos, int timeout_ms)
+{
+ int res = 0, index = 0, msgid = 0, code = 0;
+ linkkit_gateway_upstream_sync_callback_node_t *node = NULL;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+ void *semaphore = NULL;
+ char *payload = NULL;
+ lite_cjson_item_t *lite_array = NULL, *lite_array_item = NULL;
+
+ if (devid < 0 || extinfos == NULL || nb_extinfos <= 0 || timeout_ms < 0) {
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ lite_array = lite_cjson_create_array();
+ if (lite_array == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ for (index = 0; index < nb_extinfos; index++) {
+ if (extinfos[index].attrKey == NULL || extinfos[index].attrValue == NULL) {
+ lite_cjson_delete(lite_array);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ lite_array_item = lite_cjson_create_object();
+ if (lite_array_item == NULL) {
+ lite_cjson_delete(lite_array);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ lite_cjson_add_string_to_object(lite_array_item, "attrKey", extinfos[index].attrKey);
+ lite_cjson_add_string_to_object(lite_array_item, "attrValue", extinfos[index].attrValue);
+ lite_cjson_add_item_to_array(lite_array, lite_array_item);
+ }
+
+ payload = lite_cjson_print_unformatted(lite_array);
+ if (payload == NULL) {
+ lite_cjson_delete(lite_array);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ lite_cjson_delete(lite_array);
+
+ if (timeout_ms == 0) {
+ res = iotx_dm_deviceinfo_delete(devid, payload, strlen(payload));
+ IMPL_GATEWAY_FREE(payload);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ } else {
+ _linkkit_gateway_mutex_unlock();
+ return SUCCESS_RETURN;
+ }
+ }
+
+ res = iotx_dm_deviceinfo_delete(devid, payload, strlen(payload));
+ if (res < SUCCESS_RETURN) {
+ IMPL_GATEWAY_FREE(payload);
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+ IMPL_GATEWAY_FREE(payload);
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ res = _linkkit_gateway_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, timeout_ms);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_lock();
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_upstream_mutex_lock();
+ code = node->code;
+ _linkkit_gateway_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _linkkit_gateway_upstream_mutex_unlock();
+ _linkkit_gateway_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int linkkit_gateway_get_num_devices(void)
+{
+ int dev_nums = 0;
+ linkkit_gateway_legacy_ctx_t *linkkit_gateway_ctx = _linkkit_gateway_legacy_get_ctx();
+
+ if (linkkit_gateway_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_gateway_mutex_lock();
+ dev_nums = iotx_dm_subdev_number();
+ _linkkit_gateway_mutex_unlock();
+
+ return dev_nums;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_gateway.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_gateway.h
new file mode 100644
index 00000000..c742223f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_gateway.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _LINKKIT_GATEWAY_LEGACY_H_
+#define _LINKKIT_GATEWAY_LEGACY_H_
+
+#include "infra_list.h"
+#include "linkkit_gateway_export.h"
+
+#define LINKKIT_GATEWAY_LEGACY_KEY_ID "id"
+#define LINKKIT_GATEWAY_LEGACY_KEY_CODE "code"
+#define LINKKIT_GATEWAY_LEGACY_KEY_DEVID "devid"
+#define LINKKIT_GATEWAY_LEGACY_KEY_SERVICEID "serviceid"
+#define LINKKIT_GATEWAY_LEGACY_KEY_PROPERTYID "propertyid"
+#define LINKKIT_GATEWAY_LEGACY_KEY_EVENTID "eventid"
+#define LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD "payload"
+#define LINKKIT_GATEWAY_LEGACY_KEY_PRODUCT_KEY "productKey"
+#define LINKKIT_GATEWAY_LEGACY_KEY_TIME "time"
+#define LINKKIT_GATEWAY_LEGACY_KEY_VERSION "version"
+
+#define LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS (10000)
+
+typedef struct {
+ int devid;
+ linkkit_cbs_t *callback;
+ void *callback_ctx;
+ struct list_head linked_list;
+} linkkit_gateway_dev_callback_node_t;
+
+typedef void (*linkkit_gateway_upstream_async_callback)(int retval, void *ctx);
+typedef struct {
+ int msgid;
+ void *semaphore;
+ int code;
+ struct list_head linked_list;
+} linkkit_gateway_upstream_sync_callback_node_t;
+
+typedef struct {
+ int msgid;
+ int timeout_ms;
+ uint64_t timestamp_ms;
+ linkkit_gateway_upstream_async_callback callback;
+ void *callback_ctx;
+ struct list_head linked_list;
+} linkkit_gateway_upstream_async_callback_node_t;
+
+typedef struct {
+ void *mutex;
+ void *upstream_mutex;
+ int is_inited;
+ int is_started;
+ linkkit_params_t init_params;
+ void *dispatch_thread;
+ handle_service_fota_callback_fp_t fota_callback;
+ struct list_head dev_callback_list;
+ struct list_head upstream_sync_callback_list;
+ struct list_head upstream_async_callback_list;
+} linkkit_gateway_legacy_ctx_t;
+
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_linkkit.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_linkkit.c
new file mode 100644
index 00000000..834b7114
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_linkkit.c
@@ -0,0 +1,1671 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_dm_internal.h"
+
+#if defined(DEVICE_MODEL_ENABLED) && !defined(DEPRECATED_LINKKIT)
+#include "dev_model_api.h"
+
+#ifdef LOG_REPORT_TO_CLOUD
+ #include "iotx_log_report.h"
+#endif
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define IMPL_LINKKIT_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "impl.linkkit")
+ #define IMPL_LINKKIT_FREE(ptr) LITE_free(ptr)
+#else
+ #define IMPL_LINKKIT_MALLOC(size) HAL_Malloc(size)
+ #define IMPL_LINKKIT_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#ifdef DEV_BIND_ENABLED
+ #include "dev_bind_api.h"
+#endif
+
+void HAL_Reboot();
+
+#define IOTX_LINKKIT_KEY_ID "id"
+#define IOTX_LINKKIT_KEY_CODE "code"
+#define IOTX_LINKKIT_KEY_DEVID "devid"
+#define IOTX_LINKKIT_KEY_SERVICEID "serviceid"
+#define IOTX_LINKKIT_KEY_PROPERTYID "propertyid"
+#define IOTX_LINKKIT_KEY_EVENTID "eventid"
+#define IOTX_LINKKIT_KEY_PAYLOAD "payload"
+#define IOTX_LINKKIT_KEY_CONFIG_ID "configId"
+#define IOTX_LINKKIT_KEY_CONFIG_SIZE "configSize"
+#define IOTX_LINKKIT_KEY_GET_TYPE "getType"
+#define IOTX_LINKKIT_KEY_SIGN "sign"
+#define IOTX_LINKKIT_KEY_SIGN_METHOD "signMethod"
+#define IOTX_LINKKIT_KEY_URL "url"
+#define IOTX_LINKKIT_KEY_VERSION "version"
+#define IOTX_LINKKIT_KEY_UTC "utc"
+#define IOTX_LINKKIT_KEY_RRPCID "rrpcid"
+#define IOTX_LINKKIT_KEY_CTX "ctx"
+#define IOTX_LINKKIT_KEY_TOPO "topo"
+#define IOTX_LINKKIT_KEY_PRODUCT_KEY "productKey"
+#define IOTX_LINKKIT_KEY_TIME "time"
+#define IOTX_LINKKIT_KEY_DATA "data"
+
+#define IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS 10000
+
+typedef struct {
+ int msgid;
+ void *semaphore;
+ int code;
+ struct list_head linked_list;
+} iotx_linkkit_upstream_sync_callback_node_t;
+
+typedef struct {
+ void *mutex;
+ void *upstream_mutex;
+ int is_opened;
+ int is_connected;
+ int cloud_redirect;
+ struct list_head upstream_sync_callback_list;
+} iotx_linkkit_ctx_t;
+
+static iotx_linkkit_ctx_t g_iotx_linkkit_ctx = {0};
+
+static iotx_linkkit_ctx_t *_iotx_linkkit_get_ctx(void)
+{
+ return &g_iotx_linkkit_ctx;
+}
+
+static void _iotx_linkkit_mutex_lock(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexLock(ctx->mutex);
+ }
+}
+
+static void _iotx_linkkit_mutex_unlock(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ if (ctx->mutex) {
+ HAL_MutexUnlock(ctx->mutex);
+ }
+}
+
+static int _impl_copy(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
+{
+ if (input == NULL || output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *output = IMPL_LINKKIT_MALLOC(output_len);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, output_len);
+ memcpy(*output, input, input_len);
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+static void _iotx_linkkit_upstream_mutex_lock(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ if (ctx->upstream_mutex) {
+ HAL_MutexLock(ctx->upstream_mutex);
+ }
+}
+
+static void _iotx_linkkit_upstream_mutex_unlock(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ if (ctx->upstream_mutex) {
+ HAL_MutexUnlock(ctx->upstream_mutex);
+ }
+}
+
+
+static int _iotx_linkkit_upstream_sync_callback_list_insert(int msgid, void *semaphore,
+ iotx_linkkit_upstream_sync_callback_node_t **node)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &ctx->upstream_sync_callback_list, linked_list,
+ iotx_linkkit_upstream_sync_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ dm_log_debug("Message Already Exist: %d", msgid);
+ return FAIL_RETURN;
+ }
+ }
+
+ search_node = IMPL_LINKKIT_MALLOC(sizeof(iotx_linkkit_upstream_sync_callback_node_t));
+ if (search_node == NULL) {
+ dm_log_debug("malloc error");
+ return FAIL_RETURN;
+ }
+ memset(search_node, 0, sizeof(iotx_linkkit_upstream_sync_callback_node_t));
+ search_node->msgid = msgid;
+ search_node->semaphore = semaphore;
+ INIT_LIST_HEAD(&search_node->linked_list);
+
+ list_add(&search_node->linked_list, &ctx->upstream_sync_callback_list);
+ dm_log_debug("New Message, msgid: %d", msgid);
+
+ *node = search_node;
+ return SUCCESS_RETURN;
+}
+
+static int _iotx_linkkit_upstream_sync_callback_list_remove(int msgid)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &ctx->upstream_sync_callback_list, linked_list,
+ iotx_linkkit_upstream_sync_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ dm_log_debug("Message Found: %d, Delete It", msgid);
+ HAL_SemaphoreDestroy(search_node->semaphore);
+ list_del(&search_node->linked_list);
+ IMPL_LINKKIT_FREE(search_node);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _iotx_linkkit_upstream_sync_callback_list_search(int msgid,
+ iotx_linkkit_upstream_sync_callback_node_t **node)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL;
+
+ if (node == NULL || *node != NULL) {
+ dm_log_debug("invalid param");
+ return FAIL_RETURN;
+ }
+
+ list_for_each_entry(search_node, &ctx->upstream_sync_callback_list, linked_list,
+ iotx_linkkit_upstream_sync_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ dm_log_debug("Sync Message Found: %d", msgid);
+ *node = search_node;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static void _iotx_linkkit_upstream_sync_callback_list_destroy(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_linkkit_upstream_sync_callback_node_t *search_node = NULL, *next_node = NULL;
+
+ list_for_each_entry_safe(search_node, next_node, &ctx->upstream_sync_callback_list, linked_list,
+ iotx_linkkit_upstream_sync_callback_node_t) {
+ list_del(&search_node->linked_list);
+ HAL_SemaphoreDestroy(search_node->semaphore);
+ IMPL_LINKKIT_FREE(search_node);
+ }
+}
+
+
+static void _iotx_linkkit_upstream_callback_remove(int msgid, int code)
+{
+ int res = 0;
+ iotx_linkkit_upstream_sync_callback_node_t *sync_node = NULL;
+ res = _iotx_linkkit_upstream_sync_callback_list_search(msgid, &sync_node);
+ if (res == SUCCESS_RETURN) {
+ sync_node->code = (code == IOTX_DM_ERR_CODE_SUCCESS) ? (SUCCESS_RETURN) : (FAIL_RETURN);
+ dm_log_debug("Sync Message %d Result: %d", msgid, sync_node->code);
+ HAL_SemaphorePost(sync_node->semaphore);
+ }
+}
+#endif
+
+#ifdef LOG_REPORT_TO_CLOUD
+ int report_sample = 0;
+#endif
+#ifdef ALCS_ENABLED
+ extern void dm_server_free_context(_IN_ void *ctx);
+#endif
+
+static void _iotx_linkkit_event_callback(iotx_dm_event_types_t type, char *payload)
+{
+ int res = 0;
+ void *callback;
+#ifdef LOG_REPORT_TO_CLOUD
+ lite_cjson_t msg_id;
+#endif
+ lite_cjson_t lite, lite_item_id, lite_item_devid, lite_item_serviceid, lite_item_payload, lite_item_ctx;
+ lite_cjson_t lite_item_code, lite_item_eventid, lite_item_utc, lite_item_rrpcid, lite_item_topo;
+ lite_cjson_t lite_item_pk, lite_item_time;
+ lite_cjson_t lite_item_version, lite_item_configid, lite_item_configsize, lite_item_gettype, lite_item_sign,
+ lite_item_signmethod, lite_item_url;
+
+ dm_log_info("Receive Message Type: %d", type);
+ if (payload) {
+ dm_log_info("Receive Message: %s", payload);
+ res = dm_utils_json_parse(payload, strlen(payload), cJSON_Invalid, &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+#ifdef LOG_REPORT_TO_CLOUD
+ dm_utils_json_object_item(&lite, "msgid", 5, cJSON_Invalid, &msg_id);
+#endif
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_ID, strlen(IOTX_LINKKIT_KEY_ID), cJSON_Invalid, &lite_item_id);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_DEVID, strlen(IOTX_LINKKIT_KEY_DEVID), cJSON_Invalid,
+ &lite_item_devid);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_SERVICEID, strlen(IOTX_LINKKIT_KEY_SERVICEID), cJSON_Invalid,
+ &lite_item_serviceid);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_PAYLOAD, strlen(IOTX_LINKKIT_KEY_PAYLOAD), cJSON_Invalid,
+ &lite_item_payload);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_CTX, strlen(IOTX_LINKKIT_KEY_CTX), cJSON_Invalid, &lite_item_ctx);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_CODE, strlen(IOTX_LINKKIT_KEY_CODE), cJSON_Invalid, &lite_item_code);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_EVENTID, strlen(IOTX_LINKKIT_KEY_EVENTID), cJSON_Invalid,
+ &lite_item_eventid);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_UTC, strlen(IOTX_LINKKIT_KEY_UTC), cJSON_Invalid, &lite_item_utc);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_RRPCID, strlen(IOTX_LINKKIT_KEY_RRPCID), cJSON_Invalid,
+ &lite_item_rrpcid);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_TOPO, strlen(IOTX_LINKKIT_KEY_TOPO), cJSON_Invalid,
+ &lite_item_topo);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_PRODUCT_KEY, strlen(IOTX_LINKKIT_KEY_PRODUCT_KEY), cJSON_Invalid,
+ &lite_item_pk);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_TIME, strlen(IOTX_LINKKIT_KEY_TIME), cJSON_Invalid,
+ &lite_item_time);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_VERSION, strlen(IOTX_LINKKIT_KEY_VERSION), cJSON_Invalid,
+ &lite_item_version);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_CONFIG_ID, strlen(IOTX_LINKKIT_KEY_CONFIG_ID), cJSON_Invalid,
+ &lite_item_configid);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_CONFIG_SIZE, strlen(IOTX_LINKKIT_KEY_CONFIG_SIZE), cJSON_Invalid,
+ &lite_item_configsize);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_GET_TYPE, strlen(IOTX_LINKKIT_KEY_GET_TYPE), cJSON_Invalid,
+ &lite_item_gettype);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_SIGN, strlen(IOTX_LINKKIT_KEY_SIGN), cJSON_Invalid,
+ &lite_item_sign);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_SIGN_METHOD, strlen(IOTX_LINKKIT_KEY_SIGN_METHOD), cJSON_Invalid,
+ &lite_item_signmethod);
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_URL, strlen(IOTX_LINKKIT_KEY_URL), cJSON_Invalid,
+ &lite_item_url);
+
+ }
+
+ switch (type) {
+ case IOTX_DM_EVENT_CLOUD_CONNECTED: {
+ callback = iotx_event_callback(ITE_CONNECT_SUCC);
+ if (callback) {
+ ((int (*)(void))callback)();
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_CLOUD_DISCONNECT: {
+ callback = iotx_event_callback(ITE_DISCONNECTED);
+ if (callback) {
+ ((int (*)(void))callback)();
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_INITIALIZED: {
+ if (payload == NULL || lite_item_devid.type != cJSON_Number) {
+ return;
+ }
+
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ callback = iotx_event_callback(ITE_INITIALIZE_COMPLETED);
+ if (callback) {
+ ((int (*)(const int))callback)(lite_item_devid.value_int);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_MODEL_DOWN_RAW: {
+ int raw_data_len = 0;
+ unsigned char *raw_data = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number || lite_item_payload.type != cJSON_String) {
+ return;
+ }
+
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current Raw Data: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+
+ raw_data_len = lite_item_payload.value_length / 2;
+ raw_data = IMPL_LINKKIT_MALLOC(raw_data_len);
+ if (raw_data == NULL) {
+ dm_log_err("No Enough Memory");
+ return;
+ }
+ LITE_hexstr_convert(lite_item_payload.value, lite_item_payload.value_length, raw_data, raw_data_len);
+
+ HEXDUMP_DEBUG(raw_data, raw_data_len);
+ callback = iotx_event_callback(ITE_RAWDATA_ARRIVED);
+ if (callback) {
+ ((int (*)(const int, const unsigned char *, const int))callback)(lite_item_devid.value_int, raw_data, raw_data_len);
+ }
+
+ IMPL_LINKKIT_FREE(raw_data);
+ }
+ break;
+ case IOTX_DM_EVENT_MODEL_UP_RAW_REPLY: {
+ int raw_data_len = 0;
+ unsigned char *raw_data = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number || lite_item_payload.type != cJSON_String) {
+ return;
+ }
+
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current Raw Data: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+
+ raw_data_len = lite_item_payload.value_length / 2;
+ raw_data = IMPL_LINKKIT_MALLOC(raw_data_len);
+ if (raw_data == NULL) {
+ dm_log_err("No Enough Memory");
+ return;
+ }
+ memset(raw_data, 0, raw_data_len);
+ LITE_hexstr_convert(lite_item_payload.value, lite_item_payload.value_length, raw_data, raw_data_len);
+
+ HEXDUMP_DEBUG(raw_data, raw_data_len);
+
+ callback = iotx_event_callback(ITE_RAWDATA_ARRIVED);
+ if (callback) {
+ ((int (*)(const int, const unsigned char *, const int))callback)(lite_item_devid.value_int, raw_data, raw_data_len);
+ }
+
+ IMPL_LINKKIT_FREE(raw_data);
+ }
+ break;
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ case IOTX_DM_EVENT_THING_SERVICE_REQUEST: {
+ int response_len = 0;
+ char *request = NULL, *response = NULL;
+
+ uintptr_t property_get_ctx_num = 0;
+ void *property_get_ctx = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_String || lite_item_devid.type != cJSON_Number ||
+ lite_item_serviceid.type != cJSON_String || lite_item_payload.type != cJSON_Object) {
+ return;
+ }
+
+ dm_log_debug("Current Id: %.*s", lite_item_id.value_length, lite_item_id.value);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current ServiceID: %.*s", lite_item_serviceid.value_length, lite_item_serviceid.value);
+ dm_log_debug("Current Payload: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+ dm_log_debug("Current Ctx: %.*s", lite_item_ctx.value_length, lite_item_ctx.value);
+
+ LITE_hexstr_convert(lite_item_ctx.value, lite_item_ctx.value_length, (unsigned char *)&property_get_ctx_num,
+ sizeof(uintptr_t));
+ property_get_ctx = (void *)property_get_ctx_num;
+
+ request = IMPL_LINKKIT_MALLOC(lite_item_payload.value_length + 1);
+ if (request == NULL) {
+ dm_log_err("Not Enough Memory");
+ return;
+ }
+ memset(request, 0, lite_item_payload.value_length + 1);
+ memcpy(request, lite_item_payload.value, lite_item_payload.value_length);
+
+ callback = iotx_event_callback(ITE_SERVICE_REQUEST);
+ if (callback) {
+ res = ((int (*)(const int, const char *, const int, const char *, const int, char **,
+ int *))callback)(lite_item_devid.value_int, lite_item_serviceid.value,
+ lite_item_serviceid.value_length, request, lite_item_payload.value_length, &response, &response_len);
+ if (response != NULL && response_len > 0) {
+ /* service response exist */
+ iotx_dm_error_code_t code = (res == 0) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+ iotx_dm_send_service_response(lite_item_devid.value_int, lite_item_id.value, lite_item_id.value_length, code,
+ lite_item_serviceid.value,
+ lite_item_serviceid.value_length,
+ response, response_len, property_get_ctx);
+ HAL_Free(response);
+ }
+ }
+#ifdef ALCS_ENABLED
+ if (property_get_ctx) {
+ dm_server_free_context(property_get_ctx);
+ }
+#endif
+ IMPL_LINKKIT_FREE(request);
+ }
+ break;
+ case IOTX_DM_EVENT_PROPERTY_SET: {
+ char *property_payload = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number || lite_item_payload.type != cJSON_Object) {
+ return;
+ }
+
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current Payload: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+
+ property_payload = IMPL_LINKKIT_MALLOC(lite_item_payload.value_length + 1);
+ if (property_payload == NULL) {
+ dm_log_err("No Enough Memory");
+ return;
+ }
+ memset(property_payload, 0, lite_item_payload.value_length + 1);
+ memcpy(property_payload, lite_item_payload.value, lite_item_payload.value_length);
+#ifdef LOG_REPORT_TO_CLOUD
+ if (SUCCESS_RETURN == check_target_msg(msg_id.value, msg_id.value_length)) {
+ report_sample = 1;
+ send_permance_info(msg_id.value, msg_id.value_length, "3", 1);
+ }
+#endif
+ callback = iotx_event_callback(ITE_PROPERTY_SET);
+ if (callback) {
+ ((int (*)(const int, const char *, const int))callback)(lite_item_devid.value_int, property_payload,
+ lite_item_payload.value_length);
+ }
+#ifdef LOG_REPORT_TO_CLOUD
+ if (1 == report_sample) {
+ send_permance_info(NULL, 0, "5", 2);
+ report_sample = 0;
+ }
+#endif
+
+ IMPL_LINKKIT_FREE(property_payload);
+ }
+ break;
+#ifdef DEVICE_MODEL_SHADOW
+ case IOTX_DM_EVENT_PROPERTY_DESIRED_GET_REPLY: {
+ char *property_data = NULL;
+ lite_cjson_t lite_item_data;
+
+ memset(&lite_item_data, 0, sizeof(lite_cjson_t));
+ dm_utils_json_object_item(&lite, IOTX_LINKKIT_KEY_DATA, strlen(IOTX_LINKKIT_KEY_DATA), cJSON_Invalid,
+ &lite_item_data);
+ if (payload == NULL || lite_item_data.type != cJSON_Object) {
+ return;
+ }
+ dm_log_debug("Current Data: %.*s", lite_item_data.value_length, lite_item_data.value);
+
+ property_data = IMPL_LINKKIT_MALLOC(lite_item_data.value_length + 1);
+ if (property_data == NULL) {
+ dm_log_err("No Enough Memory");
+ return;
+ }
+ memset(property_data, 0, lite_item_data.value_length + 1);
+ memcpy(property_data, lite_item_data.value, lite_item_data.value_length);
+
+ callback = iotx_event_callback(ITE_PROPERTY_DESIRED_GET_REPLY);
+ if (callback) {
+ ((int (*)(const char *, const int))callback)(property_data,
+ lite_item_data.value_length);
+ }
+
+ IMPL_LINKKIT_FREE(property_data);
+ }
+ break;
+#endif
+ case IOTX_DM_EVENT_PROPERTY_GET: {
+ int response_len = 0;
+ char *request = NULL, *response = NULL;
+ uintptr_t property_get_ctx_num = 0;
+ void *property_get_ctx = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_String || lite_item_devid.type != cJSON_Number ||
+ lite_item_payload.type != cJSON_Array) {
+ return;
+ }
+
+ dm_log_debug("Current Id: %.*s", lite_item_id.value_length, lite_item_id.value);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current Payload: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+ dm_log_debug("Current Ctx: %.*s", lite_item_ctx.value_length, lite_item_ctx.value);
+
+ LITE_hexstr_convert(lite_item_ctx.value, lite_item_ctx.value_length, (unsigned char *)&property_get_ctx_num,
+ sizeof(uintptr_t));
+ property_get_ctx = (void *)property_get_ctx_num;
+ dm_log_debug("property_get_ctx_num: %0x016llX", (unsigned int)property_get_ctx_num);
+ dm_log_debug("property_get_ctx: %p", property_get_ctx);
+
+ request = IMPL_LINKKIT_MALLOC(lite_item_payload.value_length + 1);
+ if (request == NULL) {
+ dm_log_err("No Enough Memory");
+ return;
+ }
+ memset(request, 0, lite_item_payload.value_length + 1);
+ memcpy(request, lite_item_payload.value, lite_item_payload.value_length);
+
+ callback = iotx_event_callback(ITE_PROPERTY_GET);
+ if (callback) {
+ res = ((int (*)(const int, const char *, const int, char **, int *))callback)(lite_item_devid.value_int, request,
+ lite_item_payload.value_length, &response, &response_len);
+
+ if (response != NULL && response_len > 0) {
+ /* property get response exist */
+ iotx_dm_error_code_t code = (res == 0) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+ iotx_dm_send_property_get_response(lite_item_devid.value_int, lite_item_id.value, lite_item_id.value_length, code,
+ response, response_len, property_get_ctx);
+ HAL_Free(response);
+ }
+ }
+
+ IMPL_LINKKIT_FREE(request);
+ }
+ break;
+ case IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY:
+ case IOTX_DM_EVENT_DEVICEINFO_UPDATE_REPLY:
+#ifdef DEVICE_MODEL_SHADOW
+ case IOTX_DM_EVENT_PROPERTY_DESIRED_DELETE_REPLY:
+#endif
+ case IOTX_DM_EVENT_DEVICEINFO_DELETE_REPLY: {
+ char *user_payload = NULL;
+ int user_payload_length = 0;
+
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_code.type != cJSON_Number
+ || lite_item_devid.type != cJSON_Number) {
+ return;
+ }
+ dm_log_debug("Current Id: %d", lite_item_id.value_int);
+ dm_log_debug("Current Code: %d", lite_item_code.value_int);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ if (lite_item_payload.type == cJSON_Object && lite_item_payload.value_length > 0) {
+ user_payload = IMPL_LINKKIT_MALLOC(lite_item_payload.value_length + 1);
+ if (user_payload == NULL) {
+ dm_log_err("No Enough Memory");
+ return;
+ }
+ memset(user_payload, 0, lite_item_payload.value_length + 1);
+ memcpy(user_payload, lite_item_payload.value, lite_item_payload.value_length);
+ user_payload_length = lite_item_payload.value_length;
+ }
+
+ callback = iotx_event_callback(ITE_REPORT_REPLY);
+ if (callback) {
+ ((int (*)(const int, const int, const int, const char *, const int))callback)(lite_item_devid.value_int,
+ lite_item_id.value_int, lite_item_code.value_int, user_payload,
+ user_payload_length);
+ }
+
+ if (user_payload) {
+ IMPL_LINKKIT_FREE(user_payload);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_EVENT_SPECIFIC_POST_REPLY: {
+ char *user_eventid = NULL;
+ char *user_payload = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_code.type != cJSON_Number ||
+ lite_item_devid.type != cJSON_Number || lite_item_eventid.type != cJSON_String
+ || lite_item_payload.type != cJSON_String) {
+ return;
+ }
+
+ dm_log_debug("Current Id: %d", lite_item_id.value_int);
+ dm_log_debug("Current Code: %d", lite_item_code.value_int);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current EventID: %.*s", lite_item_eventid.value_length, lite_item_eventid.value);
+ dm_log_debug("Current Message: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+
+ user_eventid = IMPL_LINKKIT_MALLOC(lite_item_eventid.value_length + 1);
+ if (user_eventid == NULL) {
+ dm_log_err("Not Enough Memory");
+ return;
+ }
+ memset(user_eventid, 0, lite_item_eventid.value_length + 1);
+ memcpy(user_eventid, lite_item_eventid.value, lite_item_eventid.value_length);
+
+ user_payload = IMPL_LINKKIT_MALLOC(lite_item_payload.value_length + 1);
+ if (user_payload == NULL) {
+ dm_log_err("Not Enough Memory");
+ IMPL_LINKKIT_FREE(user_eventid);
+ return;
+ }
+ memset(user_payload, 0, lite_item_payload.value_length + 1);
+ memcpy(user_payload, lite_item_payload.value, lite_item_payload.value_length);
+
+
+ callback = iotx_event_callback(ITE_TRIGGER_EVENT_REPLY);
+ if (callback) {
+ ((int (*)(const int, const int, const int, const char *, const int, const char *,
+ const int))callback)(lite_item_devid.value_int,
+ lite_item_id.value_int, lite_item_code.value_int,
+ user_eventid, lite_item_eventid.value_length, user_payload, lite_item_payload.value_length);
+ }
+
+ IMPL_LINKKIT_FREE(user_eventid);
+ IMPL_LINKKIT_FREE(user_payload);
+ }
+ break;
+ case IOTX_DM_EVENT_NTP_RESPONSE: {
+ char *utc_payload = NULL;
+
+ if (payload == NULL || lite_item_utc.type != cJSON_String) {
+ return;
+ }
+
+ dm_log_debug("Current UTC: %.*s", lite_item_utc.value_length, lite_item_utc.value);
+
+ utc_payload = IMPL_LINKKIT_MALLOC(lite_item_utc.value_length + 1);
+ if (utc_payload == NULL) {
+ dm_log_err("Not Enough Memory");
+ return;
+ }
+ memset(utc_payload, 0, lite_item_utc.value_length + 1);
+ memcpy(utc_payload, lite_item_utc.value, lite_item_utc.value_length);
+
+ callback = iotx_event_callback(ITE_TIMESTAMP_REPLY);
+ if (callback) {
+ ((int (*)(const char *))callback)(utc_payload);
+ }
+
+ IMPL_LINKKIT_FREE(utc_payload);
+ }
+ break;
+ case IOTX_DM_EVENT_RRPC_REQUEST: {
+ int rrpc_response_len = 0;
+ char *rrpc_request = NULL, *rrpc_response = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_String || lite_item_devid.type != cJSON_Number ||
+ lite_item_serviceid.type != cJSON_String || lite_item_rrpcid.type != cJSON_String
+ || lite_item_payload.type != cJSON_Object) {
+ return;
+ }
+
+ dm_log_debug("Current Id: %.*s", lite_item_id.value_length, lite_item_id.value);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current ServiceID: %.*s", lite_item_serviceid.value_length, lite_item_serviceid.value);
+ dm_log_debug("Current RRPC ID: %.*s", lite_item_rrpcid.value_length, lite_item_rrpcid.value);
+ dm_log_debug("Current Payload: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+
+ rrpc_request = IMPL_LINKKIT_MALLOC(lite_item_payload.value_length + 1);
+ if (rrpc_request == NULL) {
+ dm_log_err("Not Enough Memory");
+ return;
+ }
+ memset(rrpc_request, 0, lite_item_payload.value_length + 1);
+ memcpy(rrpc_request, lite_item_payload.value, lite_item_payload.value_length);
+
+ callback = iotx_event_callback(ITE_SERVICE_REQUEST);
+ if (callback) {
+ res = ((int (*)(const int, const char *, const int, const char *, const int, char **,
+ int *))callback)(lite_item_devid.value_int, lite_item_serviceid.value,
+ lite_item_serviceid.value_length,
+ rrpc_request, lite_item_payload.value_length, &rrpc_response, &rrpc_response_len);
+ if (rrpc_response != NULL && rrpc_response_len > 0) {
+ iotx_dm_error_code_t code = (res == 0) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
+ iotx_dm_send_rrpc_response(lite_item_devid.value_int, lite_item_id.value, lite_item_id.value_length, code,
+ lite_item_rrpcid.value,
+ lite_item_rrpcid.value_length,
+ rrpc_response, rrpc_response_len);
+ HAL_Free(rrpc_response);
+ }
+ }
+
+ IMPL_LINKKIT_FREE(rrpc_request);
+ }
+ break;
+#endif
+ case IOTX_DM_EVENT_FOTA_NEW_FIRMWARE: {
+ char *version = NULL;
+
+ if (payload == NULL || lite_item_version.type != cJSON_String) {
+ return;
+ }
+
+ dm_log_debug("Current Firmware Version: %.*s", lite_item_version.value_length, lite_item_version.value);
+
+ version = IMPL_LINKKIT_MALLOC(lite_item_version.value_length + 1);
+ if (version == NULL) {
+ return;
+ }
+ memset(version, 0, lite_item_version.value_length + 1);
+ memcpy(version, lite_item_version.value, lite_item_version.value_length);
+
+ callback = iotx_event_callback(ITE_FOTA);
+ if (callback) {
+ ((int (*)(const int, const char *))callback)(0, version);
+ }
+
+ if (version) {
+ IMPL_LINKKIT_FREE(version);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_COTA_NEW_CONFIG: {
+ char *config_id = NULL, *get_type = NULL, *sign = NULL, *sign_method = NULL, *url = NULL;
+
+ if (payload == NULL || lite_item_configid.type != cJSON_String || lite_item_configsize.type != cJSON_Number ||
+ lite_item_gettype.type != cJSON_String || lite_item_sign.type != cJSON_String
+ || lite_item_signmethod.type != cJSON_String ||
+ lite_item_url.type != cJSON_String) {
+ return;
+ }
+
+ dm_log_debug("Current Config ID: %.*s", lite_item_configid.value_length, lite_item_configid.value);
+ dm_log_debug("Current Config Size: %d", lite_item_configsize.value_int);
+ dm_log_debug("Current Get Type: %.*s", lite_item_gettype.value_length, lite_item_gettype.value);
+ dm_log_debug("Current Sign: %.*s", lite_item_sign.value_length, lite_item_sign.value);
+ dm_log_debug("Current Sign Method: %.*s", lite_item_signmethod.value_length, lite_item_signmethod.value);
+ dm_log_debug("Current URL: %.*s", lite_item_url.value_length, lite_item_url.value);
+
+ _impl_copy(lite_item_configid.value, lite_item_configid.value_length, (void **)&config_id,
+ lite_item_configid.value_length + 1);
+ _impl_copy(lite_item_gettype.value, lite_item_gettype.value_length, (void **)&get_type,
+ lite_item_gettype.value_length + 1);
+ _impl_copy(lite_item_sign.value, lite_item_sign.value_length, (void **)&sign, lite_item_sign.value_length + 1);
+ _impl_copy(lite_item_signmethod.value, lite_item_signmethod.value_length, (void **)&sign_method,
+ lite_item_signmethod.value_length + 1);
+ _impl_copy(lite_item_url.value, lite_item_url.value_length, (void **)&url, lite_item_url.value_length + 1);
+
+ if (config_id == NULL || get_type == NULL || sign == NULL || sign_method == NULL || url == NULL) {
+ if (config_id) {
+ IMPL_LINKKIT_FREE(config_id);
+ }
+ if (get_type) {
+ IMPL_LINKKIT_FREE(get_type);
+ }
+ if (sign) {
+ IMPL_LINKKIT_FREE(sign);
+ }
+ if (sign_method) {
+ IMPL_LINKKIT_FREE(sign_method);
+ }
+ if (url) {
+ IMPL_LINKKIT_FREE(url);
+ }
+ return;
+ }
+
+ callback = iotx_event_callback(ITE_COTA);
+ if (callback) {
+ ((int (*)(const int, const char *, int, const char *, const char *, const char *, const char *))callback)(0, config_id,
+ lite_item_configsize.value_int, get_type, sign, sign_method, url);
+ }
+
+ if (config_id) {
+ IMPL_LINKKIT_FREE(config_id);
+ }
+ if (get_type) {
+ IMPL_LINKKIT_FREE(get_type);
+ }
+ if (sign) {
+ IMPL_LINKKIT_FREE(sign);
+ }
+ if (sign_method) {
+ IMPL_LINKKIT_FREE(sign_method);
+ }
+ if (url) {
+ IMPL_LINKKIT_FREE(url);
+ }
+ }
+ break;
+#ifdef DEVICE_MODEL_GATEWAY
+ case IOTX_DM_EVENT_TOPO_GET_REPLY: {
+ char *topo_list = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_devid.type != cJSON_Number ||
+ lite_item_code.type != cJSON_Number || lite_item_topo.type != cJSON_Array) {
+ return;
+ }
+ dm_log_debug("Current Id: %d", lite_item_id.value_int);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+ dm_log_debug("Current Code: %d", lite_item_code.value_int);
+ dm_log_debug("Current Topo List: %.*s", lite_item_topo.value_length, lite_item_topo.value);
+
+ topo_list = IMPL_LINKKIT_MALLOC(lite_item_topo.value_length + 1);
+ if (topo_list == NULL) {
+ dm_log_err("Not Enough Memory");
+ return;
+ }
+ memset(topo_list, 0, lite_item_topo.value_length + 1);
+ memcpy(topo_list, lite_item_topo.value, lite_item_topo.value_length);
+
+ callback = iotx_event_callback(ITE_TOPOLIST_REPLY);
+ if (callback) {
+ ((int (*)(const int, const int, const int, const char *, const int))callback)(lite_item_devid.value_int,
+ lite_item_id.value_int,
+ lite_item_code.value_int, topo_list, lite_item_topo.value_length);
+ }
+
+ IMPL_LINKKIT_FREE(topo_list);
+ }
+ break;
+ case IOTX_DM_EVENT_TOPO_DELETE_REPLY:
+ case IOTX_DM_EVENT_TOPO_ADD_REPLY:
+ case IOTX_DM_EVENT_SUBDEV_REGISTER_REPLY:
+ case IOTX_DM_EVENT_COMBINE_LOGIN_REPLY:
+ case IOTX_DM_EVENT_COMBINE_LOGOUT_REPLY: {
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_devid.type != cJSON_Number ||
+ lite_item_code.type != cJSON_Number) {
+ return;
+ }
+ dm_log_debug("Current Id: %d", lite_item_id.value_int);
+ dm_log_debug("Current Code: %d", lite_item_code.value_int);
+ dm_log_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ _iotx_linkkit_upstream_mutex_lock();
+ _iotx_linkkit_upstream_callback_remove(lite_item_id.value_int, lite_item_code.value_int);
+ _iotx_linkkit_upstream_mutex_unlock();
+ }
+ break;
+ case IOTX_DM_EVENT_GATEWAY_PERMIT: {
+ char *product_key = "";
+
+ if (payload == NULL || lite_item_time.type != cJSON_Number) {
+ return;
+ }
+ dm_log_debug("Current Time: %d", lite_item_time.value_int);
+
+ if (lite_item_pk.type == cJSON_String) {
+ dm_log_debug("Current Product Key: %.*s", lite_item_pk.value_length, lite_item_pk.value);
+ product_key = IMPL_LINKKIT_MALLOC(lite_item_pk.value_length + 1);
+ if (product_key == NULL) {
+ dm_log_err("Not Enough Memory");
+ return;
+ }
+ memset(product_key, 0, lite_item_pk.value_length + 1);
+ memcpy(product_key, lite_item_pk.value, lite_item_pk.value_length);
+ }
+
+ callback = iotx_event_callback(ITE_PERMIT_JOIN);
+ if (callback) {
+ ((int (*)(const char *, int))callback)((const char *)product_key, (const int)lite_item_time.value_int);
+ }
+
+ if (lite_item_pk.type == cJSON_String) {
+ IMPL_LINKKIT_FREE(product_key);
+ }
+ }
+ break;
+#endif
+ default: {
+ }
+ break;
+ }
+}
+
+static int _iotx_linkkit_master_open(iotx_linkkit_dev_meta_info_t *meta_info)
+{
+ int res = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (ctx->is_opened) {
+ return FAIL_RETURN;
+ }
+ ctx->is_opened = 1;
+
+ /* Create Mutex */
+ ctx->mutex = HAL_MutexCreate();
+ if (ctx->mutex == NULL) {
+ dm_log_err("Not Enough Memory");
+ ctx->is_opened = 0;
+ return FAIL_RETURN;
+ }
+
+#ifdef DEVICE_MODEL_GATEWAY
+ ctx->upstream_mutex = HAL_MutexCreate();
+ if (ctx->upstream_mutex == NULL) {
+ HAL_MutexDestroy(ctx->mutex);
+ dm_log_err("Not Enough Memory");
+ ctx->is_opened = 0;
+ return FAIL_RETURN;
+ }
+#endif
+
+ res = iotx_dm_open();
+ if (res != SUCCESS_RETURN) {
+#ifdef DEVICE_MODEL_GATEWAY
+ HAL_MutexDestroy(ctx->upstream_mutex);
+#endif
+ HAL_MutexDestroy(ctx->mutex);
+ ctx->is_opened = 0;
+ return FAIL_RETURN;
+ }
+
+ INIT_LIST_HEAD(&ctx->upstream_sync_callback_list);
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+static int _iotx_linkkit_slave_open(iotx_linkkit_dev_meta_info_t *meta_info)
+{
+ int res = 0, devid;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (!ctx->is_opened) {
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_subdev_create(meta_info->product_key, meta_info->device_name, meta_info->device_secret, &devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ return devid;
+}
+#endif
+
+static int _iotx_linkkit_master_connect(void)
+{
+ int res = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_dm_init_params_t dm_init_params;
+ iotx_dm_event_types_t type;
+
+ if (ctx->is_connected) {
+ return FAIL_RETURN;
+ }
+ ctx->is_connected = 1;
+
+ memset(&dm_init_params, 0, sizeof(iotx_dm_init_params_t));
+ dm_init_params.event_callback = _iotx_linkkit_event_callback;
+
+ res = iotx_dm_connect(&dm_init_params);
+ if (res != SUCCESS_RETURN) {
+ dm_log_err("DM Start Failed");
+ ctx->is_connected = 0;
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_subscribe(IOTX_DM_LOCAL_NODE_DEVID);
+ if (res != SUCCESS_RETURN) {
+ dm_log_err("DM Subscribe Failed");
+ ctx->is_connected = 0;
+ return FAIL_RETURN;
+ }
+
+ type = IOTX_DM_EVENT_INITIALIZED;
+ _iotx_linkkit_event_callback(type, "{\"devid\":0}");
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+static int _iotx_linkkit_slave_connect(int devid)
+{
+ int res = 0, msgid = 0, code = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
+ void *semaphore = NULL;
+
+ if (ctx->is_connected == 0) {
+ dm_log_err("master isn't start");
+ return FAIL_RETURN;
+ }
+
+ if (devid <= 0) {
+ dm_log_err("devid invalid");
+ return FAIL_RETURN;
+ }
+
+ /* Subdev Register */
+ res = iotx_dm_subdev_register(devid);
+ if (res < SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ if (res > SUCCESS_RETURN) {
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ return FAIL_RETURN;
+ }
+
+ msgid = res;
+
+ _iotx_linkkit_upstream_mutex_lock();
+ res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_lock();
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ code = node->code;
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+ }
+
+ /* Subdev Add Topo */
+ res = iotx_dm_subdev_topo_add(devid);
+ if (res < SUCCESS_RETURN) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ msgid = res;
+ _iotx_linkkit_upstream_mutex_lock();
+ res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_lock();
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ code = node->code;
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+static int _iotx_linkkit_subdev_delete_topo(int devid)
+{
+ int res = 0, msgid = 0, code = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+ iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
+ void *semaphore = NULL;
+
+ if (ctx->is_connected == 0) {
+ dm_log_err("master isn't start");
+ return FAIL_RETURN;
+ }
+
+ if (devid <= 0) {
+ dm_log_err("devid invalid");
+ return FAIL_RETURN;
+ }
+
+ /* Subdev Delete Topo */
+ res = iotx_dm_subdev_topo_del(devid);
+ if (res < SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_lock();
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ code = node->code;
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+static int _iotx_linkkit_master_close(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ _iotx_linkkit_mutex_lock();
+ if (ctx->is_opened == 0) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ ctx->is_opened = 0;
+
+ iotx_dm_close();
+#ifdef DEVICE_MODEL_GATEWAY
+ _iotx_linkkit_upstream_sync_callback_list_destroy();
+ HAL_MutexDestroy(ctx->upstream_mutex);
+#endif
+ _iotx_linkkit_mutex_unlock();
+ HAL_MutexDestroy(ctx->mutex);
+ memset(ctx, 0, sizeof(iotx_linkkit_ctx_t));
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+static int _iotx_linkkit_slave_close(int devid)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ _iotx_linkkit_mutex_lock();
+ if (ctx->is_opened == 0) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ /* Release Subdev Resources */
+ iotx_dm_subdev_destroy(devid);
+
+ _iotx_linkkit_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+//data moved from global data center to the region user used, MUST reinitialized sdk and all devices.
+int user_handle_redirect()
+{
+ iotx_linkkit_dev_meta_info_t meta_info;
+ int id = 0;
+ int res = 0;
+
+ //close master
+
+ memset(&meta_info, 0, sizeof(iotx_linkkit_dev_meta_info_t));
+ HAL_GetProductKey(meta_info.product_key);
+ HAL_GetProductSecret(meta_info.product_secret);
+ HAL_GetDeviceName(meta_info.device_name);
+ HAL_GetDeviceSecret(meta_info.device_secret);
+
+ IOT_Linkkit_Close(IOTX_DM_LOCAL_NODE_DEVID);
+ /* Create Master Device Resources */
+ do {
+ id = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, &meta_info);
+ if (id < 0) {
+ dm_log_err("IOT_Linkkit_Open Failed, retry after 5s...\n");
+ HAL_SleepMs(5000);
+ }
+ } while (id < 0);
+ /* Start Connect Aliyun Server */
+ do {
+ res = IOT_Linkkit_Connect(id);
+ if (res < 0) {
+ dm_log_err("IOT_Linkkit_Connect Failed, retry after 5s...\n");
+ HAL_SleepMs(5000);
+ }
+ } while (res < 0);
+
+ return 0;
+}
+
+static int user_redirect_event_handler(void)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ dm_log_debug("Cloud Redirect");
+
+ ctx->cloud_redirect = 1;
+
+ return 0;
+}
+
+int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info)
+{
+ int res = 0;
+
+ if (dev_type < 0 || dev_type >= IOTX_LINKKIT_DEV_TYPE_MAX || meta_info == NULL) {
+ dm_log_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ switch (dev_type) {
+ case IOTX_LINKKIT_DEV_TYPE_MASTER: {
+ res = _iotx_linkkit_master_open(meta_info);
+ if (res == SUCCESS_RETURN) {
+ res = IOTX_DM_LOCAL_NODE_DEVID;
+ IOT_RegisterCallback(ITE_REDIRECT, user_redirect_event_handler);
+ }
+ }
+ break;
+ case IOTX_LINKKIT_DEV_TYPE_SLAVE: {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = _iotx_linkkit_slave_open(meta_info);
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+ break;
+ default: {
+ dm_log_err("Unknown Device Type");
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ return res;
+}
+
+int IOT_Linkkit_Connect(int devid)
+{
+ int res = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (devid < 0) {
+ dm_log_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (ctx->is_opened == 0) {
+
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_mutex_lock();
+
+ if (devid == IOTX_DM_LOCAL_NODE_DEVID) {
+ res = _iotx_linkkit_master_connect();
+ } else {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = _iotx_linkkit_slave_connect(devid);
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+ _iotx_linkkit_mutex_unlock();
+
+ return res;
+}
+
+void IOT_Linkkit_Yield(int timeout_ms)
+{
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (timeout_ms <= 0) {
+ dm_log_err("Invalid Parameter");
+ return;
+ }
+
+ if (ctx->is_opened == 0 || ctx->is_connected == 0) {
+ return;
+ }
+
+ // NOTICE: Do Not remove the following codes!
+ if (ctx->cloud_redirect == 1){
+ // user_handle_redirect();
+ dm_log_info("Reboot to redirect");
+ HAL_Reboot();
+ ctx->cloud_redirect = 0;
+ }
+
+ iotx_dm_yield(timeout_ms);
+ iotx_dm_dispatch();
+
+#ifdef DEVICE_MODEL_GATEWAY
+ HAL_SleepMs(timeout_ms);
+#endif
+}
+
+int IOT_Linkkit_Close(int devid)
+{
+ int res = 0;
+
+ if (devid < 0) {
+ dm_log_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (devid == IOTX_DM_LOCAL_NODE_DEVID) {
+ res = _iotx_linkkit_master_close();
+#ifdef DEV_BIND_ENABLED
+ awss_bind_deinit();
+#endif
+ } else {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = _iotx_linkkit_slave_close(devid);
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+
+ return res;
+}
+
+#ifdef DEVICE_MODEL_GATEWAY
+static int _iotx_linkkit_subdev_login(int devid)
+{
+ int res = 0, msgid = 0, code = 0;
+ iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
+ void *semaphore = NULL;
+ void *callback = NULL;
+
+ res = iotx_dm_subdev_login(devid);
+ if (res < SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ msgid = res;
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_lock();
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ code = node->code;
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ res = iotx_dm_subscribe(devid);
+ if (res != SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ iotx_dm_send_aos_active(devid);
+ callback = iotx_event_callback(ITE_INITIALIZE_COMPLETED);
+ if (callback) {
+ ((int (*)(const int))callback)(devid);
+ }
+
+ return res;
+}
+
+static int _iotx_linkkit_subdev_logout(int devid)
+{
+ int res = 0, msgid = 0, code = 0;
+ iotx_linkkit_upstream_sync_callback_node_t *node = NULL;
+ void *semaphore = NULL;
+
+ res = iotx_dm_subdev_logout(devid);
+ if (res < SUCCESS_RETURN) {
+ return FAIL_RETURN;
+ }
+
+ msgid = res;
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ res = _iotx_linkkit_upstream_sync_callback_list_insert(msgid, semaphore, &node);
+ if (res != SUCCESS_RETURN) {
+ HAL_SemaphoreDestroy(semaphore);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ res = HAL_SemaphoreWait(semaphore, IOTX_LINKKIT_SYNC_DEFAULT_TIMEOUT_MS);
+ if (res < SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_lock();
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_upstream_mutex_lock();
+ code = node->code;
+ _iotx_linkkit_upstream_sync_callback_list_remove(msgid);
+ if (code != SUCCESS_RETURN) {
+ _iotx_linkkit_upstream_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ _iotx_linkkit_upstream_mutex_unlock();
+
+ return res;
+}
+#endif
+
+int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, int payload_len)
+{
+ int res = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (devid < 0 || msg_type < 0 || msg_type >= IOTX_LINKKIT_MSG_MAX) {
+ dm_log_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (ctx->is_opened == 0 || ctx->is_connected == 0) {
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_mutex_lock();
+ switch (msg_type) {
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ case ITM_MSG_POST_PROPERTY: {
+ if (payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ res = iotx_dm_post_property(devid, (char *)payload, payload_len);
+#ifdef LOG_REPORT_TO_CLOUD
+ if (1 == report_sample) {
+ send_permance_info(NULL, 0, "4", 1);
+ }
+#endif
+ }
+ break;
+#ifdef DEVICE_MODEL_SHADOW
+ case ITM_MSG_PROPERTY_DESIRED_GET: {
+ if (payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ res = iotx_dm_property_desired_get(devid, (char *)payload, payload_len);
+ }
+ break;
+ case ITM_MSG_PROPERTY_DESIRED_DELETE: {
+ if (payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ res = iotx_dm_property_desired_delete(devid, (char *)payload, payload_len);
+ }
+ break;
+#endif
+ case ITM_MSG_DEVICEINFO_UPDATE: {
+ if (payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ res = iotx_dm_deviceinfo_update(devid, (char *)payload, payload_len);
+ }
+ break;
+ case ITM_MSG_DEVICEINFO_DELETE: {
+ if (payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ res = iotx_dm_deviceinfo_delete(devid, (char *)payload, payload_len);
+ }
+ break;
+#endif
+ case ITM_MSG_POST_RAW_DATA: {
+ if (payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ res = iotx_dm_post_rawdata(devid, (char *)payload, payload_len);
+ }
+ break;
+ case ITM_MSG_LOGIN: {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = _iotx_linkkit_subdev_login(devid);
+ if (res != SUCCESS_RETURN) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+ break;
+ case ITM_MSG_LOGOUT: {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = _iotx_linkkit_subdev_logout(devid);
+ if (res != SUCCESS_RETURN) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+ break;
+ case ITM_MSG_DELETE_TOPO: {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = _iotx_linkkit_subdev_delete_topo(devid);
+ if (res != SUCCESS_RETURN) {
+ _iotx_linkkit_mutex_unlock();
+ return FAIL_RETURN;
+ }
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+ break;
+#ifdef DEVICE_MODEL_GATEWAY
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+ case ITM_MSG_REPORT_SUBDEV_FIRMWARE_VERSION: {
+ res = iotx_dm_send_firmware_version(devid, (const char *)payload);
+ }
+ break;
+#endif
+#endif
+ default: {
+ dm_log_err("Unknown Message Type");
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+ _iotx_linkkit_mutex_unlock();
+ return res;
+}
+
+int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload, int payload_len)
+{
+ int res = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (devid < 0 || msg_type < 0 || msg_type >= IOTX_LINKKIT_MSG_MAX) {
+ dm_log_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (ctx->is_opened == 0 || ctx->is_connected == 0) {
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_mutex_lock();
+ switch (msg_type) {
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ case ITM_MSG_QUERY_TIMESTAMP: {
+ res = iotx_dm_qurey_ntp();
+ }
+ break;
+#endif
+ case ITM_MSG_QUERY_TOPOLIST: {
+#ifdef DEVICE_MODEL_GATEWAY
+ res = iotx_dm_query_topo_list();
+#else
+ res = FAIL_RETURN;
+#endif
+ }
+ break;
+ case ITM_MSG_QUERY_FOTA_DATA: {
+ res = iotx_dm_fota_perform_sync((char *)payload, payload_len);
+ }
+ break;
+ case ITM_MSG_QUERY_COTA_DATA: {
+ res = iotx_dm_cota_perform_sync((char *)payload, payload_len);
+ }
+ break;
+ case ITM_MSG_REQUEST_COTA: {
+ res = iotx_dm_cota_get_config("product", "file", "");
+ }
+ break;
+ case ITM_MSG_REQUEST_FOTA_IMAGE: {
+ res = iotx_dm_fota_request_image((const char *)payload, payload_len);
+ }
+ break;
+ default: {
+ dm_log_err("Unknown Message Type");
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+ _iotx_linkkit_mutex_unlock();
+ return res;
+}
+
+int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len)
+{
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ int res = 0;
+ iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx();
+
+ if (devid < 0 || eventid == NULL || eventid_len <= 0 || payload == NULL || payload_len <= 0) {
+ dm_log_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (ctx->is_opened == 0 || ctx->is_connected == 0) {
+ return FAIL_RETURN;
+ }
+
+ _iotx_linkkit_mutex_lock();
+ res = iotx_dm_post_event(devid, eventid, eventid_len, payload, payload_len);
+ _iotx_linkkit_mutex_unlock();
+
+ return res;
+#else
+ return -1;
+#endif
+}
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_ntp.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_ntp.c
new file mode 100644
index 00000000..ffb9f941
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_ntp.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#ifdef DEPRECATED_LINKKIT
+
+#include "infra_json_parser.h"
+#include "mqtt_api.h"
+#include "impl_ntp.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#define IMPL_NTP_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "impl.ntp")
+#define IMPL_NTP_FREE(ptr) LITE_free(ptr)
+#else
+#define IMPL_NTP_MALLOC(size) HAL_Malloc(size)
+#define IMPL_NTP_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+typedef void (*ntp_reply_cb_t)(const char *);
+static ntp_reply_cb_t g_ntp_reply_cb = NULL;
+static char g_ntp_time[NTP_TIME_STR_MAX_LEN + 1] = {0};
+
+static void linkkit_ntp_time_reply(void *pcontext, void *pclient, void *mesg)
+{
+#define DEV_TX_TIME "deviceSendTime"
+#define SERVER_RX_TIME "serverRecvTime"
+#define SERVER_TX_TIME "serverSendTime"
+
+ int len = 0;
+ char *elem = NULL;
+ char server_rx_time[NTP_TIME_STR_MAX_LEN + 1] = {0};
+ char server_tx_time[NTP_TIME_STR_MAX_LEN + 1] = {0};
+ uint32_t payload_len;
+ char *payload;
+ uint32_t tx = 0;
+ uint32_t rx = 0;
+ uint32_t diff = 0;
+
+ iotx_mqtt_event_msg_pt msg = (iotx_mqtt_event_msg_pt)mesg;
+ iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
+
+ switch (msg->event_type) {
+ case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
+ payload_len = ptopic_info->payload_len;
+ payload = (char *)ptopic_info->payload;
+ break;
+ default:
+ goto NTP_FAIL;
+ }
+
+ if (payload == NULL || payload_len == 0) {
+ goto NTP_FAIL;
+ }
+
+ memset(g_ntp_time, 0, sizeof(g_ntp_time));
+ log_debug("[ntp]", "ntp reply len:%u, payload:%s\r\n", payload_len, payload);
+
+ /*
+ * get deviceSendTime, serverRecvTime, serverSendTime
+ */
+ elem = json_get_value_by_name(payload, payload_len, SERVER_TX_TIME, &len, NULL);
+ if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
+ goto NTP_FAIL;
+ }
+
+ memcpy(server_tx_time, elem, len);
+
+ elem = json_get_value_by_name(payload, payload_len, SERVER_RX_TIME, &len, NULL);
+ if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
+ goto NTP_FAIL;
+ }
+
+ memcpy(server_rx_time, elem, len);
+
+ elem = json_get_value_by_name(payload, payload_len, DEV_TX_TIME, &len, NULL);
+ if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
+ goto NTP_FAIL;
+ }
+ /*
+ * atoi fails to convert string to integer
+ * so we convert manully
+ */
+ while (len -- > 0) {
+ tx *= 10;
+ tx += elem[0] - '0';
+ elem ++;
+ }
+ rx = HAL_UptimeMs();
+ diff = (rx - tx) >> 1;
+ if (diff >= 1000000) {
+ goto NTP_FAIL;
+ }
+
+ len = strlen(server_tx_time);
+ elem = &server_tx_time[len > 9 ? len - 9 : 0];
+ tx = atoi(elem);
+ tx += diff;
+
+ if (tx > 999999999) {
+ tx = 999999999;
+ }
+
+ if (len > 9) {
+ sprintf(elem, "%09u", (unsigned int)tx);
+ } else {
+ sprintf(elem, "%u", (unsigned int)tx);
+ }
+
+ strncpy(g_ntp_time, (const char *)server_tx_time, sizeof(g_ntp_time) - 1);
+
+NTP_FAIL:
+ if (g_ntp_reply_cb != NULL) {
+ g_ntp_reply_cb(g_ntp_time);
+ }
+ return;
+}
+
+int linkkit_ntp_time_request(void (*ntp_reply)(const char *ntp_offset_time_ms))
+{
+ int ret = -1;
+ int final_len = 0;
+ int packet_len = 64;
+ int topic_len = 128;
+ char *packet = NULL;
+ char *topic = NULL;
+
+ 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 *)IMPL_NTP_MALLOC(topic_len + 1);
+ if (topic == NULL) {
+ goto NTP_REQ_ERR;
+ }
+ memset(topic, 0, topic_len + 1);
+
+ HAL_Snprintf(topic, topic_len, TOPIC_NTP_REPLY, pk, dn);
+ ret = IOT_MQTT_Subscribe_Sync(NULL, topic, IOTX_MQTT_QOS0,
+ (iotx_mqtt_event_handle_func_fpt)linkkit_ntp_time_reply, NULL, 1000);
+ if (ret < 0) {
+ goto NTP_REQ_ERR;
+ }
+
+ memset(topic, 0, topic_len + 1);
+ HAL_Snprintf(topic, topic_len, TOPIC_NTP, pk, dn);
+ } while (0);
+
+ packet = (char *)IMPL_NTP_MALLOC(packet_len + 1);
+ if (packet == NULL) {
+ ret = -1;
+ goto NTP_REQ_ERR;
+ }
+ memset(packet, 0, packet_len + 1);
+
+ g_ntp_reply_cb = ntp_reply;
+ final_len = HAL_Snprintf(packet, packet_len, "{\"deviceSendTime\":\"%u\"}", (unsigned int)(HAL_UptimeMs()));
+
+ log_debug("[ntp]", "report ntp:%s\r\n", packet);
+
+
+ ret = IOT_MQTT_Publish_Simple(NULL, topic, IOTX_MQTT_QOS0, packet, final_len);
+
+NTP_REQ_ERR:
+ if (topic) {
+ IMPL_NTP_FREE(topic);
+ }
+ if (packet) {
+ IMPL_NTP_FREE(packet);
+ }
+ return ret;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_ntp.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_ntp.h
new file mode 100644
index 00000000..d5f20d06
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_ntp.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NTP_H
+#define NTP_H
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+
+#define TOPIC_NTP "/ext/ntp/%s/%s/request"
+#define TOPIC_NTP_REPLY "/ext/ntp/%s/%s/response"
+
+#define NTP_TIME_STR_MAX_LEN (20)
+
+int linkkit_ntp_time_request(void (*)(const char *ntp_offset_time_ms));
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_solo.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_solo.c
new file mode 100644
index 00000000..7cb2a9a5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_solo.c
@@ -0,0 +1,1186 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "iotx_dm_internal.h"
+
+#ifdef DEPRECATED_LINKKIT
+
+#include "linkkit_export.h"
+#include "impl_solo.h"
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define IMPL_SOLO_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "impl.solo")
+ #define IMPL_SOLO_FREE(ptr) LITE_free(ptr)
+#else
+ #define IMPL_SOLO_MALLOC(size) HAL_Malloc(size)
+ #define IMPL_SOLO_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define impl_solo_err(...) log_err("impl.solo", __VA_ARGS__)
+ #define impl_solo_info(...) log_info("impl.solo", __VA_ARGS__)
+ #define impl_solo_debug(...) log_debug("impl.solo", __VA_ARGS__)
+#else
+ #define impl_solo_err(...)
+ #define impl_solo_info(...)
+ #define impl_solo_debug(...)
+#endif
+
+linkkit_solo_legacy_ctx_t g_linkkit_solo_legacy_ctx = {0};
+
+static being_deprecated linkkit_solo_legacy_ctx_t *_linkkit_solo_legacy_get_ctx(void)
+{
+ return &g_linkkit_solo_legacy_ctx;
+}
+
+static void _linkkit_solo_mutex_lock(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ if (linkkit_solo_ctx->mutex) {
+ HAL_MutexLock(linkkit_solo_ctx->mutex);
+ }
+}
+
+static void _linkkit_solo_mutex_unlock(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ if (linkkit_solo_ctx->mutex) {
+ HAL_MutexUnlock(linkkit_solo_ctx->mutex);
+ }
+}
+
+static void _linkkit_solo_upstream_mutex_lock(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ if (linkkit_solo_ctx->upstream_mutex) {
+ HAL_MutexLock(linkkit_solo_ctx->upstream_mutex);
+ }
+}
+
+static void _linkkit_solo_upstream_mutex_unlock(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ if (linkkit_solo_ctx->upstream_mutex) {
+ HAL_MutexUnlock(linkkit_solo_ctx->upstream_mutex);
+ }
+}
+
+static int _impl_copy(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
+{
+ if (input == NULL || output == NULL || *output != NULL) {
+ return DM_INVALID_PARAMETER;
+ }
+
+ *output = IMPL_SOLO_MALLOC(output_len);
+ if (*output == NULL) {
+ return DM_MEMORY_NOT_ENOUGH;
+ }
+ memset(*output, 0, output_len);
+ memcpy(*output, input, input_len);
+
+ return SUCCESS_RETURN;
+}
+
+static int _linkkit_solo_upstream_callback_list_insert(int msgid, handle_post_cb_fp_t callback)
+{
+ int count = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ linkkit_solo_upstream_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_solo_ctx->callback_list, linked_list, linkkit_solo_upstream_callback_node_t) {
+ count++;
+ if (search_node->msgid == msgid) {
+ impl_solo_info("Message ID Already Exist: %d", msgid);
+ return FAIL_RETURN;
+ }
+ }
+
+ impl_solo_info("linkkit_solo_upstream_callback_list node count: %d", count);
+
+ search_node = IMPL_SOLO_MALLOC(sizeof(linkkit_solo_upstream_callback_node_t));
+ if (search_node == NULL) {
+ return FAIL_RETURN;
+ }
+ memset(search_node, 0, sizeof(linkkit_solo_upstream_callback_node_t));
+
+ search_node->msgid = msgid;
+ search_node->callback = callback;
+ search_node->callback = callback;
+ INIT_LIST_HEAD(&search_node->linked_list);
+
+ list_add(&search_node->linked_list, &linkkit_solo_ctx->callback_list);
+
+ return SUCCESS_RETURN;
+}
+
+static int _linkkit_solo_upstream_callback_list_remove(int msgid)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ linkkit_solo_upstream_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_solo_ctx->callback_list, linked_list, linkkit_solo_upstream_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ list_del(&search_node->linked_list);
+ IMPL_SOLO_FREE(search_node);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _linkkit_solo_upstream_callback_list_search(int msgid, linkkit_solo_upstream_callback_node_t **node)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ linkkit_solo_upstream_callback_node_t *search_node = NULL;
+
+ list_for_each_entry(search_node, &linkkit_solo_ctx->callback_list, linked_list, linkkit_solo_upstream_callback_node_t) {
+ if (search_node->msgid == msgid) {
+ *node = search_node;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ return FAIL_RETURN;
+}
+
+static int _linkkit_solo_upstream_callback_list_destroy(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ linkkit_solo_upstream_callback_node_t *search_node = NULL, *next_node = NULL;
+
+ list_for_each_entry_safe(search_node, next_node, &linkkit_solo_ctx->callback_list, linked_list,
+ linkkit_solo_upstream_callback_node_t) {
+ list_del(&search_node->linked_list);
+ IMPL_SOLO_FREE(search_node);
+ }
+
+ return FAIL_RETURN;
+}
+
+void *linkkit_dispatch(void)
+{
+ iotx_dm_dispatch();
+ return NULL;
+}
+
+int being_deprecated linkkit_is_try_leave(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ return linkkit_solo_ctx->is_leaved;
+}
+
+int being_deprecated linkkit_set_opt(linkkit_opt_t opt, void *data)
+{
+ int res = 0;
+
+ if (data == NULL) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_set_opt(opt, data);
+ _linkkit_solo_mutex_unlock();
+
+ return res;
+}
+
+static void _linkkit_solo_event_callback(iotx_dm_event_types_t type, char *payload)
+{
+ int res = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ lite_cjson_t lite, lite_item_id, lite_item_code, lite_item_devid, lite_item_payload, lite_item_serviceid;
+ lite_cjson_t lite_item_propertyid, lite_item_eventid, lite_item_configid, lite_item_configsize, lite_item_gettype;
+ lite_cjson_t lite_item_sign, lite_item_signmethod, lite_item_url, lite_item_version;
+
+ impl_solo_info("Receive Message Type: %d", type);
+ if (payload) {
+ impl_solo_info("Receive Message: %s", payload);
+ res = dm_utils_json_parse(payload, strlen(payload), cJSON_Invalid, &lite);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_ID, strlen(LINKKIT_SOLO_LEGACY_KEY_ID), cJSON_Invalid,
+ &lite_item_id);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_CODE, strlen(LINKKIT_SOLO_LEGACY_KEY_CODE), cJSON_Invalid,
+ &lite_item_code);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_DEVID, strlen(LINKKIT_SOLO_LEGACY_KEY_DEVID), cJSON_Invalid,
+ &lite_item_devid);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_PAYLOAD, strlen(LINKKIT_SOLO_LEGACY_KEY_PAYLOAD),
+ cJSON_Invalid, &lite_item_payload);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_SERVICEID, strlen(LINKKIT_SOLO_LEGACY_KEY_SERVICEID),
+ cJSON_Invalid, &lite_item_serviceid);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_PROPERTYID, strlen(LINKKIT_SOLO_LEGACY_KEY_PROPERTYID),
+ cJSON_Invalid, &lite_item_propertyid);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_EVENTID, strlen(LINKKIT_SOLO_LEGACY_KEY_EVENTID),
+ cJSON_Invalid, &lite_item_eventid);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_CONFIG_ID, strlen(LINKKIT_SOLO_LEGACY_KEY_CONFIG_ID),
+ cJSON_Invalid, &lite_item_configid);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_CONFIG_SIZE, strlen(LINKKIT_SOLO_LEGACY_KEY_CONFIG_SIZE),
+ cJSON_Invalid, &lite_item_configsize);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_GET_TYPE, strlen(LINKKIT_SOLO_LEGACY_KEY_GET_TYPE),
+ cJSON_Invalid, &lite_item_gettype);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_SIGN, strlen(LINKKIT_SOLO_LEGACY_KEY_SIGN), cJSON_Invalid,
+ &lite_item_sign);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_SIGN_METHOD, strlen(LINKKIT_SOLO_LEGACY_KEY_SIGN_METHOD),
+ cJSON_Invalid, &lite_item_signmethod);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_URL, strlen(LINKKIT_SOLO_LEGACY_KEY_URL), cJSON_Invalid,
+ &lite_item_url);
+ dm_utils_json_object_item(&lite, LINKKIT_SOLO_LEGACY_KEY_VERSION, strlen(LINKKIT_SOLO_LEGACY_KEY_VERSION),
+ cJSON_Invalid, &lite_item_version);
+ }
+
+ switch (type) {
+ case IOTX_DM_EVENT_CLOUD_CONNECTED: {
+ if (linkkit_solo_ctx->user_callback->on_connect) {
+ linkkit_solo_ctx->user_callback->on_connect(linkkit_solo_ctx->user_context);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_CLOUD_DISCONNECT: {
+ if (linkkit_solo_ctx->user_callback->on_disconnect) {
+ linkkit_solo_ctx->user_callback->on_disconnect(linkkit_solo_ctx->user_context);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_MODEL_DOWN_RAW: {
+ int res = 0, raw_data_len = 0;
+ void *thing_id = NULL;
+ unsigned char *raw_data = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number || lite_item_payload.type != cJSON_String) {
+ return;
+ }
+
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+ impl_solo_debug("Current Raw Data: %.*s", lite_item_payload.value_length, lite_item_payload.value);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ res = dm_utils_str_to_hex(lite_item_payload.value, lite_item_payload.value_length, &raw_data, &raw_data_len);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+ HEXDUMP_DEBUG(raw_data, raw_data_len);
+
+ if (linkkit_solo_ctx->user_callback->raw_data_arrived) {
+ linkkit_solo_ctx->user_callback->raw_data_arrived(thing_id, raw_data, raw_data_len, linkkit_solo_ctx->user_context);
+ }
+
+ IMPL_SOLO_FREE(raw_data);
+ }
+ break;
+ case IOTX_DM_EVENT_THING_SERVICE_REQUEST: {
+ int res = 0;
+ void *thing_id = NULL;
+ char *service = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_devid.type != cJSON_Number ||
+ lite_item_serviceid.type != cJSON_String) {
+ return;
+ }
+
+ impl_solo_debug("Current Id: %d", lite_item_id.value_int);
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+ impl_solo_debug("Current ServiceID: %.*s", lite_item_serviceid.value_length, lite_item_serviceid.value);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ service = IMPL_SOLO_MALLOC(lite_item_serviceid.value_length + 1);
+ if (service == NULL) {
+ return;
+ }
+ memset(service, 0, lite_item_serviceid.value_length + 1);
+ memcpy(service, lite_item_serviceid.value, lite_item_serviceid.value_length);
+
+ if (linkkit_solo_ctx->user_callback->thing_call_service) {
+ linkkit_solo_ctx->user_callback->thing_call_service(thing_id, (const char *)service, lite_item_id.value_int,
+ linkkit_solo_ctx->user_context);
+ }
+
+ IMPL_SOLO_FREE(service);
+ }
+ break;
+ case IOTX_DM_EVENT_LEGACY_THING_CREATED: {
+ int res = 0;
+ void *thing_id = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number) {
+ return;
+ }
+
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ if (linkkit_solo_ctx->user_callback->thing_create) {
+ linkkit_solo_ctx->user_callback->thing_create(thing_id, linkkit_solo_ctx->user_context);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_THING_DISABLE: {
+ int res = 0;
+ void *thing_id = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number) {
+ return;
+ }
+
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ if (linkkit_solo_ctx->user_callback->thing_disable) {
+ linkkit_solo_ctx->user_callback->thing_disable(thing_id, linkkit_solo_ctx->user_context);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_THING_ENABLE: {
+ int res = 0;
+ void *thing_id = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number) {
+ return;
+ }
+
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ if (linkkit_solo_ctx->user_callback->thing_enable) {
+ linkkit_solo_ctx->user_callback->thing_enable(thing_id, linkkit_solo_ctx->user_context);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_PROPERTY_SET: {
+ int res = 0;
+ void *thing_id = NULL;
+ char *propertyid = NULL;
+
+ if (payload == NULL || lite_item_devid.type != cJSON_Number || lite_item_propertyid.type != cJSON_String) {
+ return;
+ }
+
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+ impl_solo_debug("Current PropertyID: %.*s", lite_item_propertyid.value_length, lite_item_propertyid.value);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ propertyid = IMPL_SOLO_MALLOC(lite_item_propertyid.value_length + 1);
+ if (propertyid == NULL) {
+ return;
+ }
+ memset(propertyid, 0, lite_item_propertyid.value_length + 1);
+ memcpy(propertyid, lite_item_propertyid.value, lite_item_propertyid.value_length);
+
+ if (linkkit_solo_ctx->user_callback->thing_prop_changed) {
+ linkkit_solo_ctx->user_callback->thing_prop_changed(thing_id, propertyid, linkkit_solo_ctx->user_context);
+ }
+
+ IMPL_SOLO_FREE(propertyid);
+ }
+ break;
+ case IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY: {
+ int res = 0;
+ void *thing_id = NULL;
+ linkkit_solo_upstream_callback_node_t *node = NULL;
+ handle_post_cb_fp_t callback = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_code.type != cJSON_Number ||
+ lite_item_devid.type != cJSON_Number) {
+ return;
+ }
+
+ impl_solo_debug("Current Id: %d", lite_item_id.value_int);
+ impl_solo_debug("Current Code: %d", lite_item_code.value_int);
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ _linkkit_solo_upstream_mutex_lock();
+ res = _linkkit_solo_upstream_callback_list_search(lite_item_id.value_int, &node);
+ if (res == SUCCESS_RETURN) {
+ callback = node->callback;
+ }
+ _linkkit_solo_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (callback) {
+ callback(thing_id, lite_item_id.value_int, lite_item_code.value_int, NULL, linkkit_solo_ctx->user_context);
+ }
+ _linkkit_solo_upstream_mutex_lock();
+ _linkkit_solo_upstream_callback_list_remove(lite_item_id.value_int);
+ _linkkit_solo_upstream_mutex_unlock();
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_EVENT_SPECIFIC_POST_REPLY: {
+ int res = 0;
+ void *thing_id = NULL;
+ linkkit_solo_upstream_callback_node_t *node = NULL;
+ handle_post_cb_fp_t callback = NULL;
+
+ if (payload == NULL || lite_item_id.type != cJSON_Number || lite_item_code.type != cJSON_Number ||
+ lite_item_devid.type != cJSON_Number || lite_item_eventid.type != cJSON_String) {
+ return;
+ }
+
+ impl_solo_debug("Current Id: %d", lite_item_id.value_int);
+ impl_solo_debug("Current Code: %d", lite_item_code.value_int);
+ impl_solo_debug("Current Devid: %d", lite_item_devid.value_int);
+ impl_solo_debug("Current EventID: %.*s", lite_item_eventid.value_length, lite_item_eventid.value);
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(lite_item_devid.value_int, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ return;
+ }
+
+ _linkkit_solo_upstream_mutex_lock();
+ res = _linkkit_solo_upstream_callback_list_search(lite_item_id.value_int, &node);
+ if (res == SUCCESS_RETURN) {
+ callback = node->callback;
+ }
+ _linkkit_solo_upstream_mutex_unlock();
+ if (res == SUCCESS_RETURN) {
+ if (callback) {
+ callback(thing_id, lite_item_id.value_int, lite_item_code.value_int, NULL, linkkit_solo_ctx->user_context);
+ }
+ _linkkit_solo_upstream_mutex_lock();
+ _linkkit_solo_upstream_callback_list_remove(lite_item_id.value_int);
+ _linkkit_solo_upstream_mutex_unlock();
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_COTA_NEW_CONFIG: {
+ char *config_id = NULL, *get_type = NULL, *sign = NULL, *sign_method = NULL, *url = NULL;
+
+ if (payload == NULL || lite_item_configid.type != cJSON_String || lite_item_configsize.type != cJSON_Number ||
+ lite_item_gettype.type != cJSON_String || lite_item_sign.type != cJSON_String
+ || lite_item_signmethod.type != cJSON_String ||
+ lite_item_url.type != cJSON_String) {
+ return;
+ }
+
+ impl_solo_debug("Current Config ID: %.*s", lite_item_configid.value_length, lite_item_configid.value);
+ impl_solo_debug("Current Config Size: %d", lite_item_configsize.value_int);
+ impl_solo_debug("Current Get Type: %.*s", lite_item_gettype.value_length, lite_item_gettype.value);
+ impl_solo_debug("Current Sign: %.*s", lite_item_sign.value_length, lite_item_sign.value);
+ impl_solo_debug("Current Sign Method: %.*s", lite_item_signmethod.value_length, lite_item_signmethod.value);
+ impl_solo_debug("Current URL: %.*s", lite_item_url.value_length, lite_item_url.value);
+
+ _impl_copy(lite_item_configid.value, lite_item_configid.value_length, (void **)&config_id,
+ lite_item_configid.value_length + 1);
+ _impl_copy(lite_item_gettype.value, lite_item_gettype.value_length, (void **)&get_type,
+ lite_item_gettype.value_length + 1);
+ _impl_copy(lite_item_sign.value, lite_item_sign.value_length, (void **)&sign, lite_item_sign.value_length + 1);
+ _impl_copy(lite_item_signmethod.value, lite_item_signmethod.value_length, (void **)&sign_method,
+ lite_item_signmethod.value_length + 1);
+ _impl_copy(lite_item_url.value, lite_item_url.value_length, (void **)&url, lite_item_url.value_length + 1);
+
+ if (config_id == NULL || get_type == NULL || sign == NULL || sign_method == NULL || url == NULL) {
+ if (config_id) {
+ IMPL_SOLO_FREE(config_id);
+ }
+ if (get_type) {
+ IMPL_SOLO_FREE(get_type);
+ }
+ if (sign) {
+ IMPL_SOLO_FREE(sign);
+ }
+ if (sign_method) {
+ IMPL_SOLO_FREE(sign_method);
+ }
+ if (url) {
+ IMPL_SOLO_FREE(url);
+ }
+ return;
+ }
+
+ if (linkkit_solo_ctx->cota_callback) {
+ linkkit_solo_ctx->cota_callback(service_cota_callback_type_new_version_detected, config_id,
+ lite_item_configsize.value_int, get_type, sign, sign_method, url);
+ }
+
+ if (config_id) {
+ IMPL_SOLO_FREE(config_id);
+ }
+ if (get_type) {
+ IMPL_SOLO_FREE(get_type);
+ }
+ if (sign) {
+ IMPL_SOLO_FREE(sign);
+ }
+ if (sign_method) {
+ IMPL_SOLO_FREE(sign_method);
+ }
+ if (url) {
+ IMPL_SOLO_FREE(url);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_FOTA_NEW_FIRMWARE: {
+ char *version = NULL;
+
+ if (payload == NULL || lite_item_version.type != cJSON_String) {
+ return;
+ }
+
+ impl_solo_debug("Current Firmware Version: %.*s", lite_item_version.value_length, lite_item_version.value);
+
+ _impl_copy(lite_item_version.value, lite_item_version.value_length, (void **)&version,
+ lite_item_version.value_length + 1);
+ if (version == NULL) {
+ return;
+ }
+
+ if (linkkit_solo_ctx->fota_callback) {
+ linkkit_solo_ctx->fota_callback(service_fota_callback_type_new_version_detected, version);
+ }
+
+ if (version) {
+ IMPL_SOLO_FREE(version);
+ }
+ }
+ break;
+#ifdef LOCAL_CONN_ENABLE
+ case IOTX_DM_EVENT_LOCAL_CONNECTED: {
+ if (linkkit_solo_ctx->on_connect) {
+ linkkit_solo_ctx->on_connect(context, 0);
+ }
+ }
+ break;
+ case IOTX_DM_EVENT_LOCAL_DISCONNECT: {
+ if (linkkit_solo_ctx->on_connect) {
+ linkkit_solo_ctx->on_connect(context, 0);
+ }
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+int being_deprecated linkkit_start(int max_buffered_msg, int get_tsl_from_cloud, linkkit_loglevel_t log_level,
+ linkkit_ops_t *ops,
+ linkkit_cloud_domain_type_t domain_type, void *user_context)
+{
+ int res = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+ iotx_dm_init_params_t dm_init_params;
+
+ if (linkkit_solo_ctx->is_started == 1) {
+ return FAIL_RETURN;
+ }
+ linkkit_solo_ctx->is_started = 1;
+
+ if (max_buffered_msg <= 0 || ops == NULL || log_level > LOG_DEBUG_LEVEL ||
+ domain_type >= linkkit_cloud_domain_max) {
+ impl_solo_err("Invalid Parameter");
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Create Mutex */
+ linkkit_solo_ctx->mutex = HAL_MutexCreate();
+ if (linkkit_solo_ctx->mutex == NULL) {
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ linkkit_solo_ctx->upstream_mutex = HAL_MutexCreate();
+ if (linkkit_solo_ctx->upstream_mutex == NULL) {
+ HAL_MutexDestroy(linkkit_solo_ctx->mutex);
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Set Linkkit Log Level */
+ IOT_SetLogLevel(log_level);
+
+ /* Set Region */
+ IOT_Ioctl(IOTX_IOCTL_SET_REGION, &domain_type);
+
+ /* Initialize Device Manager */
+ memset(&dm_init_params, 0, sizeof(iotx_dm_init_params_t));
+ dm_init_params.secret_type = IOTX_DM_DEVICE_SECRET_DEVICE;
+ dm_init_params.domain_type = (iotx_dm_cloud_domain_types_t)domain_type;
+ dm_init_params.event_callback = _linkkit_solo_event_callback;
+
+ res = iotx_dm_open();
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_solo_ctx->mutex);
+ HAL_MutexDestroy(linkkit_solo_ctx->upstream_mutex);
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_connect(&dm_init_params);
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_solo_ctx->mutex);
+ HAL_MutexDestroy(linkkit_solo_ctx->upstream_mutex);
+ iotx_dm_close();
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_subscribe(IOTX_DM_LOCAL_NODE_DEVID);
+ if (res != SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_solo_ctx->mutex);
+ HAL_MutexDestroy(linkkit_solo_ctx->upstream_mutex);
+ iotx_dm_close();
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+
+ /* Get TSL From Cloud If Need */
+ if (get_tsl_from_cloud != 0) {
+ res = iotx_dm_deprecated_set_tsl(IOTX_DM_LOCAL_NODE_DEVID, IOTX_DM_TSL_SOURCE_CLOUD, NULL, 0);
+ if (res < SUCCESS_RETURN) {
+ HAL_MutexDestroy(linkkit_solo_ctx->mutex);
+ HAL_MutexDestroy(linkkit_solo_ctx->upstream_mutex);
+ iotx_dm_close();
+ linkkit_solo_ctx->is_started = 0;
+ return FAIL_RETURN;
+ }
+ }
+
+ /* Init Message Callback List */
+ INIT_LIST_HEAD(&linkkit_solo_ctx->callback_list);
+
+ linkkit_solo_ctx->user_callback = ops;
+ linkkit_solo_ctx->user_context = user_context;
+ linkkit_solo_ctx->is_leaved = 0;
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_end(void)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ _linkkit_solo_upstream_mutex_lock();
+ linkkit_solo_ctx->is_started = 0;
+ _linkkit_solo_upstream_callback_list_destroy();
+ _linkkit_solo_upstream_mutex_unlock();
+
+ iotx_dm_close();
+ _linkkit_solo_mutex_unlock();
+
+ HAL_MutexDestroy(linkkit_solo_ctx->upstream_mutex);
+ HAL_MutexDestroy(linkkit_solo_ctx->mutex);
+
+ linkkit_solo_ctx->mutex = NULL;
+ linkkit_solo_ctx->upstream_mutex = NULL;
+ linkkit_solo_ctx->user_callback = NULL;
+ linkkit_solo_ctx->user_context = NULL;
+ linkkit_solo_ctx->cota_callback = NULL;
+ linkkit_solo_ctx->fota_callback = NULL;
+ INIT_LIST_HEAD(&linkkit_solo_ctx->callback_list);
+
+ return SUCCESS_RETURN;
+}
+
+void *linkkit_set_tsl(const char *tsl, int tsl_len)
+{
+ int res = 0;
+ void *thing_id = NULL;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (tsl == NULL || tsl_len <= 0) {
+ impl_solo_err("Invalid Parameter");
+ return NULL;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return NULL;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_set_tsl(IOTX_DM_LOCAL_NODE_DEVID, IOTX_DM_TSL_SOURCE_LOCAL, tsl, tsl_len);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return NULL;
+ }
+
+ res = iotx_dm_deprecated_legacy_get_thingid_by_devid(IOTX_DM_LOCAL_NODE_DEVID, &thing_id);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return NULL;
+ }
+
+ _linkkit_solo_mutex_unlock();
+ return thing_id;
+}
+
+int being_deprecated linkkit_set_value(linkkit_method_set_t method_set, const void *thing_id, const char *identifier,
+ const void *value,
+ const char *value_str)
+{
+ int res = 0, devid = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL || identifier == NULL || (value == NULL && value_str == NULL)) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (method_set) {
+ case linkkit_method_set_property_value: {
+ res = iotx_dm_deprecated_legacy_set_property_value(devid, (char *)identifier, strlen(identifier), (void *)value,
+ (char *)value_str);
+ }
+ break;
+ case linkkit_method_set_event_output_value: {
+ res = iotx_dm_deprecated_legacy_set_event_output_value(devid, (char *)identifier, strlen(identifier), (void *)value,
+ (char *)value_str);
+ }
+ break;
+ case linkkit_method_set_service_output_value: {
+ res = iotx_dm_deprecated_legacy_set_service_output_value(devid, (char *)identifier, strlen(identifier), (void *)value,
+ (char *)value_str);
+ }
+ break;
+ default: {
+ impl_solo_err("Invalid Parameter");
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_get_value(linkkit_method_get_t method_get, const void *thing_id, const char *identifier,
+ void *value,
+ char **value_str)
+{
+ int res = 0, devid = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL || identifier == NULL || (value == NULL && value_str == NULL)) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (method_get) {
+ case linkkit_method_get_property_value: {
+ res = iotx_dm_deprecated_legacy_get_property_value(devid, (char *)identifier, strlen(identifier), value, value_str);
+ }
+ break;
+ case linkkit_method_get_event_output_value: {
+ res = iotx_dm_deprecated_legacy_get_event_output_value(devid, (char *)identifier, strlen(identifier), value, value_str);
+ }
+ break;
+ case linkkit_method_get_service_input_value: {
+ res = iotx_dm_deprecated_legacy_get_service_input_value(devid, (char *)identifier, strlen(identifier), value,
+ value_str);
+ }
+ break;
+ case linkkit_method_get_service_output_value: {
+ res = iotx_dm_deprecated_legacy_get_service_output_value(devid, (char *)identifier, strlen(identifier), value,
+ value_str);
+ }
+ break;
+ default: {
+ impl_solo_err("Invalid Parameter");
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_answer_service(const void *thing_id, const char *service_identifier, int response_id,
+ int code)
+{
+ int res = 0, devid = 0;
+
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL || service_identifier == NULL) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_deprecated_send_service_response(devid, response_id, (iotx_dm_error_code_t)code,
+ (char *)service_identifier, strlen(service_identifier));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_invoke_raw_service(const void *thing_id, int is_up_raw, void *raw_data,
+ int raw_data_length)
+{
+ int res = 0, devid = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL || raw_data == NULL || raw_data_length <= 0) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_post_rawdata(devid, raw_data, raw_data_length);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_trigger_extended_info_operate(const void *thing_id, const char *params,
+ linkkit_extended_info_operate_t linkkit_extended_info_operation)
+{
+ int res = 0, devid = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL || params == NULL) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ switch (linkkit_extended_info_operation) {
+ case linkkit_extended_info_operate_update: {
+ res = iotx_dm_deviceinfo_update(devid, (char *)params, strlen(params));
+ }
+ break;
+ case linkkit_extended_info_operate_delete: {
+ res = iotx_dm_deviceinfo_delete(devid, (char *)params, strlen(params));
+ }
+ break;
+ default: {
+ impl_solo_err("Invalid Parameter");
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_trigger_event(const void *thing_id, const char *event_identifier, handle_post_cb_fp_t cb)
+{
+ int res = 0, devid = 0, msgid = 0, post_event_reply = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL || event_identifier == NULL) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_deprecated_post_event(devid, (char *)event_identifier, strlen((char *)event_identifier));
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ res = iotx_dm_get_opt(linkkit_opt_event_post_reply, &post_event_reply);
+ if (cb != NULL && post_event_reply) {
+ /* Insert Message ID Into Linked List */
+ _linkkit_solo_upstream_mutex_lock();
+ res = _linkkit_solo_upstream_callback_list_insert(msgid, cb);
+ _linkkit_solo_upstream_mutex_unlock();
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_post_property(const void *thing_id, const char *property_identifier,
+ handle_post_cb_fp_t cb)
+{
+ int res = 0, devid = 0, msgid = 0, property_identifier_len = 0, post_property_reply = 0;
+ void *property_handle = NULL;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (thing_id == NULL) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_deprecated_legacy_get_devid_by_thingid((void *)thing_id, &devid);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_deprecated_post_property_start(devid, &property_handle);
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ property_identifier_len = (property_identifier) ? (strlen((char *)property_identifier)) : (0);
+ res = iotx_dm_deprecated_post_property_add(property_handle, (char *)property_identifier, property_identifier_len);
+ if (res != SUCCESS_RETURN) {
+ iotx_dm_deprecated_post_property_end(&property_handle);
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+
+ res = iotx_dm_deprecated_post_property_end(&property_handle);
+ if (res < SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ msgid = res;
+
+ res = iotx_dm_get_opt(linkkit_opt_property_post_reply, &post_property_reply);
+ if (cb != NULL && post_property_reply) {
+ /* Insert Message ID Into Linked List */
+ _linkkit_solo_upstream_mutex_lock();
+ res = _linkkit_solo_upstream_callback_list_insert(msgid, cb);
+ _linkkit_solo_upstream_mutex_unlock();
+ if (res != SUCCESS_RETURN) {
+ _linkkit_solo_mutex_unlock();
+ return FAIL_RETURN;
+ }
+ }
+
+ _linkkit_solo_mutex_unlock();
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_yield(int timeout_ms)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (timeout_ms <= 0) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ return iotx_dm_yield(timeout_ms);
+}
+
+int being_deprecated linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ linkkit_solo_ctx->cota_callback = callback_fp;
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_invoke_cota_service(void *data_buf, int data_buf_length)
+{
+ int res = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (data_buf == NULL || data_buf_length <= 0) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_cota_perform_sync(data_buf, data_buf_length);
+ _linkkit_solo_mutex_unlock();
+
+ return res;
+}
+
+int being_deprecated linkkit_invoke_cota_get_config(const char *config_scope, const char *get_type,
+ const char *attribute_Keys,
+ void *option)
+{
+ int res = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (config_scope == NULL || get_type == NULL || attribute_Keys == NULL) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_cota_get_config(config_scope, get_type, attribute_Keys);
+ _linkkit_solo_mutex_unlock();
+
+ return res;
+}
+
+int being_deprecated linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp)
+{
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ linkkit_solo_ctx->fota_callback = callback_fp;
+
+ return SUCCESS_RETURN;
+}
+
+int being_deprecated linkkit_invoke_fota_service(void *data_buf, int data_buf_length)
+{
+ int res = 0;
+ linkkit_solo_legacy_ctx_t *linkkit_solo_ctx = _linkkit_solo_legacy_get_ctx();
+
+ if (data_buf == NULL || data_buf_length <= 0) {
+ impl_solo_err("Invalid Parameter");
+ return FAIL_RETURN;
+ }
+
+ if (linkkit_solo_ctx->is_started == 0) {
+ return FAIL_RETURN;
+ }
+
+ _linkkit_solo_mutex_lock();
+ res = iotx_dm_fota_perform_sync(data_buf, data_buf_length);
+ _linkkit_solo_mutex_unlock();
+
+ return res;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_solo.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_solo.h
new file mode 100644
index 00000000..7bebcfd8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/impl_solo.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _LINKKIT_SOLO_LEGACY_H_
+#define _LINKKIT_SOLO_LEGACY_H_
+
+#include "linkkit_export.h"
+
+#define LINKKIT_SOLO_LEGACY_KEY_ID "id"
+#define LINKKIT_SOLO_LEGACY_KEY_CODE "code"
+#define LINKKIT_SOLO_LEGACY_KEY_DEVID "devid"
+#define LINKKIT_SOLO_LEGACY_KEY_SERVICEID "serviceid"
+#define LINKKIT_SOLO_LEGACY_KEY_PROPERTYID "propertyid"
+#define LINKKIT_SOLO_LEGACY_KEY_EVENTID "eventid"
+#define LINKKIT_SOLO_LEGACY_KEY_PAYLOAD "payload"
+#define LINKKIT_SOLO_LEGACY_KEY_CONFIG_ID "configId"
+#define LINKKIT_SOLO_LEGACY_KEY_CONFIG_SIZE "configSize"
+#define LINKKIT_SOLO_LEGACY_KEY_GET_TYPE "getType"
+#define LINKKIT_SOLO_LEGACY_KEY_SIGN "sign"
+#define LINKKIT_SOLO_LEGACY_KEY_SIGN_METHOD "signMethod"
+#define LINKKIT_SOLO_LEGACY_KEY_URL "url"
+#define LINKKIT_SOLO_LEGACY_KEY_VERSION "version"
+
+typedef struct {
+ int msgid;
+ handle_post_cb_fp_t callback;
+ struct list_head linked_list;
+} linkkit_solo_upstream_callback_node_t;
+
+typedef struct {
+ void *mutex;
+ void *upstream_mutex;
+ int is_started;
+ int is_leaved;
+ linkkit_ops_t *user_callback;
+ void *user_context;
+ handle_service_cota_callback_fp_t cota_callback;
+ handle_service_fota_callback_fp_t fota_callback;
+ struct list_head callback_list;
+} linkkit_solo_legacy_ctx_t;
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iot_export_linkkit.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iot_export_linkkit.h
new file mode 100644
index 00000000..93ad8026
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iot_export_linkkit.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOT_EXPORT_LINKKIT_H_
+#define _IOT_EXPORT_LINKKIT_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "dm_wrapper.h"
+
+typedef enum {
+ IOTX_LINKKIT_DEV_TYPE_MASTER,
+ IOTX_LINKKIT_DEV_TYPE_SLAVE,
+ IOTX_LINKKIT_DEV_TYPE_MAX
+} iotx_linkkit_dev_type_t;
+
+typedef struct {
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char product_secret[IOTX_PRODUCT_SECRET_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
+} iotx_linkkit_dev_meta_info_t;
+
+typedef enum {
+ /* post property value to cloud */
+ ITM_MSG_POST_PROPERTY,
+
+ /* post device info update message to cloud */
+ ITM_MSG_DEVICEINFO_UPDATE,
+
+ /* post device info delete message to cloud */
+ ITM_MSG_DEVICEINFO_DELETE,
+
+ /* post raw data to cloud */
+ ITM_MSG_POST_RAW_DATA,
+
+ /* only for slave device, send login request to cloud */
+ ITM_MSG_LOGIN,
+
+ /* only for slave device, send logout request to cloud */
+ ITM_MSG_LOGOUT,
+
+ /* only for slave device, send delete topo request to cloud */
+ ITM_MSG_DELETE_TOPO,
+
+ /* query ntp time from cloud */
+ ITM_MSG_QUERY_TIMESTAMP,
+
+ /* only for master device, query topo list */
+ ITM_MSG_QUERY_TOPOLIST,
+
+ /* only for master device, qurey firmware ota data */
+ ITM_MSG_QUERY_FOTA_DATA,
+
+ /* only for master device, qurey config ota data */
+ ITM_MSG_QUERY_COTA_DATA,
+
+ /* only for master device, request config ota data from cloud */
+ ITM_MSG_REQUEST_COTA,
+
+ /* only for master device, request fota image from cloud */
+ ITM_MSG_REQUEST_FOTA_IMAGE,
+
+ /* report subdev's firmware version */
+ ITM_MSG_REPORT_SUBDEV_FIRMWARE_VERSION,
+
+ /* get a device's desired property */
+ ITM_MSG_PROPERTY_DESIRED_GET,
+
+ /* delete a device's desired property */
+ ITM_MSG_PROPERTY_DESIRED_DELETE,
+
+ IOTX_LINKKIT_MSG_MAX
+} iotx_linkkit_msg_type_t;
+
+/**
+ * @brief create a new device
+ *
+ * @param dev_type. type of device which will be created. see iotx_linkkit_dev_type_t
+ * @param meta_info. The product key, product secret, device name and device secret of new device.
+ *
+ * @return success: device id (>=0), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info);
+
+/**
+ * @brief start device network connection.
+ * for master device, start to connect aliyun server.
+ * for slave device, send message to cloud for register new device and add topo with master device
+ *
+ * @param devid. device identifier.
+ *
+ * @return success: device id (>=0), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Connect(int devid);
+
+/**
+ * @brief try to receive message from cloud and dispatch these message to user event callback
+ *
+ * @param timeout_ms. timeout for waiting new message arrived
+ *
+ * @return void.
+ *
+ */
+DLL_IOT_API void IOT_Linkkit_Yield(int timeout_ms);
+
+/**
+ * @brief close device network connection and release resources.
+ * for master device, disconnect with aliyun server and release all local resources.
+ * for slave device, send message to cloud for delete topo with master device and unregister itself, then release device's resources.
+ *
+ * @param devid. device identifier.
+ *
+ * @return success: 0, fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Close(int devid);
+
+/**
+ * @brief Report message to cloud
+ *
+ * @param devid. device identifier.
+ * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
+ * ITM_MSG_POST_PROPERTY
+ * ITM_MSG_DEVICEINFO_UPDATE
+ * ITM_MSG_DEVICEINFO_DELETE
+ * ITM_MSG_POST_RAW_DATA
+ * ITM_MSG_LOGIN
+ * ITM_MSG_LOGOUT
+ *
+ * @param payload. message payload.
+ * @param payload_len. message payload length.
+ *
+ * @return success: 0 or message id (>=1), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
+ int payload_len);
+
+/**
+ * @brief post message to cloud
+ *
+ * @param devid. device identifier.
+ * @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
+ * ITM_MSG_QUERY_TIMESTAMP
+ * ITM_MSG_QUERY_TOPOLIST
+ * ITM_MSG_QUERY_FOTA_DATA
+ * ITM_MSG_QUERY_COTA_DATA
+ * ITM_MSG_REQUEST_COTA
+ * ITM_MSG_REQUEST_FOTA_IMAGE
+ *
+ * @param payload. message payload.
+ * @param payload_len. message payload length.
+ *
+ * @return success: 0 or message id (>=1), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
+ int payload_len);
+
+/**
+ * @brief post event to cloud
+ *
+ * @param devid. device identifier.
+ * @param eventid. tsl event id.
+ * @param eventid_len. length of tsl event id.
+ * @param payload. event payload.
+ * @param payload_len. event payload length.
+ *
+ * @return success: message id (>=1), fail: -1.
+ *
+ */
+DLL_IOT_API int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_alcs.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_alcs.h
new file mode 100644
index 00000000..040a4aa3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_alcs.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _IOT_EXPORT_ALCS_BACKUP_H_
+#define _IOT_EXPORT_ALCS_BACKUP_H_
+
+#define IOTX_ALCS_ROLE_CLIENT (0x01)
+#define IOTX_ALCS_ROLE_SERVER (0x02)
+
+#define ALCS_MSG_MAX_TOKEN_LEN (8)
+
+typedef enum {
+
+ /*iotx_alcs_send Message Result And Receive Message*/
+ IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_SUCCESS,
+ IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_RESP_TIMEOUT,
+ IOTX_ALCS_EVENT_MSG_RECV_MESSAGE,
+ /*Its data type is @iotx_alcs_transfer_msg_t and see detail at the declare of this type.*/
+
+} iotx_alcs_event_type_t;
+
+typedef struct iotx_alcs_event_msg_st {
+
+ /* Specify the event type */
+ iotx_alcs_event_type_t event_type;
+
+ void *msg;
+} iotx_alcs_event_msg_t, *iotx_alcs_event_msg_pt;
+
+typedef struct iotx_alcs_transfer_msg_st {
+ char *ip;
+ uint16_t port;
+ char *uri;
+ uint8_t token_len;
+ uint8_t *token;
+ uint16_t payload_len;
+ uint8_t *payload;
+} iotx_alcs_transfer_msg_t, *iotx_alcs_transfer_msg_pt;
+
+typedef void (*iotx_alcs_event_handle_func_fpt)(void *pcontext, void *phandle, iotx_alcs_event_msg_t *msg);
+
+typedef struct {
+ iotx_alcs_event_handle_func_fpt h_fp;
+ void *pcontext;
+} iotx_alcs_event_handle_t;
+
+typedef struct iotx_alcs_param_st {
+ uint8_t role; /*can be client, server or both*/
+
+ uint8_t send_maxcount; /*list maximal count*/
+ uint8_t obs_maxcount; /*observe maximal count*/
+ uint16_t port; /* Local port */
+ char *group; /* Multicast address */
+ uint32_t waittime;
+ uint8_t res_maxcount;
+
+ iotx_alcs_event_handle_t *handle_event;
+} iotx_alcs_param_t, *iotx_alcs_param_pt;
+
+#define ITOX_ALCS_COAP_MSG_CODE_DEF(N) (((N)/100 << 5) | (N)%100)
+
+/*CoAP Message codes*/
+typedef enum {
+ /* CoAP Empty Message */
+ ITOX_ALCS_COAP_MSG_CODE_EMPTY_MESSAGE = ITOX_ALCS_COAP_MSG_CODE_DEF(0), /* Mapping to CoAP code 0.00 */
+
+ /* CoAP Method Codes */
+ ITOX_ALCS_COAP_MSG_CODE_GET = ITOX_ALCS_COAP_MSG_CODE_DEF(1), /* CoAP Get method */
+ ITOX_ALCS_COAP_MSG_CODE_POST = ITOX_ALCS_COAP_MSG_CODE_DEF(2), /* CoAP Post method */
+ ITOX_ALCS_COAP_MSG_CODE_PUT = ITOX_ALCS_COAP_MSG_CODE_DEF(3), /* CoAP Put method */
+ ITOX_ALCS_COAP_MSG_CODE_DELETE = ITOX_ALCS_COAP_MSG_CODE_DEF(4), /* CoAP Delete method */
+
+ /* CoAP Success Response Codes */
+ ITOX_ALCS_COAP_MSG_CODE_201_CREATED = ITOX_ALCS_COAP_MSG_CODE_DEF(201), /* Mapping to CoAP code 2.01, Hex:0x41, Created */
+ ITOX_ALCS_COAP_MSG_CODE_202_DELETED = ITOX_ALCS_COAP_MSG_CODE_DEF(202), /* Mapping to CoAP code 2.02, Hex:0x42, Deleted*/
+ ITOX_ALCS_COAP_MSG_CODE_203_VALID = ITOX_ALCS_COAP_MSG_CODE_DEF(203), /* Mapping to CoAP code 2.03, Hex:0x43, Valid*/
+ ITOX_ALCS_COAP_MSG_CODE_204_CHANGED = ITOX_ALCS_COAP_MSG_CODE_DEF(204), /* Mapping to CoAP code 2.04, Hex:0x44, Changed*/
+ ITOX_ALCS_COAP_MSG_CODE_205_CONTENT = ITOX_ALCS_COAP_MSG_CODE_DEF(205), /* Mapping to CoAP code 2.05, Hex:0x45, Content*/
+ ITOX_ALCS_COAP_MSG_CODE_231_CONTINUE = ITOX_ALCS_COAP_MSG_CODE_DEF(231), /* Mapping to CoAP code 2.31, Hex:0x5F, Continue*/
+
+ /* CoAP Client Error Response Codes */
+ ITOX_ALCS_COAP_MSG_CODE_400_BAD_REQUEST = ITOX_ALCS_COAP_MSG_CODE_DEF(400), /* Mapping to CoAP code 4.00, Hex:0x80, Bad Request */
+ ITOX_ALCS_COAP_MSG_CODE_401_UNAUTHORIZED = ITOX_ALCS_COAP_MSG_CODE_DEF(401), /* Mapping to CoAP code 4.01, Hex:0x81, Unauthorized */
+ ITOX_ALCS_COAP_MSG_CODE_402_BAD_OPTION = ITOX_ALCS_COAP_MSG_CODE_DEF(402), /* Mapping to CoAP code 4.02, Hex:0x82, Bad Option */
+ ITOX_ALCS_COAP_MSG_CODE_403_FORBIDDEN = ITOX_ALCS_COAP_MSG_CODE_DEF(403), /* Mapping to CoAP code 4.03, Hex:0x83, Forbidden */
+ ITOX_ALCS_COAP_MSG_CODE_404_NOT_FOUND = ITOX_ALCS_COAP_MSG_CODE_DEF(404), /* Mapping to CoAP code 4.04, Hex:0x84, Not Found */
+ ITOX_ALCS_COAP_MSG_CODE_405_METHOD_NOT_ALLOWED = ITOX_ALCS_COAP_MSG_CODE_DEF(405), /* Mapping to CoAP code 4.05, Hex:0x85, Method Not Allowed */
+ ITOX_ALCS_COAP_MSG_CODE_406_NOT_ACCEPTABLE = ITOX_ALCS_COAP_MSG_CODE_DEF(406), /* Mapping to CoAP code 4.06, Hex:0x86, Not Acceptable */
+ ITOX_ALCS_COAP_MSG_CODE_408_REQUEST_ENTITY_INCOMPLETE = ITOX_ALCS_COAP_MSG_CODE_DEF(408), /* Mapping to CoAP code 4.08, Hex:0x88, Request Entity Incomplete */
+ ITOX_ALCS_COAP_MSG_CODE_412_PRECONDITION_FAILED = ITOX_ALCS_COAP_MSG_CODE_DEF(412), /* Mapping to CoAP code 4.12, Hex:0x8C, Precondition Failed */
+ ITOX_ALCS_COAP_MSG_CODE_413_REQUEST_ENTITY_TOO_LARGE = ITOX_ALCS_COAP_MSG_CODE_DEF(413), /* Mapping to CoAP code 4.13, Hex:0x8D, Request Entity Too Large */
+ ITOX_ALCS_COAP_MSG_CODE_415_UNSUPPORTED_CONTENT_FORMAT = ITOX_ALCS_COAP_MSG_CODE_DEF(415), /* Mapping to CoAP code 4.15, Hex:0x8F, Unsupported Content-Format */
+
+ /* CoAP Server Error Response Codes */
+ ITOX_ALCS_COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR = ITOX_ALCS_COAP_MSG_CODE_DEF(500), /* Mapping to CoAP code 5.00, Hex:0xA0, Internal Server Error */
+ ITOX_ALCS_COAP_MSG_CODE_501_NOT_IMPLEMENTED = ITOX_ALCS_COAP_MSG_CODE_DEF(501), /* Mapping to CoAP code 5.01, Hex:0xA1, Not Implemented */
+ ITOX_ALCS_COAP_MSG_CODE_502_BAD_GATEWAY = ITOX_ALCS_COAP_MSG_CODE_DEF(502), /* Mapping to CoAP code 5.02, Hex:0xA2, Bad Gateway */
+ ITOX_ALCS_COAP_MSG_CODE_503_SERVICE_UNAVAILABLE = ITOX_ALCS_COAP_MSG_CODE_DEF(503), /* Mapping to CoAP code 5.03, Hex:0xA3, Service Unavailable */
+ ITOX_ALCS_COAP_MSG_CODE_504_GATEWAY_TIMEOUT = ITOX_ALCS_COAP_MSG_CODE_DEF(504), /* Mapping to CoAP code 5.04, Hex:0xA4, Gateway Timeout */
+ ITOX_ALCS_COAP_MSG_CODE_505_PROXYING_NOT_SUPPORTED = ITOX_ALCS_COAP_MSG_CODE_DEF(505) /* Mapping to CoAP code 5.05, Hex:0xA5, Proxying Not Supported */
+
+} iotx_alcs_message_code_t;
+
+typedef enum {
+ IOTX_ALCS_MESSAGE_TYPE_CON = 0,
+ IOTX_ALCS_MESSAGE_TYPE_NON = 1,
+ IOTX_ALCS_MESSAGE_TYPE_ACK = 2,
+ IOTX_ALCS_MESSAGE_TYPE_RST = 3
+} iotx_alcs_message_type_t;
+
+typedef enum {
+ IOTX_ALCS_MESSAGE_PERM_NONE = 0x0000,
+ IOTX_ALCS_MESSAGE_PERM_GET = 0x0001,
+ IOTX_ALCS_MESSAGE_PERM_POST = 0x0002,
+ IOTX_ALCS_MESSAGE_PERM_PUT = 0x0004,
+ IOTX_ALCS_MESSAGE_PERM_DEL = 0x0008,
+ IOTX_ALCS_MESSAGE_PERM_OBSERVE = 0x0100
+} iotx_alcs_message_perm_t;
+
+typedef enum {
+ IOTX_ALCS_MESSAGE_CT_TEXT_PLAIN = 0, /* text/plain (UTF-8) */
+ IOTX_ALCS_MESSAGE_CT_APP_LINK_FORMAT = 40, /* application/link-format */
+ IOTX_ALCS_MESSAGE_CT_APP_XML = 41, /* application/xml */
+ IOTX_ALCS_MESSAGE_CT_APP_OCTET_STREAM = 42, /* application/octet-stream */
+ IOTX_ALCS_MESSAGE_CT_APP_RDF_XML = 43, /* application/rdf+xml */
+ IOTX_ALCS_MESSAGE_CT_APP_EXI = 47, /* application/exi */
+ IOTX_ALCS_MESSAGE_CT_APP_JSON = 50, /* application/json */
+ IOTX_ALCS_MESSAGE_CT_APP_CBOR = 60 /* application/cbor */
+} iotx_alcs_message_content_type_t;
+
+typedef struct iotx_alcs_msg_st {
+ uint16_t group_id; /*multicast group id, used as unicast when 0*/
+ char *ip; /*dotted decimal notation, max len 16*/
+ uint16_t port;
+ iotx_alcs_message_code_t msg_code;
+ iotx_alcs_message_type_t msg_type;
+ char *uri;
+ uint32_t payload_len;
+ uint8_t *payload;
+} iotx_alcs_msg_t, *iotx_alcs_msg_pt;
+
+typedef struct iotx_alcs_res_st {
+ char *uri;
+ int32_t need_auth;
+ iotx_alcs_message_perm_t msg_perm;
+ iotx_alcs_message_content_type_t msg_ct;
+ uint32_t maxage; /*0~60*/
+ CoAPRecvMsgHandler callback;
+} iotx_alcs_res_t, *iotx_alcs_res_pt;
+
+/**
+ * @brief Construct the ALCS handle
+ * This function initialize the data structures, initialize ALCS information.
+ *
+ * @param [in] params: specify the ALCS initialize parameter.
+ *
+ * @retval NULL : Construct failed.
+ * @retval NOT_NULL : The handle of ALCS.
+ * @see None.
+ */
+void *iotx_alcs_construct(iotx_alcs_param_t *params);
+
+/**
+ * @brief Init Cloud Part
+ * This function initialize the cloud part.
+ *
+ * @param [in] params: specify the ALCS initialize parameter.
+ *
+ * @retval NULL : Construct failed.
+ * @retval NOT_NULL : The handle of ALCS.
+ * @see None.
+ */
+int iotx_alcs_cloud_init(void *handle);
+
+/**
+ * @brief Deconstruct the ALCS handle
+ * This function distroy ALCS handle and release the related resource.
+ *
+ * @param [in] phandle: pointer of handle, specify the MQTT client.
+ *
+ * @retval 0 : Deconstruct success.
+ * @retval -1 : Deconstruct failed.
+ * @see None.
+ */
+int iotx_alcs_destroy(void **phandle);
+
+/**
+ * @brief Handle ALCS message from specific udp port
+ *
+ * @param [in] handle: specify the ALCS handle.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_yield(void *handle);
+
+/**
+ * @brief Send Message To Secific Deivce
+ *
+ * @param [in] handle: specify the ALCS handle.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_send(void *handle, iotx_alcs_msg_t *msg);
+
+/**
+ * @brief Send Response Message To Secific Deivce
+ *
+ * @param [in] handle: specify the ALCS handle.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_send_Response(void *handle, iotx_alcs_msg_t *msg, uint8_t token_len, uint8_t *token);
+
+/**
+ * @brief Register Resource
+ *
+ * @param [in] handle: specify the ALCS handle.
+ * @param [in] handle: the resource need to be registered.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_register_resource(void *handle, iotx_alcs_res_t *resource);
+
+/**
+ * @brief ALCS Observe Notify
+ *
+ * @param [in] handle: specify the ALCS handle.
+ * @param [in] uri: the resource need to notify.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_observe_notify(void *handle, const char *uri, uint32_t payload_len, uint8_t *payload);
+
+/**
+ * @brief Unregister Resource
+ *
+ * @param [in] handle: specify the ALCS handle.
+ * @param [in] handle: the resource need to be registered.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_unregister_resource(void *handle, char *uri);
+
+/**
+ * @brief Add sub device
+ *
+ * @param [in] handle: specify the ALCS handle.
+ * @param [in] pk: the productkey of device.
+ * @param [in] dn: the deviceName of device.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_add_sub_device(void *handle, const char *pk, const char *dn);
+
+/**
+ * @brief remove sub device
+ *
+ * @param [in] handle: specify the ALCS handle.
+ * @param [in] pk: the productkey of device.
+ * @param [in] dn: the deviceName of device.
+ *
+ * @return status.
+ * @see None.
+ */
+int iotx_alcs_remove_sub_device(void *handle, const char *pk, const char *dn);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_alcs_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_alcs_config.h
new file mode 100644
index 00000000..5294ac26
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_alcs_config.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __IOTX_ALCS_CONFIG_H__
+#define __IOTX_ALCS_CONFIG_H__
+
+#if 0
+#ifndef ALCS_CLIENT_ENABLED
+ #define ALCS_CLIENT_ENABLED (1)
+#endif
+#endif
+
+#ifndef ALCS_SERVER_ENABLED
+ #define ALCS_SERVER_ENABLED (1)
+#endif
+
+#ifndef USE_ALCS_SECURE
+ #define USE_ALCS_SECURE (1)
+#endif
+
+#ifndef KEYPREFIX_LEN
+ #define KEYPREFIX_LEN (8)
+#endif
+
+#ifndef GROUPID_LEN
+ #define GROUPID_LEN (8)
+#endif
+
+#endif /* #ifndef __IOTX_ALCS_CONFIG_H__ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm.c
new file mode 100644
index 00000000..17e199be
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm.c
@@ -0,0 +1,304 @@
+#include "iotx_cm_internal.h"
+
+#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
+#include "iotx_cm_mqtt.h"
+#endif
+#ifdef COAP_COMM_ENABLED
+#include "iotx_cm_coap.h"
+#endif
+
+
+static void *fd_lock = NULL;
+static iotx_cm_connection_t *_cm_fd[CM_MAX_FD_NUM] = {NULL};
+static int _get_fd(iotx_cm_connection_t *handle);
+static int _recycle_fd(int fd);
+static int inline _fd_is_valid(int fd);
+static int inited_conn_num = 0;
+
+#ifdef DEVICE_MODEL_GATEWAY
+ static void *_iotx_cm_yield_thread_func(void *params);
+ static void *yield_thread = NULL;
+ static int yield_task_leave = 1;
+#endif
+
+const char ERR_INVALID_PARAMS[] = "invalid parameter";
+int iotx_cm_open(iotx_cm_init_param_t *params)
+{
+ int fd;
+ iotx_cm_connection_t *connection = NULL;
+
+ switch (params->protocol_type) {
+ case IOTX_CM_PROTOCOL_TYPE_MQTT:
+#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
+ connection = iotx_cm_open_mqtt(params);
+#endif
+ break;
+ case IOTX_CM_PROTOCOL_TYPE_COAP:
+#ifdef COAP_COMM_ENABLED
+ connection = iotx_cm_open_coap(params);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ if (connection == NULL) {
+ cm_err("cm opon failed");
+ return -1;
+ }
+ fd = _get_fd(connection);
+ if (fd < 0) {
+ cm_err("get fd failed");
+ connection->close_func();
+ return -1;
+ }
+ connection->fd = fd;
+ return fd;
+}
+
+int iotx_cm_connect(int fd, uint32_t timeout)
+{
+ iotx_cm_connect_fp connect_func;
+ int ret;
+
+ if (_fd_is_valid(fd) == -1) {
+ cm_err(ERR_INVALID_PARAMS);
+ return -1;
+ }
+ HAL_MutexLock(fd_lock);
+ connect_func = _cm_fd[fd]->connect_func;
+ HAL_MutexUnlock(fd_lock);
+
+ iotx_event_post(IOTX_CONN_CLOUD);
+
+ ret = connect_func(timeout);
+
+ if (ret == 0) {
+ inited_conn_num++;
+ if (inited_conn_num == 1) {
+
+#ifdef DEVICE_MODEL_GATEWAY
+ int stack_used;
+ hal_os_thread_param_t task_parms = {0};
+ task_parms.stack_size = 6144;
+ task_parms.name = "cm_yield";
+ ret = HAL_ThreadCreate(&yield_thread, _iotx_cm_yield_thread_func, NULL,
+ &task_parms, &stack_used);
+ if (ret < 0) {
+ inited_conn_num--;
+ }
+#endif
+ }
+ iotx_event_post(IOTX_CONN_CLOUD_SUC);
+ } else {
+ iotx_event_post(IOTX_CONN_CLOUD_FAIL);
+ }
+
+
+ return ret;
+}
+
+static int _iotx_cm_yield(int fd, unsigned int timeout)
+{
+ iotx_cm_yield_fp yield_func;
+
+ if (fd_lock == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (fd == -1) {
+ int i;
+ for (i = 0; i < CM_MAX_FD_NUM; i++) {
+ yield_func = NULL;
+ HAL_MutexLock(fd_lock);
+ if (_cm_fd[i] != NULL) {
+ yield_func = _cm_fd[i]->yield_func;
+ }
+ HAL_MutexUnlock(fd_lock);
+ if (yield_func != NULL) {
+ yield_func(timeout);
+ }
+ }
+ return 0;
+ }
+
+ if (_fd_is_valid(fd) == -1) {
+ cm_err(ERR_INVALID_PARAMS);
+ return -1;
+ }
+
+ HAL_MutexLock(fd_lock);
+ yield_func = _cm_fd[fd]->yield_func;
+ HAL_MutexUnlock(fd_lock);
+ return yield_func(timeout);
+
+}
+#ifdef DEVICE_MODEL_GATEWAY
+static void *_iotx_cm_yield_thread_func(void *params)
+{
+ yield_task_leave = 0;
+ while (inited_conn_num > 0) {
+ _iotx_cm_yield(-1, CM_DEFAULT_YIELD_TIMEOUT);
+ }
+ yield_task_leave = 1;
+ return NULL;
+}
+#endif
+
+int iotx_cm_yield(int fd, unsigned int timeout)
+{
+#ifdef DEVICE_MODEL_GATEWAY
+ return 0;
+#else
+ return _iotx_cm_yield(fd, timeout);
+#endif
+}
+
+
+int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
+{
+ iotx_cm_sub_fp sub_func;
+
+ if (_fd_is_valid(fd) == -1) {
+ cm_err(ERR_INVALID_PARAMS);
+ return -1;
+ }
+
+ HAL_MutexLock(fd_lock);
+ sub_func = _cm_fd[fd]->sub_func;
+ HAL_MutexUnlock(fd_lock);
+ return sub_func(ext, topic, topic_handle_func, pcontext);
+}
+
+int iotx_cm_unsub(int fd, const char *topic)
+{
+ iotx_cm_unsub_fp unsub_func;
+
+ if (_fd_is_valid(fd) == -1) {
+ cm_err(ERR_INVALID_PARAMS);
+ return -1;
+ }
+
+ HAL_MutexLock(fd_lock);
+ unsub_func = _cm_fd[fd]->unsub_func;
+ HAL_MutexUnlock(fd_lock);
+ return unsub_func(topic);
+}
+
+
+
+int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
+{
+ iotx_cm_pub_fp pub_func;
+
+ if (_fd_is_valid(fd) == -1) {
+ cm_err(ERR_INVALID_PARAMS);
+ return -1;
+ }
+
+ HAL_MutexLock(fd_lock);
+ pub_func = _cm_fd[fd]->pub_func;
+ HAL_MutexUnlock(fd_lock);
+ return pub_func(ext, topic, payload, payload_len);
+}
+
+int iotx_cm_close(int fd)
+{
+ iotx_cm_close_fp close_func;
+
+ if (_fd_is_valid(fd) != 0) {
+ cm_err(ERR_INVALID_PARAMS);
+ return -1;
+ }
+
+ if (inited_conn_num > 0 && --inited_conn_num == 0) {
+#ifdef DEVICE_MODEL_GATEWAY
+ while (!yield_task_leave) {
+ HAL_SleepMs(10);
+ }
+ HAL_ThreadDelete(yield_thread);
+#endif
+ }
+
+ HAL_MutexLock(fd_lock);
+ close_func = _cm_fd[fd]->close_func;
+ HAL_MutexUnlock(fd_lock);
+ if (close_func() != 0) {
+ return -1;
+ }
+ if (_recycle_fd(fd) != 0) {
+ return -1;
+ }
+
+ if (inited_conn_num == 0) {
+ if (fd_lock != NULL) {
+ HAL_MutexDestroy(fd_lock);
+ fd_lock = NULL;
+ }
+ }
+
+ return 0;
+}
+
+
+static int inline _fd_is_valid(int fd)
+{
+ int ret;
+
+ if (fd_lock == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ HAL_MutexLock(fd_lock);
+ ret = (fd >= 0 && fd < CM_MAX_FD_NUM && _cm_fd[fd] != NULL) ? 0 : -1;
+ HAL_MutexUnlock(fd_lock);
+ return ret;
+}
+
+static int _recycle_fd(int fd)
+{
+ if (fd_lock == NULL) {
+ fd_lock = HAL_MutexCreate();
+ if (fd_lock == NULL) {
+ return -1;
+ }
+ }
+
+ if (fd < 0 || fd > CM_MAX_FD_NUM - 1) {
+ return -1;
+ }
+
+ HAL_MutexLock(fd_lock);
+ _cm_fd[fd] = NULL;
+ HAL_MutexUnlock(fd_lock);
+
+ return 0;
+}
+
+static int _get_fd(iotx_cm_connection_t *handle)
+{
+ int i;
+ if (handle == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (fd_lock == NULL) {
+ fd_lock = HAL_MutexCreate();
+ if (fd_lock == NULL) {
+ return -1;
+ }
+ }
+
+ HAL_MutexLock(fd_lock);
+ for (i = 0; i < CM_MAX_FD_NUM; i++) {
+ if (_cm_fd[i] == NULL) {
+ _cm_fd[i] = handle;
+ HAL_MutexUnlock(fd_lock);
+ return i;
+ }
+ }
+ HAL_MutexUnlock(fd_lock);
+ cm_err("cm fd reached the limit");
+ return -1;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm.h
new file mode 100644
index 00000000..877b1032
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef _IOTX_CM_H_
+#define _IOTX_CM_H_
+
+#include "infra_types.h"
+
+#define CM_MAX_FD_NUM 3
+#define CM_DEFAULT_YIELD_TIMEOUT 200
+/* message confirmation type */
+typedef enum {
+ /* non ACK */
+ /* MQTT: QoS is 0 */
+ /* CoAP: NON */
+ /* default */
+ IOTX_CM_MESSAGE_NO_ACK,
+ /* need ACK */
+ /* MQTT: QoS is 1 */
+ /* CoAP: CON */
+ IOTX_CM_MESSAGE_NEED_ACK,
+ /* non ACK */
+ /* MQTT: QoS is 3 */
+ /* CoAP: NONE*/
+ IOTX_CM_MESSAGE_SUB_LOCAL,
+ /* Maximum number of ack type */
+ IOTX_CM_MESSAGE_ACK_MAX
+} iotx_cm_ack_types_t;
+
+/* message confirmation type */
+typedef enum {
+ /* non ACK */
+ /* MQTT: QoS is 0 */
+ /* CoAP: NON */
+ /* default */
+ IOTX_CM_ASYNC,
+ /* need ACK */
+ /* MQTT: QoS is 1 */
+ /* CoAP: CON */
+ IOTX_CM_SYNC,
+ /* Maximum number of ack type */
+ IOTX_CM_SYNC_MAX
+} iotx_cm_sync_mode_types_t;
+
+/* protocol type */
+typedef enum IOTX_CM_PROTOCOL_TYPES {
+ /* MQTT */
+ IOTX_CM_PROTOCOL_TYPE_MQTT = 1,
+ /* COAP */
+ IOTX_CM_PROTOCOL_TYPE_COAP = 2,
+ /* HTTP */
+ IOTX_CM_PROTOCOL_TYPE_HTTP = 3,
+ /* HTTP2 */
+ IOTX_CM_PROTOCOL_TYPE_HTTP2 = 4,
+ /* Maximum number of protocol type */
+ IOTX_CM_PROTOCOL_TYPE_MAX
+} iotx_cm_protocol_types_t;
+
+
+/* event type */
+typedef enum IOTX_CM_EVENT_TYPES {
+ /* cloud connected */
+ IOTX_CM_EVENT_CLOUD_CONNECTED = 0,
+ /* cloud: disconnect */
+ /* event_msg is null */
+ IOTX_CM_EVENT_CLOUD_CONNECT_FAILED,
+ /* cloud: disconnect */
+ /* event_msg is null */
+ IOTX_CM_EVENT_CLOUD_DISCONNECT,
+ /* event_msg is iotx_cm_event_result_pt */
+ IOTX_CM_EVENT_SUBCRIBE_SUCCESS,
+ IOTX_CM_EVENT_SUBCRIBE_FAILED,
+ IOTX_CM_EVENT_UNSUB_SUCCESS,
+ IOTX_CM_EVENT_UNSUB_FAILED,
+ IOTX_CM_EVENT_PUBLISH_SUCCESS,
+ IOTX_CM_EVENT_PUBLISH_FAILED,
+ /* Maximum number of event */
+ IOTX_CM_EVENT_MAX
+} iotx_cm_event_types_t;
+
+/* The structure of cloud Connection event struct */
+typedef struct {
+ iotx_cm_event_types_t type;
+ void *msg;
+} iotx_cm_event_msg_t;
+
+typedef struct {
+ char *topic;
+ uint8_t *payload;
+ uint32_t payload_len;
+} event_msg_data_t;
+
+#ifdef DEVICE_MODEL_ALINK2
+typedef void (*iotx_cm_data_handle_cb)(int fd, const char *topic, uint32_t topic_len, const char *payload, unsigned int payload_len, void *context);
+#else
+typedef void (*iotx_cm_data_handle_cb)(int fd, const char *topic, const char *payload, unsigned int payload_len,
+ void *context);
+#endif
+
+typedef void (*iotx_cm_event_handle_cb)(int fd, iotx_cm_event_msg_t *event, void *context);
+
+
+/* IoTx initializa parameters */
+typedef struct {
+ uint32_t request_timeout_ms;
+ uint32_t keepalive_interval_ms;
+ uint32_t write_buf_size;
+ uint32_t read_buf_size;
+ iotx_cm_protocol_types_t protocol_type;
+ iotx_cm_event_handle_cb handle_event; /* Specify MQTT event handle */
+ void *context;
+#ifdef DEVICE_MODEL_ALINK2
+ iotx_dev_meta_info_t *dev_info;
+ iotx_mqtt_region_types_t region;
+#endif
+} iotx_cm_init_param_t;
+
+typedef struct {
+ iotx_cm_ack_types_t ack_type;
+ iotx_cm_sync_mode_types_t sync_mode;
+ uint32_t sync_timeout;
+ iotx_cm_data_handle_cb ack_cb;
+ void *cb_context;
+} iotx_cm_ext_params_t;
+
+int iotx_cm_open(iotx_cm_init_param_t *params);
+int iotx_cm_connect(int fd, uint32_t timeout);
+int iotx_cm_yield(int fd, unsigned int timeout);
+int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
+int iotx_cm_unsub(int fd, const char *topic);
+int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len);
+int iotx_cm_close(int fd);
+#endif /* _LINKKIT_CM_H_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_coap.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_coap.c
new file mode 100644
index 00000000..10a24665
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_coap.c
@@ -0,0 +1,408 @@
+#include "iotx_cm_internal.h"
+
+#ifdef COAP_COMM_ENABLED
+#include "iotx_cm.h"
+#include "iotx_cm_coap.h"
+#include "infra_timer.h"
+
+#ifdef COAP_DTLS_SUPPORT /* DTLS */
+ #ifdef ON_DAILY
+ #define IOTX_COAP_SERVER_URI "coaps://11.239.164.238:5684"
+ #else
+ #ifdef ON_PRE
+ #define IOTX_COAP_SERVER_URI "coaps://pre.coap.cn-shanghai.link.aliyuncs.com:5684"
+
+ #else /* online */
+ #define IOTX_COAP_SERVER_URI "coaps://%s.coap.cn-shanghai.link.aliyuncs.com:5684"
+ #endif
+ #endif
+
+#else
+ #ifdef COAP_PSK_SUPPORT /* PSK */
+ #ifdef ON_DAILY
+ #define IOTX_COAP_SERVER_URI "coap-psk://10.101.83.159:5682"
+ #else
+ #ifdef ON_PRE
+ #define IOTX_COAP_SERVER_URI "coap-psk://pre.coap.cn-shanghai.link.aliyuncs.com:5682"
+ #else /* online */
+ #define IOTX_COAP_SERVER_URI "coap-psk://%s.coap.cn-shanghai.link.aliyuncs.com:5682"
+ #endif
+ #endif
+ #else /* UDP */
+ #ifdef ON_DAILY
+ #define IOTX_COAP_SERVER_URI ""
+ #else
+ #ifdef ON_PRE
+ #define IOTX_COAP_SERVER_URI "coap://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5683"
+ #else /* online */
+ #define IOTX_COAP_SERVER_URI "coap://%s.coap.cn-shanghai.link.aliyuncs.com:5683"
+ #endif
+ #endif
+
+ #endif
+#endif
+
+extern uint32_t IOT_CoAP_GetCurToken(iotx_coap_context_t *p_context);
+int IOT_CoAP_GetMessageToken(void *p_message, unsigned int *token);
+static struct list_head g_coap_response_list = LIST_HEAD_INIT(g_coap_response_list);
+
+static iotx_cm_connection_t *_coap_conncection = NULL;
+static int iotx_set_devinfo(iotx_device_info_t *p_devinfo);
+
+static int _coap_connect(uint32_t timeout);
+static int _coap_publish(iotx_cm_ext_params_t *params, const char *topic, const char *payload,
+ unsigned int payload_len);
+static int _coap_sub(iotx_cm_ext_params_t *params, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
+static iotx_msg_type_t _get_coap_qos(iotx_cm_ack_types_t ack_type);
+static int _coap_unsub(const char *topic);
+static int _coap_close();
+static void _set_common_handlers();
+
+iotx_cm_connection_t *iotx_cm_open_coap(iotx_cm_init_param_t *params)
+{
+ iotx_coap_config_t *coap_config = NULL;
+ iotx_device_info_t *deviceinfo = NULL;
+
+ if (_coap_conncection != NULL) {
+ cm_warning("mqtt connection is opened already,return it");
+ return _coap_conncection;
+ }
+
+ _coap_conncection = (iotx_cm_connection_t *)cm_malloc(sizeof(iotx_cm_connection_t));
+ if (_coap_conncection == NULL) {
+ cm_err("_coap_conncection malloc failed!");
+ goto failed;
+ }
+
+ _coap_conncection->list_lock = HAL_MutexCreate();
+ if (_coap_conncection->list_lock == NULL) {
+ cm_err("list_lock create failed!");
+ goto failed;
+ }
+
+ coap_config = (iotx_coap_config_t *)cm_malloc(sizeof(iotx_coap_config_t));
+ if (coap_config == NULL) {
+ cm_err("coap_config malloc failed!");
+ goto failed;
+ }
+ memset(coap_config, 0, sizeof(iotx_coap_config_t));
+ deviceinfo = (iotx_device_info_t *)cm_malloc(sizeof(iotx_device_info_t));
+ if (deviceinfo == NULL) {
+ cm_err("deviceinfo malloc failed!");
+ goto failed;
+ }
+
+ _coap_conncection->open_params = coap_config;
+
+ memset(deviceinfo, 0, sizeof(iotx_device_info_t));
+
+ iotx_set_devinfo(deviceinfo);
+ coap_config->wait_time_ms = params->request_timeout_ms;
+ coap_config->p_devinfo = deviceinfo;
+ /* coap_config->p_url = IOTX_COAP_SERVER_URI; */
+
+ _coap_conncection->event_handler = params->handle_event;
+
+ _set_common_handlers();
+
+ return _coap_conncection;
+
+failed:
+ if (_coap_conncection != NULL) {
+ if (_coap_conncection->list_lock != NULL) {
+ HAL_MutexDestroy(_coap_conncection->list_lock);
+ }
+ cm_free(_coap_conncection);
+ _coap_conncection = NULL;
+ }
+
+ if (coap_config != NULL) {
+ cm_free(coap_config);
+ }
+ if (deviceinfo != NULL) {
+ cm_free(deviceinfo);
+ }
+
+ return NULL;
+}
+
+static int iotx_set_devinfo(iotx_device_info_t *p_devinfo)
+{
+ if (NULL == p_devinfo) {
+ return IOTX_ERR_INVALID_PARAM;
+ }
+
+ memset(p_devinfo, 0x00, sizeof(iotx_device_info_t));
+
+ /**< get device info*/
+ HAL_GetProductKey(p_devinfo->product_key);
+ HAL_GetDeviceName(p_devinfo->device_name);
+ HAL_GetDeviceSecret(p_devinfo->device_secret);
+ HAL_Snprintf(p_devinfo->device_id, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2, "%s.%s", p_devinfo->product_key, p_devinfo->device_name);
+ p_devinfo->device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = '\0';
+ /**< end*/
+ cm_info("*****The Product Key : %s *****\r\n", p_devinfo->product_key);
+ cm_info("*****The Device Name : %s *****\r\n", p_devinfo->device_name);
+ cm_info("*****The Device Secret: %s *****\r\n", p_devinfo->device_secret);
+ cm_info("*****The Device ID : %s *****\r\n", p_devinfo->device_id);
+ return IOTX_SUCCESS;
+}
+
+static int _coap_connect(uint32_t timeout)
+{
+ int ret;
+ char url[100] = {0};
+ iotx_time_t timer;
+ iotx_coap_config_t *config = NULL;
+ iotx_coap_context_t *p_ctx = NULL;
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+
+ if (_coap_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ HAL_GetProductKey(product_key);
+ config = _coap_conncection->open_params;
+ if (config == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ HAL_Snprintf(url, 100, IOTX_COAP_SERVER_URI, product_key);
+ config->p_url = url;
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout);
+ do {
+ if (p_ctx == NULL) {
+ p_ctx = IOT_CoAP_Init(config);
+ if (NULL == p_ctx) {
+ continue;
+ }
+ }
+ ret = IOT_CoAP_DeviceNameAuth(p_ctx);
+ if (ret == 0) {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
+ event.msg = NULL;
+ _coap_conncection->context = p_ctx;
+
+ if (_coap_conncection->event_handler) {
+ _coap_conncection->event_handler(_coap_conncection->fd, &event, (void *)_coap_conncection);
+ }
+ return 0;
+ }
+ } while (!utils_time_is_expired(&timer));
+
+ {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_CLOUD_CONNECT_FAILED;
+ event.msg = NULL;
+
+ if (_coap_conncection->event_handler) {
+ _coap_conncection->event_handler(_coap_conncection->fd, &event, (void *)_coap_conncection);
+ }
+ }
+ cm_err("mqtt connect failed");
+ return -1;
+}
+
+static void _coap_response_default(void *p_arg, void *p_message)
+{
+ int ret;
+ int len = 0;
+ unsigned char *p_payload = NULL;
+ unsigned int token;
+ iotx_coap_resp_code_t resp_code;
+ coap_response_node_t *node = NULL;
+ coap_response_node_t *next = NULL;
+
+ if (_coap_conncection == NULL || p_message == NULL) {
+ cm_err("paras err");
+ return;
+ }
+
+ ret = IOT_CoAP_GetMessageCode(p_message, &resp_code);
+ if (ret < 0) {
+ cm_err("get msg code err");
+ return;
+ }
+
+ cm_info("resp_code = %d", resp_code);
+
+ ret = IOT_CoAP_GetMessagePayload(p_message, &p_payload, &len);
+ if (ret < 0) {
+ cm_err("get msg payload err");
+ return;
+ }
+
+ ret = IOT_CoAP_GetMessageToken(p_message, &token);
+ if (ret < 0) {
+ cm_err("get msg token err");
+ return;
+ }
+
+ HAL_MutexLock(_coap_conncection->list_lock);
+ list_for_each_entry_safe(node, next, &g_coap_response_list, linked_list, coap_response_node_t) {
+ if (node->token_num == token) {
+ iotx_cm_data_handle_cb recieve_cb = node->responce_cb;
+ void *context = node->context;
+ unsigned int topic_len = strlen(node->topic) + 1;
+ char *topic = cm_malloc(topic_len);
+ if (topic == NULL) {
+ cm_err("topic malloc failed");
+ continue;
+ }
+ memset(topic, 0, topic_len);
+ strncpy(topic, node->topic, topic_len);
+ list_del(&node->linked_list);
+ cm_free(node->topic);
+ cm_free(node);
+ HAL_MutexUnlock(_coap_conncection->list_lock); /* do not lock while callback */
+
+ recieve_cb(_coap_conncection->fd, topic, (const char *)p_payload, len, context);
+ /* recieve_cb(_coap_conncection->fd, &msg, context); */
+ cm_free(topic);
+ HAL_MutexLock(_coap_conncection->list_lock);
+ }
+ }
+ HAL_MutexUnlock(_coap_conncection->list_lock);
+}
+
+
+static int _coap_publish(iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
+{
+ iotx_msg_type_t qos = 0;
+ iotx_message_t message;
+ uint32_t token;
+ int topic_len;
+ int ret;
+
+ if (_coap_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (ext != NULL) {
+ qos = _get_coap_qos(ext->ack_type);
+ }
+ memset(&message, 0, sizeof(iotx_message_t));
+
+ message.p_payload = (unsigned char *)payload;
+ message.payload_len = payload_len;
+ message.resp_callback = _coap_response_default;
+ message.msg_type = qos;
+ message.content_type = IOTX_CONTENT_TYPE_JSON;
+
+ token = IOT_CoAP_GetCurToken((iotx_coap_context_t *)_coap_conncection->context);
+ ret = IOT_CoAP_SendMessage((iotx_coap_context_t *)_coap_conncection->context, (char *)topic, &message);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ if (ext != NULL && ext->ack_cb != NULL) {
+ coap_response_node_t *node;
+ node = (coap_response_node_t *)cm_malloc(sizeof(coap_response_node_t));
+ if (node == NULL) {
+ return -1;
+ }
+ memset(node, 0, sizeof(coap_response_node_t));
+ topic_len = strlen(topic) + 1;
+ node->topic = (char *)cm_malloc(topic_len);
+ if (node->topic == NULL) {
+ cm_free(node);
+ return -1;
+ }
+
+ memset(node->topic, 0, topic_len);
+ strncpy(node->topic, topic, topic_len);
+
+ node->user_data = _coap_conncection;
+ node->responce_cb = ext->ack_cb;
+ node->context = ext->cb_context;
+ node->token_num = token;
+
+ HAL_MutexLock(_coap_conncection->list_lock);
+ list_add_tail(&node->linked_list, &g_coap_response_list);
+ HAL_MutexUnlock(_coap_conncection->list_lock);
+ }
+ return 0;
+}
+
+static int _coap_yield(uint32_t timeout)
+{
+ if (_coap_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+ return IOT_CoAP_Yield((iotx_coap_context_t *)_coap_conncection->context);
+}
+
+static int _coap_sub(iotx_cm_ext_params_t *ext, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
+{
+ return 0;
+}
+
+static int _coap_unsub(const char *topic)
+{
+ return 0;
+}
+
+static int _coap_close()
+{
+ coap_response_node_t *node = NULL;
+ coap_response_node_t *next = NULL;
+ iotx_coap_config_t *coap_config = NULL;
+
+ if (_coap_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ coap_config = (iotx_coap_config_t *)_coap_conncection->open_params;
+
+ HAL_MutexLock(_coap_conncection->list_lock);
+ list_for_each_entry_safe(node, next, &g_coap_response_list, linked_list, coap_response_node_t) {
+ cm_free(node->topic);
+ list_del(&node->linked_list);
+ cm_free(node);
+ }
+ HAL_MutexUnlock(_coap_conncection->list_lock);
+
+ if (_coap_conncection->list_lock != NULL) {
+ HAL_MutexDestroy(_coap_conncection->list_lock);
+ }
+ cm_free(coap_config->p_devinfo);
+ cm_free(coap_config);
+ IOT_CoAP_Deinit(&_coap_conncection->context);
+
+ cm_free(_coap_conncection);
+ _coap_conncection = NULL;
+ return 0;
+}
+
+static iotx_msg_type_t _get_coap_qos(iotx_cm_ack_types_t ack_type)
+{
+ switch (ack_type) {
+ case IOTX_CM_MESSAGE_NO_ACK:
+ return IOTX_MESSAGE_NON;
+
+ case IOTX_CM_MESSAGE_NEED_ACK:
+ return IOTX_MESSAGE_CON;
+
+ default:
+ return IOTX_MESSAGE_CON;
+ }
+}
+
+static void _set_common_handlers()
+{
+ if (_coap_conncection != NULL) {
+ _coap_conncection->connect_func = _coap_connect;
+ _coap_conncection->sub_func = _coap_sub;
+ _coap_conncection->unsub_func = _coap_unsub;
+ _coap_conncection->pub_func = _coap_publish;
+ _coap_conncection->yield_func = _coap_yield;
+ _coap_conncection->close_func = _coap_close;
+ }
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_coap.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_coap.h
new file mode 100644
index 00000000..9d664b3c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_coap.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOTX_CM_COAP_H_
+#define _IOTX_CM_COAP_H_
+#include "iotx_cm.h"
+#include "iotx_cm_internal.h"
+#include "coap_api.h"
+
+
+typedef struct {
+ uint32_t token_num;
+ void *user_data;
+ char *topic;
+ iotx_cm_data_handle_cb responce_cb;
+ void *context;
+ dlist_t linked_list;
+} coap_response_node_t;
+
+iotx_cm_connection_t *iotx_cm_open_coap(iotx_cm_init_param_t *params);
+
+#endif /* _LINKKIT_CM_H_ */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_internal.h
new file mode 100644
index 00000000..ca9fccd3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_internal.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef _IOTX_CM_INTERNAL_H_
+#define _IOTX_CM_INTERNAL_H_
+
+#include
+
+#include "infra_config.h"
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_list.h"
+#include "infra_compat.h"
+#include "infra_timer.h"
+
+#include "dm_wrapper.h"
+#include "mqtt_api.h"
+
+#include "iotx_cm.h"
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define cm_malloc(size) LITE_malloc(size, MEM_MAGIC, "cm")
+ #define cm_free(ptr) LITE_free(ptr)
+#else
+ #define cm_malloc(size) HAL_Malloc(size)
+ #define cm_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define cm_debug(...) log_debug("CM", __VA_ARGS__)
+ #define cm_info(...) log_info("CM", __VA_ARGS__)
+ #define cm_warning(...) log_warning("CM", __VA_ARGS__)
+ #define cm_err(...) log_err("CM", __VA_ARGS__)
+#else
+ #define cm_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define cm_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define cm_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define cm_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+typedef int (*iotx_cm_connect_fp)(uint32_t timeout);
+typedef int (*iotx_cm_yield_fp)(unsigned int timeout);
+typedef int (*iotx_cm_sub_fp)(iotx_cm_ext_params_t *params, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
+typedef int (*iotx_cm_unsub_fp)(const char *topic);
+typedef int (*iotx_cm_pub_fp)(iotx_cm_ext_params_t *params, const char *topic, const char *payload,
+ unsigned int payload_len);
+typedef int (*iotx_cm_close_fp)();
+
+
+typedef struct iotx_connection_st {
+ int fd;
+ void *open_params;
+ void *context;
+ void *list_lock;
+ iotx_cm_protocol_types_t protocol_type;
+ iotx_cm_connect_fp connect_func;
+ iotx_cm_sub_fp sub_func;
+ iotx_cm_unsub_fp unsub_func;
+ iotx_cm_pub_fp pub_func;
+ iotx_cm_yield_fp yield_func;
+ iotx_cm_close_fp close_func;
+ iotx_cm_event_handle_cb event_handler;
+ void *cb_data;
+
+} iotx_cm_connection_t;
+
+#include "iotx_cm_mqtt.h"
+
+extern const char ERR_INVALID_PARAMS[];
+#endif /* _LINKKIT_CM_H_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_mqtt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_mqtt.c
new file mode 100644
index 00000000..6ae59f05
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_mqtt.c
@@ -0,0 +1,404 @@
+#include "iotx_cm_internal.h"
+
+#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
+
+static iotx_cm_connection_t *_mqtt_conncection = NULL;
+static void iotx_cloud_conn_mqtt_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg);
+static int _mqtt_connect(uint32_t timeout);
+static int _mqtt_publish(iotx_cm_ext_params_t *params, const char *topic, const char *payload,
+ unsigned int payload_len);
+static int _mqtt_sub(iotx_cm_ext_params_t *params, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
+static iotx_mqtt_qos_t _get_mqtt_qos(iotx_cm_ack_types_t ack_type);
+static int _mqtt_unsub(const char *topic);
+static int _mqtt_close();
+static void _set_common_handlers();
+
+iotx_cm_connection_t *iotx_cm_open_mqtt(iotx_cm_init_param_t *params)
+{
+ iotx_mqtt_param_t *mqtt_param = NULL;
+
+ if (_mqtt_conncection != NULL) {
+ cm_warning("mqtt connection is opened already,return it");
+ return _mqtt_conncection;
+ }
+
+ _mqtt_conncection = (iotx_cm_connection_t *)cm_malloc(sizeof(iotx_cm_connection_t));
+ if (_mqtt_conncection == NULL) {
+ cm_err("_mqtt_conncection malloc failed!");
+ goto failed;
+ }
+
+ mqtt_param = (iotx_mqtt_param_t *)cm_malloc(sizeof(iotx_mqtt_param_t));
+ if (mqtt_param == NULL) {
+ cm_err("mqtt_param malloc failed!");
+ goto failed;
+ }
+ _mqtt_conncection->open_params = mqtt_param;
+
+ mqtt_param->request_timeout_ms = params->request_timeout_ms;
+ mqtt_param->clean_session = 0;
+ mqtt_param->keepalive_interval_ms = params->keepalive_interval_ms;
+ mqtt_param->read_buf_size = params->read_buf_size;
+ mqtt_param->write_buf_size = params->write_buf_size;
+
+ mqtt_param->handle_event.h_fp = iotx_cloud_conn_mqtt_event_handle;
+ mqtt_param->handle_event.pcontext = NULL;
+
+ _mqtt_conncection->event_handler = params->handle_event;
+ _mqtt_conncection->cb_data = params->context;
+ _set_common_handlers();
+
+ return _mqtt_conncection;
+
+failed:
+
+ if (_mqtt_conncection != NULL) {
+ cm_free(_mqtt_conncection);
+ _mqtt_conncection = NULL;
+ }
+
+ if (mqtt_param != NULL) {
+ cm_free(mqtt_param);
+ }
+
+ return NULL;
+}
+
+
+static void iotx_cloud_conn_mqtt_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
+{
+ uintptr_t packet_id = (uintptr_t)msg->msg;
+ if (_mqtt_conncection == NULL) {
+ return;
+ }
+
+ switch (msg->event_type) {
+
+ case IOTX_MQTT_EVENT_DISCONNECT: {
+ iotx_cm_event_msg_t event;
+ cm_info("disconnected,fd = %d", _mqtt_conncection->fd);
+ event.type = IOTX_CM_EVENT_CLOUD_DISCONNECT;
+ event.msg = NULL;
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_RECONNECT: {
+ iotx_cm_event_msg_t event;
+ cm_info("connected,fd = %d", _mqtt_conncection->fd);
+ event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
+ event.msg = NULL;
+ /* cm_info(cm_log_info_MQTT_reconnect); */
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_SUBCRIBE_SUCCESS;
+ event.msg = (void *)packet_id;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_SUBCRIBE_NACK:
+ case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_SUBCRIBE_FAILED;
+ event.msg = (void *)packet_id;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_UNSUB_SUCCESS;
+ event.msg = (void *)packet_id;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK:
+ case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_UNSUB_FAILED;
+ event.msg = (void *)packet_id;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_PUBLISH_SUCCESS;
+ event.msg = (void *)packet_id;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_PUBLISH_NACK:
+ case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: {
+ iotx_cm_event_msg_t event;
+ event.type = IOTX_CM_EVENT_PUBLISH_FAILED;
+ event.msg = (void *)packet_id;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
+ }
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: {
+ iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg;
+ iotx_cm_data_handle_cb topic_handle_func = (iotx_cm_data_handle_cb)pcontext;
+#ifndef DEVICE_MODEL_ALINK2
+ char *topic = NULL;
+#endif
+ if (topic_handle_func == NULL) {
+ cm_warning("bypass %d bytes on [%.*s]", topic_info->payload_len, topic_info->topic_len, topic_info->ptopic);
+ return;
+ }
+#ifdef DEVICE_MODEL_ALINK2
+ topic_handle_func(_mqtt_conncection->fd, topic_info->ptopic, topic_info->topic_len, topic_info->payload,
+ topic_info->payload_len, NULL);
+#else
+ topic = cm_malloc(topic_info->topic_len + 1);
+ if (topic == NULL) {
+ cm_err("topic malloc failed");
+ return;
+ }
+ memset(topic, 0, topic_info->topic_len + 1);
+ memcpy(topic, topic_info->ptopic, topic_info->topic_len);
+
+ topic_handle_func(_mqtt_conncection->fd, topic, topic_info->payload, topic_info->payload_len, NULL);
+
+ cm_free(topic);
+#endif
+ }
+ break;
+
+ case IOTX_MQTT_EVENT_BUFFER_OVERFLOW:
+ cm_warning("buffer overflow", msg->msg);
+ break;
+
+ default:
+ cm_warning("msg type unkown, type = %d", msg->event_type);
+ break;
+ }
+}
+
+
+static int _mqtt_connect(uint32_t timeout)
+{
+ void *pclient;
+ iotx_time_t timer;
+ iotx_mqtt_param_t *mqtt_param = NULL;
+ iotx_conn_info_pt pconn_info = NULL;
+ iotx_cm_event_msg_t event;
+
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+
+ if (_mqtt_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ mqtt_param = _mqtt_conncection->open_params;
+
+ HAL_GetProductKey(product_key);
+ HAL_GetDeviceName(device_name);
+ HAL_GetDeviceSecret(device_secret);
+
+ if (strlen(product_key) == 0 || strlen(device_name) == 0) {
+ return FAIL_RETURN;
+ }
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout);
+ /* Device AUTH */
+ do {
+ if (0 == IOT_SetupConnInfo(product_key, device_name, device_secret, (void **)&pconn_info)) {
+ mqtt_param->port = pconn_info->port;
+ mqtt_param->host = pconn_info->host_name;
+ mqtt_param->client_id = pconn_info->client_id;
+ mqtt_param->username = pconn_info->username;
+ mqtt_param->password = pconn_info->password;
+ mqtt_param->pub_key = pconn_info->pub_key;
+ break;
+ }
+ cm_err("IOT_SetupConnInfo failed");
+ HAL_SleepMs(500);
+ } while (!utils_time_is_expired(&timer));
+
+ do {
+ pclient = IOT_MQTT_Construct((iotx_mqtt_param_t *)_mqtt_conncection->open_params);
+ if (pclient != NULL) {
+ iotx_cm_event_msg_t event;
+ _mqtt_conncection->context = pclient;
+ event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
+ event.msg = NULL;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, (void *)_mqtt_conncection);
+ }
+ return 0;
+ }
+ HAL_SleepMs(500);
+ } while (!utils_time_is_expired(&timer));
+
+ event.type = IOTX_CM_EVENT_CLOUD_CONNECT_FAILED;
+ event.msg = NULL;
+
+ if (_mqtt_conncection->event_handler) {
+ _mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, (void *)_mqtt_conncection);
+ }
+ cm_err("mqtt connect failed");
+ return -1;
+}
+
+static int _mqtt_publish(iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
+{
+ int qos = 0;
+
+ if (_mqtt_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (ext != NULL) {
+ qos = (int)_get_mqtt_qos(ext->ack_type);
+ }
+ return IOT_MQTT_Publish_Simple(_mqtt_conncection->context, topic, qos, (void *)payload, payload_len);
+}
+
+static int _mqtt_yield(uint32_t timeout)
+{
+ if (_mqtt_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ return IOT_MQTT_Yield(_mqtt_conncection->context, timeout);
+}
+
+static int _mqtt_sub(iotx_cm_ext_params_t *ext, const char *topic,
+ iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
+{
+
+ int sync = 0;
+ int qos = 0;
+ int timeout = 0;
+ int ret;
+
+ if (_mqtt_conncection == NULL || topic == NULL || topic_handle_func == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (ext != NULL) {
+ if (ext->sync_mode == IOTX_CM_ASYNC) {
+ sync = 0;
+ } else {
+ sync = 1;
+ timeout = ext->sync_timeout;
+ }
+ qos = (int)_get_mqtt_qos(ext->ack_type);
+ }
+
+ if (sync != 0) {
+ ret = IOT_MQTT_Subscribe_Sync(_mqtt_conncection->context,
+ topic,
+ qos,
+ iotx_cloud_conn_mqtt_event_handle,
+ (void *)topic_handle_func,
+ timeout);
+ } else {
+ ret = IOT_MQTT_Subscribe(_mqtt_conncection->context,
+ topic,
+ qos,
+ iotx_cloud_conn_mqtt_event_handle,
+ (void *)topic_handle_func);
+ }
+
+ return ret;
+}
+
+static int _mqtt_unsub(const char *topic)
+{
+ int ret;
+
+ if (_mqtt_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ ret = IOT_MQTT_Unsubscribe(_mqtt_conncection->context, topic);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ return ret;
+}
+
+static int _mqtt_close()
+{
+ if (_mqtt_conncection == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ cm_free(_mqtt_conncection->open_params);
+ IOT_MQTT_Destroy(&_mqtt_conncection->context);
+ cm_free(_mqtt_conncection);
+ _mqtt_conncection = NULL;
+ return 0;
+}
+
+static iotx_mqtt_qos_t _get_mqtt_qos(iotx_cm_ack_types_t ack_type)
+{
+ switch (ack_type) {
+ case IOTX_CM_MESSAGE_NO_ACK:
+ return IOTX_MQTT_QOS0;
+
+ case IOTX_CM_MESSAGE_NEED_ACK:
+ return IOTX_MQTT_QOS1;
+
+ case IOTX_CM_MESSAGE_SUB_LOCAL:
+ return IOTX_MQTT_QOS3_SUB_LOCAL;
+
+ default:
+ return IOTX_MQTT_QOS0;
+ }
+}
+
+
+static void _set_common_handlers()
+{
+ if (_mqtt_conncection != NULL) {
+ _mqtt_conncection->connect_func = _mqtt_connect;
+ _mqtt_conncection->sub_func = _mqtt_sub;
+ _mqtt_conncection->unsub_func = _mqtt_unsub;
+ _mqtt_conncection->pub_func = _mqtt_publish;
+ _mqtt_conncection->yield_func = (iotx_cm_yield_fp)_mqtt_yield;
+ _mqtt_conncection->close_func = _mqtt_close;
+ }
+}
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_mqtt.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_mqtt.h
new file mode 100644
index 00000000..90b42890
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_cm_mqtt.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef _IOTX_CM_MQTT_H_
+#define _IOTX_CM_MQTT_H_
+
+#include "iotx_cm.h"
+#include "iotx_cm_internal.h"
+
+
+typedef struct {
+ uintptr_t packet_id;
+ char * topic;
+ void * user_data;
+ iotx_mqtt_event_handle_func_fpt sub_state_cb;
+ iotx_cm_data_handle_cb sub_recieve_cb;
+ dlist_t linked_list;
+} mqtt_sub_node_t;
+
+iotx_cm_connection_t *iotx_cm_open_mqtt(iotx_cm_init_param_t *params);
+
+
+#endif /* _LINKKIT_CM_H_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm.h
new file mode 100644
index 00000000..b9b7929e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _IOT_EXPORT_DM_H_
+#define _IOT_EXPORT_DM_H_
+
+#ifndef _IN_
+ #define _IN_
+#endif
+
+#ifndef _OU_
+ #define _OU_
+#endif
+
+#ifdef DEVICE_MODEL_GATEWAY
+ #define IOTX_DM_DEVICE_TYPE IOTX_DM_DEVICE_GATEWAY
+#else
+ #define IOTX_DM_DEVICE_TYPE IOTX_DM_DEVICE_SINGLE
+#endif
+
+#define IOTX_DM_LOCAL_NODE_DEVID (0)
+
+#define IOTX_DM_DEVICE_SINGLE (0x01)
+#define IOTX_DM_DEVICE_SUBDEV (0x02)
+#define IOTX_DM_DEVICE_GATEWAY (0x04)
+#define IOTX_DM_DEVICE_MAIN (IOTX_DM_DEVICE_SINGLE|IOTX_DM_DEVICE_GATEWAY)
+#define IOTX_DM_DEVICE_ALL (IOTX_DM_DEVICE_SINGLE|IOTX_DM_DEVICE_SUBDEV|IOTX_DM_DEVICE_GATEWAY)
+
+/* Service Type 0~7bit: type, 8~15bit: extended*/
+#define IOTX_DM_SERVICE_CLOUD (0x0001)
+#define IOTX_DM_SERVICE_LOCAL (0x0002)
+#define IOTX_DM_SERVICE_LOCAL_NO_AUTH (0x0000)
+#define IOTX_DM_SERVICE_LOCAL_AUTH (0x0100)
+
+#define IOTX_DM_LOCAL_AUTH (IOTX_DM_SERVICE_LOCAL|IOTX_DM_SERVICE_LOCAL_AUTH)
+#define IOTX_DM_LOCAL_NO_AUTH (IOTX_DM_SERVICE_LOCAL|IOTX_DM_SERVICE_LOCAL_NO_AUTH)
+
+#define IOTX_DM_SERVICE_ALL (IOTX_DM_SERVICE_CLOUD|IOTX_DM_LOCAL_AUTH)
+
+typedef enum {
+ IOTX_DM_ERR_CODE_SUCCESS = 200,
+ IOTX_DM_ERR_CODE_REQUEST_ERROR = 400,
+ IOTX_DM_ERR_CODE_REQUEST_PARAMS_ERROR = 460,
+ IOTX_DM_ERR_CODE_REQUEST_TOO_MANY = 429,
+ IOTX_DM_ERR_CODE_NO_ACTIVE_SESSION = 520,
+ IOTX_DM_ERR_CODE_TIMEOUT = 100000
+} iotx_dm_error_code_t;
+
+typedef enum {
+ IOTX_DM_EVENT_CLOUD_CONNECTED = 0,
+ IOTX_DM_EVENT_CLOUD_DISCONNECT,
+ IOTX_DM_EVENT_CLOUD_RECONNECT,
+ IOTX_DM_EVENT_LOCAL_CONNECTED,
+ IOTX_DM_EVENT_LOCAL_DISCONNECT,
+ IOTX_DM_EVENT_LOCAL_RECONNECT,
+ IOTX_DM_EVENT_FOUND_DEVICE,
+ IOTX_DM_EVENT_REMOVE_DEVICE,
+ IOTX_DM_EVENT_REGISTER_RESULT,
+ IOTX_DM_EVENT_UNREGISTER_RESULT,
+ IOTX_DM_EVENT_INITIALIZED,
+ IOTX_DM_EVENT_SEND_RESULT,
+ IOTX_DM_EVENT_ADD_SERVICE_RESULT,
+ IOTX_DM_EVENT_REMOVE_SERVICE_RESULT,
+ IOTX_DM_EVENT_NEW_DATA_RECEIVED,
+ IOTX_DM_EVENT_PROPERTY_SET,
+ IOTX_DM_EVENT_PROPERTY_GET,
+ IOTX_DM_EVENT_PROPERTY_DESIRED_GET_REPLY,
+ IOTX_DM_EVENT_PROPERTY_DESIRED_DELETE_REPLY,
+ IOTX_DM_EVENT_TOPO_ADD_NOTIFY,
+ IOTX_DM_EVENT_THING_SERVICE_REQUEST,
+ IOTX_DM_EVENT_THING_DISABLE,
+ IOTX_DM_EVENT_THING_ENABLE,
+ IOTX_DM_EVENT_THING_DELETE,
+ IOTX_DM_EVENT_MODEL_DOWN_RAW,
+ IOTX_DM_EVENT_GATEWAY_PERMIT,
+ IOTX_DM_EVENT_SUBDEV_REGISTER_REPLY,
+ IOTX_DM_EVENT_SUBDEV_UNREGISTER_REPLY,
+ IOTX_DM_EVENT_TOPO_ADD_REPLY,
+ IOTX_DM_EVENT_TOPO_DELETE_REPLY,
+ IOTX_DM_EVENT_TOPO_GET_REPLY,
+ IOTX_DM_EVENT_TOPO_ADD_NOTIFY_REPLY,
+ IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY,
+ IOTX_DM_EVENT_EVENT_SPECIFIC_POST_REPLY,
+ IOTX_DM_EVENT_DEVICEINFO_UPDATE_REPLY,
+ IOTX_DM_EVENT_DEVICEINFO_DELETE_REPLY,
+ IOTX_DM_EVENT_DSLTEMPLATE_GET_REPLY,
+ IOTX_DM_EVENT_COMBINE_LOGIN_REPLY,
+ IOTX_DM_EVENT_COMBINE_LOGOUT_REPLY,
+ IOTX_DM_EVENT_MODEL_UP_RAW_REPLY,
+ IOTX_DM_EVENT_LEGACY_THING_CREATED,
+ IOTX_DM_EVENT_COTA_NEW_CONFIG,
+ IOTX_DM_EVENT_FOTA_NEW_FIRMWARE,
+ IOTX_DM_EVENT_NTP_RESPONSE,
+ IOTX_DM_EVENT_RRPC_REQUEST,
+ IOTX_DM_EVENT_MAX
+} iotx_dm_event_types_t;
+
+typedef void (*iotx_dm_event_callback)(iotx_dm_event_types_t type, char *payload);
+
+typedef enum {
+ IOTX_DM_DEVICE_SECRET_PRODUCT,
+ IOTX_DM_DEVICE_SECRET_DEVICE,
+ IOTX_DM_DEVICE_SECRET_TYPES_MAX
+} iotx_dm_device_secret_types_t;
+
+typedef enum {
+ IOTX_DM_CLOUD_DOMAIN_SHANGHAI,
+ IOTX_DM_CLOUD_DOMAIN_SINGAPORE,
+ IOTX_DM_CLOUD_DOMAIN_JAPAN,
+ IOTX_DM_CLOUD_DOMAIN_AMERICA,
+ IOTX_DM_CLOUD_DOMAIN_GERMANY,
+ IOTX_DM_CLOUD_DOMAIN_MAX
+} iotx_dm_cloud_domain_types_t;
+
+typedef enum {
+ IOTX_DM_MESSAGE_NO_AUTH,
+ IOTX_DM_MESSAGE_AUTH,
+ IOTX_DM_MESSAGE_AUTH_MAX
+} iotx_dm_message_auth_types_t;
+
+typedef enum {
+ IOTX_DM_TSL_SOURCE_LOCAL,
+ IOTX_DM_TSL_SOURCE_CLOUD
+} iotx_dm_tsl_source_t;
+
+typedef enum {
+ IOTX_DM_TSL_TYPE_ALINK,
+ IOTX_DM_TSL_TYPE_TLV
+} iotx_dm_tsl_type_t;
+
+typedef struct {
+ iotx_dm_device_secret_types_t secret_type;
+ iotx_dm_cloud_domain_types_t domain_type;
+ iotx_dm_event_callback event_callback;
+} iotx_dm_init_params_t;
+
+typedef enum {
+ IOTX_DM_DEV_AVAIL_ENABLE,
+ IOTX_DM_DEV_AVAIL_DISABLE
+} iotx_dm_dev_avail_t;
+
+typedef enum {
+ IOTX_DM_DEV_STATUS_UNAUTHORIZED, /* Subdev Created */
+ IOTX_DM_DEV_STATUS_AUTHORIZED, /* Receive Topo Add Notify */
+ IOTX_DM_DEV_STATUS_REGISTERED, /* Receive Subdev Registered */
+ IOTX_DM_DEV_STATUS_ATTACHED, /* Receive Subdev Topo Add Reply */
+ IOTX_DM_DEV_STATUS_LOGINED, /* Receive Subdev Login Reply */
+ IOTX_DM_DEV_STATUS_ONLINE /* After All Topic Subscribed */
+} iotx_dm_dev_status_t;
+
+typedef enum {
+ DM_TSL_SERVICE_GET_FAILED = -13,
+ DM_TSL_SERVICE_SET_FAILED = -12,
+ DM_TSL_EVENT_GET_FAILED = -11,
+ DM_TSL_EVENT_SET_FAILED = -10,
+ DM_TSL_PROPERTY_GET_FAILED = -9,
+ DM_TSL_PROPERTY_SET_FAILED = -8,
+ DM_TSL_EVENT_NOT_EXIST = -7,
+ DM_TSL_PROPERTY_NOT_EXIST = -6,
+ DM_TSL_SERVICE_NOT_EXIST = -5,
+ DM_JSON_PARSE_FAILED = -4,
+ DM_MEMORY_NOT_ENOUGH = -3,
+ DM_INVALID_PARAMETER = -2
+} dm_error_code_t;
+
+#define IOTX_DM_POST_PROPERTY_ALL (NULL)
+
+int iotx_dm_open(void);
+int iotx_dm_connect(_IN_ iotx_dm_init_params_t *init_params);
+int iotx_dm_subscribe(_IN_ int devid);
+int iotx_dm_close(void);
+int iotx_dm_yield(int timeout_ms);
+void iotx_dm_dispatch(void);
+
+int iotx_dm_post_rawdata(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+int iotx_dm_set_opt(int opt, void *data);
+int iotx_dm_get_opt(int opt, void *data);
+#ifdef LOG_REPORT_TO_CLOUD
+ int iotx_dm_log_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+#endif
+int iotx_dm_post_property(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int iotx_dm_property_desired_get(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int iotx_dm_property_desired_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int iotx_dm_post_event(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload,
+ _IN_ int payload_len);
+
+int iotx_dm_send_service_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier,
+ _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len, void *ctx);
+int iotx_dm_send_property_get_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
+ _IN_ iotx_dm_error_code_t code,
+ _IN_ char *payload, _IN_ int payload_len, _IN_ void *ctx);
+int iotx_dm_send_rrpc_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *rrpcid, _IN_ int rrpcid_len, _IN_ char *payload, _IN_ int payload_len);
+int iotx_dm_deviceinfo_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int iotx_dm_deviceinfo_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
+int iotx_dm_qurey_ntp(void);
+int iotx_dm_send_aos_active(int devid);
+#endif
+
+int iotx_dm_cota_perform_sync(_OU_ char *buffer, _IN_ int buffer_len);
+int iotx_dm_cota_get_config(_IN_ const char *config_scope, const char *get_type, const char *attribute_keys);
+int iotx_dm_fota_perform_sync(_OU_ char *buffer, _IN_ int buffer_len);
+int iotx_dm_fota_request_image(_IN_ const char *version, _IN_ int buffer_len);
+
+#ifdef DEVICE_MODEL_GATEWAY
+int iotx_dm_query_topo_list(void);
+int iotx_dm_subdev_create(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
+ _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ int *devid);
+int iotx_dm_subdev_destroy(_IN_ int devid);
+int iotx_dm_subdev_number(void);
+int iotx_dm_subdev_register(_IN_ int devid);
+int iotx_dm_subdev_unregister(_IN_ int devid);
+int iotx_dm_subdev_topo_add(_IN_ int devid);
+int iotx_dm_subdev_topo_del(_IN_ int devid);
+int iotx_dm_subdev_login(_IN_ int devid);
+int iotx_dm_subdev_logout(_IN_ int devid);
+int iotx_dm_get_device_type(_IN_ int devid, _OU_ int *type);
+int iotx_dm_get_device_avail_status(_IN_ int devid, _OU_ iotx_dm_dev_avail_t *status);
+int iotx_dm_get_device_status(_IN_ int devid, _OU_ iotx_dm_dev_status_t *status);
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+ int iotx_dm_send_firmware_version(int devid, const char *firmware_version);
+ int iotx_dm_ota_switch_device(_IN_ int devid);
+#endif
+#endif
+
+#ifdef DEPRECATED_LINKKIT
+int iotx_dm_deprecated_subdev_register(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
+int iotx_dm_deprecated_set_tsl(_IN_ int devid, _IN_ iotx_dm_tsl_source_t source, _IN_ const char *tsl,
+ _IN_ int tsl_len);
+int iotx_dm_deprecated_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int iotx_dm_deprecated_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int iotx_dm_deprecated_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int iotx_dm_deprecated_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int iotx_dm_deprecated_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+int iotx_dm_deprecated_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ int value_len);
+int iotx_dm_deprecated_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
+
+int iotx_dm_deprecated_post_property_start(_IN_ int devid, _OU_ void **handle);
+int iotx_dm_deprecated_post_property_add(_IN_ void *handle, _IN_ char *identifier, _IN_ int identifier_len);
+int iotx_dm_deprecated_post_property_end(_IN_ void **handle);
+int iotx_dm_deprecated_post_event(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len);
+int iotx_dm_deprecated_send_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier,
+ _IN_ int identifier_len);
+
+int iotx_dm_deprecated_legacy_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char *value_str);
+int iotx_dm_deprecated_legacy_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char **value_str);
+int iotx_dm_deprecated_legacy_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char *value_str);
+int iotx_dm_deprecated_legacy_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
+ _IN_ char **value_str);
+int iotx_dm_deprecated_legacy_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
+ _IN_ void *value,
+ _IN_ char **value_str);
+int iotx_dm_deprecated_legacy_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
+ _IN_ void *value,
+ _IN_ char *value_str);
+int iotx_dm_deprecated_legacy_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
+ _IN_ void *value,
+ _IN_ char **value_str);
+
+int iotx_dm_deprecated_legacy_get_pkdn_by_devid(_IN_ int devid, _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+int iotx_dm_deprecated_legacy_get_devid_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
+ _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ int *devid);
+int iotx_dm_deprecated_legacy_get_thingid_by_devid(_IN_ int devid, _OU_ void **thing_id);
+int iotx_dm_deprecated_legacy_get_devid_by_thingid(_IN_ void *thing_id, _OU_ int *devid);
+int iotx_dm_deprecated_legacy_get_pkdn_ptr_by_devid(_IN_ int devid, _OU_ char **product_key, _OU_ char **device_name);
+int iotx_dm_deprecated_legacy_send_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
+ _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len);
+#ifdef DEVICE_MODEL_GATEWAY
+ int iotx_dm_deprecated_subdev_register(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
+#endif
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm_config.h
new file mode 100644
index 00000000..7920fa5f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm_config.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef _IOTX_DM_CONFIG_H_
+#define _IOTX_DM_CONFIG_H_
+
+#define IOTX_DM_CLIENT_CONNECT_TIMEOUT_MS (10000)
+#define IOTX_DM_CLIENT_SUB_RETRY_MAX_COUNTS (3)
+#define IOTX_DM_CLIENT_SUB_TIMEOUT_MS (5000)
+#define IOTX_DM_CLIENT_REQUEST_TIMEOUT_MS (2000)
+#define IOTX_DM_CLIENT_KEEPALIVE_INTERVAL_MS (30000)
+
+#ifndef CONFIG_MQTT_TX_MAXLEN
+ #define CONFIG_MQTT_TX_MAXLEN (1024)
+#endif
+
+#ifndef CONFIG_MQTT_RX_MAXLEN
+ #define CONFIG_MQTT_RX_MAXLEN (1024)
+#endif
+
+#ifndef CONFIG_DISPATCH_QUEUE_MAXLEN
+ #define CONFIG_DISPATCH_QUEUE_MAXLEN (50)
+#endif
+
+#ifndef CONFIG_DISPATCH_PACKET_MAXCOUNT
+ #define CONFIG_DISPATCH_PACKET_MAXCOUNT (0)
+#endif
+
+#ifndef CONFIG_MSGCACHE_QUEUE_MAXLEN
+ #define CONFIG_MSGCACHE_QUEUE_MAXLEN (50)
+#endif
+
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm_internal.h
new file mode 100644
index 00000000..310e0127
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_dm_internal.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOTX_DM_INTERNAL_H_
+#define _IOTX_DM_INTERNAL_H_
+
+#include
+#include
+#include
+
+#include "infra_config.h"
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_list.h"
+#include "infra_cjson.h"
+#include "infra_report.h"
+#include "infra_string.h"
+#if defined(DEVICE_MODEL_GATEWAY)
+ #include "infra_sha1.h"
+#endif
+
+
+#ifndef _IN_
+ #define _IN_
+#endif
+
+#ifndef _OU_
+ #define _OU_
+#endif
+
+#ifndef DM_READ_ONLY
+ #define DM_READ_ONLY
+#endif
+
+#define _BSD_SOURCE
+
+#include
+
+#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
+ #include "iotx_ota.h"
+ #include "ota_api.h"
+#endif
+
+/* CM Header File */
+#include "iotx_cm.h"
+
+/* ALCS Header File */
+#ifdef ALCS_ENABLED
+ #include "CoAPExport.h"
+ #include "iotx_alcs.h"
+#endif
+
+/* DM Header File */
+#include "dm_wrapper.h"
+#include "iotx_dm_config.h"
+#include "iotx_dm.h"
+#include "dm_utils.h"
+#include "dm_shadow.h"
+#include "dm_tsl_alink.h"
+#include "dm_message_cache.h"
+#include "dm_opt.h"
+#include "dm_ota.h"
+#include "dm_cota.h"
+#include "dm_fota.h"
+#include "dm_ipc.h"
+#include "dm_message.h"
+#include "dm_msg_process.h"
+#include "dm_manager.h"
+#include "dm_client_adapter.h"
+#include "dm_client.h"
+#include "dm_server_adapter.h"
+#include "dm_server.h"
+#include "dm_intf.h"
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define DM_malloc(size) LITE_malloc(size, MEM_MAGIC, "dm")
+ #define DM_free(ptr) LITE_free(ptr)
+#else
+ #define DM_malloc(size) HAL_Malloc(size)
+ #define DM_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
+ #define DM_URI_OFFSET 1
+#else
+ #define DM_URI_OFFSET 0
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define dm_log_emerg(...) log_emerg("DM", __VA_ARGS__)
+ #define dm_log_crit(...) log_crit("DM", __VA_ARGS__)
+ #define dm_log_err(...) log_err("DM", __VA_ARGS__)
+ #define dm_log_warning(...) log_warning("DM", __VA_ARGS__)
+ #define dm_log_info(...) log_info("DM", __VA_ARGS__)
+ #define dm_log_debug(...) log_debug("DM", __VA_ARGS__)
+#else
+ #define dm_log_emerg(...)
+ #define dm_log_crit(...)
+ #define dm_log_err(...)
+ #define dm_log_warning(...)
+ #define dm_log_info(...)
+ #define dm_log_debug(...)
+ #define HEXDUMP_INFO(...)
+ #define HEXDUMP_DEBUG(...)
+#endif
+
+#ifdef LOG_REPORT_TO_CLOUD
+#define LOG_POLL_SIZE (CONFIG_MQTT_TX_MAXLEN - 174)
+#define REPORT_LEN (LOG_POLL_SIZE - 110)
+#define OVERFLOW_LEN (LOG_POLL_SIZE - 10)
+
+typedef enum {
+ READY,
+ RUNNING,
+ DONE
+} REPORT_STATE;
+unsigned int add_tail();
+int reset_log_poll();
+int remove_log_poll();
+unsigned int push_log(const char *perform_data, int perform_data_size);
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_log_report.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_log_report.h
new file mode 100644
index 00000000..dde32ee1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/iotx_log_report.h
@@ -0,0 +1,3 @@
+void get_msgid(char *payload, int is_cloud);
+int check_target_msg(const char *input, int len);
+void send_permance_info(char *input, int input_len, char *comments, int report_format);
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/linkkit_export.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/linkkit_export.h
new file mode 100644
index 00000000..0ce5b83a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/linkkit_export.h
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef LINKKIT_EXPORT_H
+#define LINKKIT_EXPORT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include
+
+typedef void (*handle_post_cb_fp_t)(const void *thing_id, int respons_id, int code, const char *response_message,
+ void *ctx);
+typedef void (*handle_subdev_cb_fp_t)(const void *thing_id, int code, const char *response_message, int success,
+ void *ctx);
+
+typedef struct _linkkit_ops {
+#ifdef LOCAL_CONN_ENABLE
+ int (*on_connect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */
+ int (*on_disconnect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */
+#else
+ int (*on_connect)(void *ctx); /* true: cloud connection; false: local connection */
+ int (*on_disconnect)(void *ctx); /* true: cloud connection; false: local connection */
+#endif
+ int (*raw_data_arrived)(const void *thing_id, const void *data, int len, void *ctx);
+ int (*thing_create)(const void *thing_id, void *ctx);
+ int (*thing_enable)(const void *thing_id, void *ctx);
+ int (*thing_disable)(const void *thing_id, void *ctx);
+ int (*thing_call_service)(const void *thing_id, const char *service, int request_id, void *ctx);
+ int (*thing_prop_changed)(const void *thing_id, const char *property, void *ctx);
+ int (*linkit_data_arrived)(const void *thing_id, const void *data, int len, void *ctx);
+} linkkit_ops_t;
+
+typedef enum _linkkit_loglevel {
+ linkkit_loglevel_emerg = 0,
+ linkkit_loglevel_crit,
+ linkkit_loglevel_error,
+ linkkit_loglevel_warning,
+ linkkit_loglevel_info,
+ linkkit_loglevel_debug,
+} linkkit_loglevel_t;
+
+/* domain type */
+/* please sync with dm_cloud_domain_type_t */
+typedef enum {
+ /* shanghai */
+ linkkit_cloud_domain_shanghai,
+ /* singapore */
+ linkkit_cloud_domain_singapore,
+ /* japan */
+ linkkit_cloud_domain_japan,
+ /* america */
+ linkkit_cloud_domain_america,
+ /* germany */
+ linkkit_cloud_domain_germany,
+
+ linkkit_cloud_domain_max,
+} linkkit_cloud_domain_type_t;
+
+/* device info related operation */
+typedef enum {
+ linkkit_extended_info_operate_update,
+ linkkit_extended_info_operate_delete,
+
+ linkkit_deviceinfo_operate_max,
+} linkkit_extended_info_operate_t;
+
+/**
+ * @brief dispatch message of queue for further process.
+ *
+ * @return void*
+ */
+DLL_IOT_API void *linkkit_dispatch(void);
+
+typedef enum {
+ linkkit_opt_property_post_reply, /* data type: int */
+ linkkit_opt_event_post_reply, /* data type: int */
+ linkkit_opt_property_set_reply /* data type: int */
+} linkkit_opt_t;
+
+/**
+ * @brief get leave signal.
+ *
+ *
+ * @return int,0 no leave signal, 1 get a leave signal
+ */
+DLL_IOT_API int being_deprecated linkkit_is_try_leave();
+
+/**
+ * @brief start linkkit routines, and install callback funstions(async type for cloud connecting).
+ *
+ * @param opt, specify the option need to be set.
+ * @param data, specify the option value.
+ *
+ * @return int, 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_set_opt(linkkit_opt_t opt, void *data);
+
+/**
+ * @brief start linkkit routines, and install callback funstions(async type for cloud connecting).
+ *
+ * @param max_buffered_msg, specify max buffered message size.
+ * @param ops, callback function struct to be installed.
+ * @param get_tsl_from_cloud, config if device need to get tsl from cloud(!0) or local(0), if local selected, must invoke linkkit_set_tsl to tell tsl to dm after start complete.
+ * @param log_level, config log level.
+ * @param user_context, user context pointer.
+ * @param domain_type, specify the could server domain.
+ *
+ * @return int, 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_start(int max_buffered_msg, int get_tsl_from_cloud,
+ linkkit_loglevel_t log_level,
+ linkkit_ops_t *ops,
+ linkkit_cloud_domain_type_t domain_type, void *user_context);
+
+/**
+ * @brief stop linkkit routines.
+ *
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_end(void);
+
+/**
+ * @brief install user tsl.
+ *
+ * @param tsl, tsl string that contains json description for thing object.
+ * @param tsl_len, tsl string length.
+ *
+ * @return pointer to thing object, NULL when fails.
+ */
+DLL_IOT_API void *linkkit_set_tsl(const char *tsl, int tsl_len);
+
+/* patterns: */
+/* method:
+ * set_property_/event_output_/service_output_value:
+ * method_set, thing_id, identifier, value */
+
+typedef enum {
+ linkkit_method_set_property_value = 0,
+ linkkit_method_set_event_output_value,
+ linkkit_method_set_service_output_value,
+
+ linkkit_method_set_number,
+} linkkit_method_set_t;
+
+/**
+ * @brief set value to property, event output, service output items.
+ * if identifier is struct type or service output type or event output type, use '.' as delimeter like "identifier1.ientifier2"
+ * to point to specific item.
+ * value and value_str could not be NULL at the same time;
+ * if value and value_str both as not NULL, value shall be used and value_str will be ignored.
+ * if value is NULL, value_str not NULL, value_str will be used.
+ * in brief, value will be used if not NULL, value_str will be used only if value is NULL.
+ *
+ * @param method_set, specify set value type.
+ * @param thing_id, pointer to thing object, specify which thing to set.
+ * @param identifier, property, event output, service output identifier.
+ * @param value. The value to be set, data type decided by data type of property as follows:
+ * int: int*, float: float*, double: double*,
+ * text: char*, enum: int*, date: char*, bool: int*
+ *
+ * @param value_str, value to set in string format if value is null.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_set_value(linkkit_method_set_t method_set, const void *thing_id,
+ const char *identifier,
+ const void *value, const char *value_str);
+
+typedef enum {
+ linkkit_method_get_property_value = 0,
+ linkkit_method_get_event_output_value,
+ linkkit_method_get_service_input_value,
+ linkkit_method_get_service_output_value,
+
+ linkkit_method_get_number,
+} linkkit_method_get_t;
+
+/**
+ * @brief get value from property, event output, service input/output items.
+ * if identifier is struct type or service input/output type or event output type, use '.' as delimeter like "identifier1.ientifier2"
+ * to point to specific item.
+ * value and value_str could not be NULL at the same time;
+ * if value and value_str both as not NULL, value shall be used and value_str will be ignored.
+ * if value is NULL, value_str not NULL, value_str will be used.
+ * in brief, value will be used if not NULL, value_str will be used only if value is NULL.
+ * @param method_get, specify get value type.
+ * @param thing_id, pointer to thing object, specify which thing to get.
+ * @param identifier, property, event output, service input/output identifier.
+ * @param value. The variable to store value, data type decided by data type of property as follows:
+ * int: int*, float: float*, double: double*,
+ * text: char**, enum: int*, date: char**, bool: int*
+ *
+ * @param value_str, value to get in string format. If success, memory of *value_str will be allocated,
+ * user should free the memory.
+ *
+ * @warning if data type is text or date, *value well be end with '\0'.
+ * the memory allocated to *value must be free by user.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_get_value(linkkit_method_get_t method_get, const void *thing_id,
+ const char *identifier,
+ void *value, char **value_str);
+
+
+/**
+ * @brief answer to a service when a service requested by cloud.
+ *
+ * @param thing_id, pointer to thing object.
+ * @param service_identifier, service identifier to answer, user should get this identifier from handle_dm_callback_fp_t type callback
+ * report that "dm_callback_type_service_requested" happened, use this function to generate response to the service sender.
+ * @param response_id, id value in response payload. its value is from "dm_callback_type_service_requested" type callback function.
+ * use the same id as the request to send response as the same communication session.
+ * @param code, code value in response payload. for example, 200 when service successfully executed, 400 when not successfully executed.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_answer_service(const void *thing_id, const char *service_identifier,
+ int response_id, int code);
+
+/**
+ * @brief answer a down raw service when a raw service requested by cloud, or invoke a up raw service to cloud.
+ *
+ * @param thing_id, pointer to thing object.
+ * @param is_up_raw, specify up raw(not 0) or down raw reply(0).
+ * @param raw_data, raw data that sent to cloud.
+ * @param raw_data_length, raw data length that sent to cloud.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_invoke_raw_service(const void *thing_id, int is_up_raw, void *raw_data,
+ int raw_data_length);
+
+/**
+ * @brief trigger extended info update procedure.
+ *
+ * @param thing_id, pointer to thing object.
+ * @param params, json type string that user to send to cloud.
+ * @param linkkit_extended_info_operation, specify update type or delete type.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+
+DLL_IOT_API int being_deprecated linkkit_trigger_extended_info_operate(const void *thing_id, const char *params,
+ linkkit_extended_info_operate_t linkkit_extended_info_operation);
+
+/**
+ * @brief trigger a event to post to cloud.
+ *
+ * @param thing_id, pointer to thing object.
+ * @param event_identifier, event identifier to trigger.
+ * @param cb, callback function of event post.
+ *
+ * @return >=0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_trigger_event(const void *thing_id, const char *event_identifier,
+ handle_post_cb_fp_t cb);
+
+/**
+ * @brief post property to cloud.
+ *
+ * @param thing_id, pointer to thing object.
+ * @param property_identifier, used when trigger event with method "event.property.post", if set, post specified property, if NULL, post all.
+ * @param cb, callback function of property post.
+ *
+ * @return >=0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_post_property(const void *thing_id, const char *property_identifier,
+ handle_post_cb_fp_t cb);
+
+/**
+ * @brief this function used to yield when want to receive or send data.
+ * if multi-thread enabled, user should NOT call this function.
+ *
+ * @param timeout_ms, timeout value in ms.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_yield(int timeout_ms);
+
+typedef enum {
+ service_cota_callback_type_new_version_detected = 10,
+
+ service_cota_callback_type_number,
+} service_cota_callback_type_t;
+
+typedef void (*handle_service_cota_callback_fp_t)(service_cota_callback_type_t callback_type, const char *configid,
+ uint32_t configsize,
+ const char *gettype,
+ const char *sign,
+ const char *signmethod,
+ const char *cota_url);
+
+/**
+ * @brief this function used to register callback for config ota.
+ *
+ * @param callback_fp, user callback which register to cota.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp);
+
+/**
+ * @brief this function used to execute cota process.
+ *
+ * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin.
+ * @param data_buf_length, data buf length that used to do ota.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_invoke_cota_service(void *data_buf, int data_buf_length);
+
+/**
+ * @brief this function used to trigger cota process.
+ *
+ * @param config_scope, remote config scope, should be "product".
+ * @param get_type, remote config file type, should be "file".
+ * @param attribute_Keys, reserved.
+ * @param option, reserved.
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_invoke_cota_get_config(const char *config_scope, const char *get_type,
+ const char *attribute_Keys, void *option);
+
+typedef enum {
+ service_fota_callback_type_new_version_detected = 10,
+
+ service_fota_callback_type_number,
+} service_fota_callback_type_t;
+
+typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version);
+
+/**
+ * @brief this function used to register callback for firmware ota.
+ *
+ * @param callback_fp, user callback which register to fota.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp);
+
+/**
+ * @brief this function used to execute fota process.
+ *
+ * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin.
+ * @param data_buf_length, data buf length that used to do ota.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_invoke_fota_service(void *data_buf, int data_buf_length);
+
+/**
+ * @brief this function used to get NTP time from cloud.
+ *
+ * @param ntp_reply_cb, user callback which register to ntp request.
+ * when cloud returns ntp reply, sdk would trigger the callback function
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int being_deprecated linkkit_ntp_time_request(void (*ntp_reply_cb)(const char *ntp_offset_time_ms));
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LINKKIT_EXPORT_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/linkkit_gateway_export.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/linkkit_gateway_export.h
new file mode 100644
index 00000000..f60d9a9d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_model/linkkit_gateway_export.h
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef LINKKIT_GATEWAY_EXPORT_H
+#define LINKKIT_GATEWAY_EXPORT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef _WIN32
+#ifdef DLL_IOT_EXPORTS
+#define DLL_IOT_API __declspec(dllexport)
+#else
+#define DLL_IOT_API __declspec(dllimport)
+#endif
+#else
+#define DLL_IOT_API
+#endif
+
+#if defined (__CC_ARM)
+#define ssize_t int
+#elif defined (__ICCARM__)
+#define ssize_t int
+#endif
+
+/***************************Gateway Interface***************************/
+
+enum {
+ LINKKIT_EVENT_CLOUD_DISCONNECTED = 0, /* cloud disconnected */
+ LINKKIT_EVENT_CLOUD_CONNECTED = 1, /* cloud connected */
+ LINKKIT_EVENT_SUBDEV_DELETED = 2, /* subdev deleted */
+ LINKKIT_EVENT_SUBDEV_PERMITED = 3, /* subdev permit join */
+ LINKKIT_EVENT_SUBDEV_SETUP = 4, /* subdev install */
+};
+
+/*
+ * option | default | minimum | maximum
+ *--------------------------------|---------|---------|---------
+ * LINKKIT_OPT_MAX_MSG_SIZE | 20480 | 512 | 51200
+ * LINKKIT_OPT_MAX_MSG_QUEUE_SIZE | 16 | 2 | 32
+ * LINKKIT_OPT_THREAD_POOL_SIZE | 4 | 1 | 16
+ * LINKKIT_OPT_THREAD_STACK_SIZE | 8192 | 1024 | 8388608
+ * LINKKIT_OPT_LOG_LEVEL | 3 | 0 | 5
+ */
+
+enum {
+ LINKKIT_OPT_MAX_MSG_SIZE = 1,
+ LINKKIT_OPT_MAX_MSG_QUEUE_SIZE = 2,
+ LINKKIT_OPT_THREAD_POOL_SIZE = 3,
+ LINKKIT_OPT_THREAD_STACK_SIZE = 4,
+ LINKKIT_OPT_PROPERTY_POST_REPLY = 5, /* data type: int */
+ LINKKIT_OPT_EVENT_POST_REPLY = 6, /* data type: int */
+ LINKKIT_OPT_PROPERTY_SET_REPLY = 7 /* data type: int */
+};
+
+typedef struct {
+ int event_type; /* see LINKKIT_EVENT_XXX for more details */
+
+ union {
+ struct {
+ char *productKey;
+ char *deviceName;
+ } subdev_deleted;
+
+ struct {
+ char *productKey;
+ int timeoutSec;
+ } subdev_permited;
+
+ struct {
+ char *subdevList; /* json format:[{"productKey":"","deviceName":""},...] */
+ } subdev_install;
+ } event_data;
+} linkkit_event_t;
+
+typedef struct linkkit_params_s {
+ int maxMsgSize; /* max message size */
+ int maxMsgQueueSize; /* max message queue size */
+
+ int threadPoolSize; /* number threads in pool */
+ int threadStackSize; /* default thread stack size */
+
+ int (*event_cb)(linkkit_event_t *ev, void *ctx);
+
+ /* user private data */
+ void *ctx;
+} linkkit_params_t;
+
+/**
+ * @brief get default initialize parameters
+ *
+ * @return linkkit default parameters.
+ */
+linkkit_params_t *linkkit_gateway_get_default_params(void);
+
+/**
+ * @brief set option in paremeters
+ *
+ * @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params().
+ * @param option, see LINKKIT_OPT_XXX for more detail.
+ * @param value, value of option.
+ * @param value_len, value length.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_setopt(linkkit_params_t *params, int option, void *value, int value_len);
+
+/**
+ * @brief set event callback
+ *
+ * @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params().
+ * @param event_cb, event callback.
+ * @param ctx, user private data.
+ *
+ * @return 0 when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_set_event_callback(linkkit_params_t *params, int (*event_cb)(linkkit_event_t *ev,
+ void *ctx),
+ void *ctx);
+
+/**
+ * @brief linkkit initialization.
+ *
+ * @param initParams, linkkit initialize parameters, see linkkit_params_t for more detail.
+ *
+ * @return 0 when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_init(linkkit_params_t *initParams);
+
+/**
+ * @brief linkkit deinitialization.
+ *
+ * @return 0 when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_exit(void);
+
+typedef struct {
+
+ int (*register_complete)(void *ctx);
+ /**
+ * @brief get property callback.
+ *
+ * @param in, properties to be get, in JSON array format, terminated by NULL.
+ * @param out, output buffer fill by user, in json format, terminated by NULL.
+ * @param out_len, out buffer length.
+ * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create()
+ *
+ * @return 0 when success, -1 when fail.
+ */
+ int (*get_property)(char *in, char *out, int out_len, void *ctx);
+
+ /**
+ * @brief set property callback.
+ *
+ * @param in, properties to be set, in JSON object format, terminated by NULL.
+ * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create()
+ *
+ * @return 0 when success, -1 when fail.
+ */
+ int (*set_property)(char *in, void *ctx);
+
+ /**
+ * @brief call service callback.
+ *
+ * @param identifier, service identifier, available services define in TSL file.
+ * @param in, service input data, in JSON object format, terminated by NULL.
+ * @param out, service output, this buffer will be filled by user, in json format, terminated by NULL.
+ * @param out_len, out buffer length.
+ * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ *
+ * @return 0 when success, -1 when fail.
+ */
+ int (*call_service)(char *identifier, char *in, char *out, int out_len, void *ctx);
+
+ /**
+ * @brief raw data from cloud.
+ *
+ * @param in, input data from cloud.
+ * @param in_len, input data length.
+ * @param out, output data to cloud, allocated by linkkit fill by user, no need to be free.
+ * @param out_len, out buffer length.
+ * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ *
+ * @return output data size. < 0 when fail.
+ */
+ int (*down_rawdata)(const void *in, int in_len, void *out, int out_len, void *ctx);
+
+ /**
+ * @brief return data from cloud when calling linkkit_gateway_post_rawdata().
+ *
+ * @param data, return raw data from cloud.
+ * @param len, data length.
+ * @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ *
+ * @return 0 when success, -1 when fail.
+ */
+ int (*post_rawdata_reply)(const void *data, int len, void *ctx);
+} linkkit_cbs_t;
+
+/**
+ * @brief start linkkit gateway routines and install callback funstions.
+ *
+ * @param cbs, callback function struct to be installed.
+ * @param ctx, user context pointer.
+ *
+ * @return device id, 0 > when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_start(linkkit_cbs_t *cbs, void *ctx);
+
+/**
+ * @brief stop linkkit gateway.
+
+ * @param devid, device id return from linkkit_gateway_start().
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_stop(int devid);
+
+/**
+ * @brief register subdev to gateway.
+
+ * @param productKey, subdev's product key.
+ * @param deviceName, subdev's device name.
+ * @param deviceSecret, subdev's device secret.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_subdev_register(char *productKey, char *deviceName, char *deviceSecret);
+
+/**
+ * @brief deregister subdev from gateway.
+
+ * @param productKey, subdev's product key.
+ * @param deviceName, subdev's device name.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_subdev_unregister(char *productKey, char *deviceName);
+
+/**
+ * @brief create subdev and install callback funstions.
+ *
+ * @param productKey, subdev's product key.
+ * @param deviceName, subdev's device name.
+ * @param cbs, callback function struct to be installed.
+ * @param ctx, user context pointer.
+ *
+ * @return device id, 0 > when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_subdev_create(char *productKey, char *deviceName, linkkit_cbs_t *cbs, void *ctx);
+
+/**
+ * @brief destroy subdev by device id.
+
+ * @param devid, device id return from linkkit_gateway_subdev_create().
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_subdev_destroy(int devid);
+
+/**
+ * @brief make subdev accessible from cloud.
+
+ * @param devid, device id return from linkkit_gateway_subdev_create().
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_subdev_login(int devid);
+
+/**
+ * @brief make subdev inaccessible on cloud.
+
+ * @param devid, device id return from linkkit_gateway_subdev_create().
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_subdev_logout(int devid);
+
+enum {
+ LINKKIT_STATE_ENABLED = 0, /* device is enabled by cloud */
+ LINKKIT_STATE_DISABLED, /* device is disabled by cloud */
+ LINKKIT_STATE_REMOVED, /* device is deleted by cloud */
+};
+
+typedef struct {
+ char *productKey; /* device's product key */
+ char *deviceName; /* device's device name */
+
+ int devtype; /* Device Type: 0 - gateway, 1 - subdev */
+ int login; /* Login State: 0 - logout, 1 - login */
+ int state; /* Device State: see LINKKIT_STATE_xxx */
+ int online; /* 0 - offline, 1 - online */
+} linkkit_devinfo_t;
+
+/**
+ * @brief get device infomation specific by devid.
+ *
+ * @param devinfo, device information, see linkkit_devinfo_t for more detail.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_get_devinfo(int devid, linkkit_devinfo_t *devinfo);
+
+/**
+ * @brief post event to cloud.
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param identifier, event identifier, see tsl file for more detail.
+ * @param event, event data, in JSON format.
+ * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_trigger_event_json_sync(int devid, char *identifier, char *event, int timeout_ms);
+
+/**
+ * @brief post event to cloud asynchronously.
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param identifier, event identifier, see tsl file for more detail.
+ * @param event, event data, in JSON format.
+ * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
+ * @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0).
+ * @param ctx, user data passed to 'func'.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_trigger_event_json(int devid, char *identifier, char *event, int timeout_ms,
+ void (*func)(int retval, void *ctx), void *ctx);
+
+
+/**
+ * @brief post property to cloud.
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param property, property data, in JSON format.
+ * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_post_property_json_sync(int devid, char *property, int timeout_ms);
+
+/**
+ * @brief post property to cloud asynchronously.
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param property, property data, in JSON format.
+ * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
+ * @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0).
+ * @param ctx, user data passed to 'func'.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_post_property_json(int devid, char *property, int timeout_ms,
+ void (*func)(int retval, void *ctx),
+ void *ctx);
+
+/**
+ * @brief post raw data to cloud.
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param data, raw data buffer pointer.
+ * @param len, raw data length.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_post_rawdata(int devid, void *data, int len);
+
+typedef enum {
+ LINKKIT_OTA_EVENT_NEW_VERSION_DETECTED = 1,
+} linkkit_ota_event_t;
+
+typedef enum {
+ service_fota_callback_type_new_version_detected = 10,
+
+ service_fota_callback_type_number,
+} service_fota_callback_type_t;
+
+typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version);
+
+/**
+ * @brief this function used to register callback for firmware ota.
+ *
+ * @param callback_fp, user callback which register to fota. (NULL for unregister)
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_fota_init(handle_service_fota_callback_fp_t callback_fp);
+
+/**
+ * @brief this function used to execute fota process.
+ *
+ * @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin.
+ * @param data_buf_length, data buf length that used to do ota.
+ *
+ * @return 0 when success, -1 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_invoke_fota_service(void *data_buf, int data_buf_length);
+
+typedef struct {
+ char *attrKey; /* the key of extend info. */
+ char *attrValue; /* the value of extend info. */
+} linkkit_extinfo_t;
+
+/**
+ * @brief post group of extend info to cloud
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param extinfos, group of extend info to be post.
+ * @param nb_extinfos, number of extend infos in extinfos.
+ * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
+ *
+ * @return 0 when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_post_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos,
+ int timeout_ms);
+
+/**
+ * @brief delete extend info specific by key
+ *
+ * @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
+ * @param extinfos, group of extend info to be deleted, attrValue in linkkit_extinfo_t will be ignore.
+ * @param nb_extinfos, number of extend infos in extinfos.
+ * @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
+ *
+ * @return 0 when success, < 0 when fail.
+ */
+DLL_IOT_API int linkkit_gateway_delete_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos,
+ int timeout_ms);
+
+/**
+ * @brief get number devices currently in gateway
+ *
+ * @return number devinfos.
+ */
+DLL_IOT_API int linkkit_gateway_get_num_devices(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LINKKIT_GATEWAY_EXPORT_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset.c
new file mode 100644
index 00000000..59c89b83
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "dev_reset_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+static int g_dev_reset_sub_flag = 0;
+iotx_devrst_evt_handle_t g_devrst_event_handle = NULL;
+
+
+#include "mqtt_api.h"
+static void mqtt_sub_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
+{
+ switch (msg->event_type)
+ {
+ case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: {
+ iotx_mqtt_topic_info_t *packet_info = (iotx_mqtt_topic_info_t *)msg->msg;
+ if (g_devrst_event_handle) {
+ iotx_devrst_evt_recv_msg_t recv_msg;
+ memset(&recv_msg, 0, sizeof(iotx_devrst_evt_recv_msg_t));
+ recv_msg.msgid = packet_info->packet_id;
+ recv_msg.payload = (char *)packet_info->payload;
+ recv_msg.payload_len = packet_info->payload_len;
+ g_devrst_event_handle(IOTX_DEVRST_EVT_RECEIVED, (void *)&recv_msg);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+int IOT_DevReset_Report(iotx_dev_meta_info_t *meta_info, iotx_devrst_evt_handle_t handle, void *extended)
+{
+ int res = 0;
+ const char *reset_fmt = "/sys/%s/%s/thing/reset";
+ const char *reset_reply_fmt = "/sys/%s/%s/thing/reset_reply";
+ const char *payload_fmt = "{\"id\":%d, \"version\":\"1.0\", \"method\":\"thing.reset\", \"params\":{}}";
+ char topic[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 30] = {0};
+ char payload[128] = {0};
+
+ if (meta_info == NULL || handle== NULL ) {
+ return FAIL_RETURN;
+ }
+ g_devrst_event_handle = handle;
+
+ memset(topic, 0, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 30);
+ HAL_Snprintf(topic,IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 30, reset_reply_fmt, meta_info->product_key, meta_info->device_name);
+
+ if (g_dev_reset_sub_flag == 0) {
+ res = IOT_MQTT_Subscribe_Sync(NULL, topic, IOTX_MQTT_QOS0, mqtt_sub_handle, NULL, 5000);
+ if (res < 0 ) {
+ return FAIL_RETURN;
+ }
+ g_dev_reset_sub_flag = 1;
+ }
+
+ memset(topic, 0, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 30);
+ HAL_Snprintf(topic, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 30, reset_fmt, meta_info->product_key, meta_info->device_name);
+
+ memset(payload, 0, 128);
+ HAL_Snprintf(payload, 128, payload_fmt, iotx_report_id());
+
+ res = IOT_MQTT_Publish_Simple(NULL, topic, IOTX_MQTT_QOS0, payload, strlen(payload));
+
+ return res;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_api.h
new file mode 100644
index 00000000..fed53791
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_api.h
@@ -0,0 +1,31 @@
+#ifndef __DEV_RESET_API_H__
+#define __DEV_RESET_API_H__
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+typedef enum {
+ IOTX_DEVRST_EVT_RECEIVED
+} iotx_devrst_evt_type_t;
+
+typedef struct {
+ int msgid;
+ char *payload;
+ uint32_t payload_len;
+} iotx_devrst_evt_recv_msg_t;
+
+typedef void (*iotx_devrst_evt_handle_t)(iotx_devrst_evt_type_t evt, void *msg);
+
+/**
+ * @brief report reset message to cloud.
+ *
+ * @param meta_info. device meta info, only product_key and device_name needed.
+ * @param extended. reserved.
+ *
+ * @retval -1 : failure
+ * @retval 0 : sucess
+ */
+int IOT_DevReset_Report(iotx_dev_meta_info_t *meta_info, iotx_devrst_evt_handle_t handle, void *extended);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_internal.h
new file mode 100644
index 00000000..8899e5da
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_internal.h
@@ -0,0 +1,36 @@
+#ifndef _DEV_RESET_INTERNAL_H_
+#define _DEV_RESET_INTERNAL_H_
+
+#include
+#include
+#include "infra_config.h"
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_report.h"
+#include "dev_reset_internal.h"
+#include "dev_reset_wrapper.h"
+#include "dev_reset_api.h"
+#include "mqtt_api.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
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_wrapper.h
new file mode 100644
index 00000000..f1d09a51
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_reset/dev_reset_wrapper.h
@@ -0,0 +1,7 @@
+#ifndef _DEV_RESET_WRAPPER_H_
+#define _DEV_RESET_WRAPPER_H_
+
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_api.h
new file mode 100644
index 00000000..9b56c178
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_api.h
@@ -0,0 +1,18 @@
+#ifndef _DEV_SIGN_H_
+#define _DEV_SIGN_H_
+
+#include "dev_sign_internal.h"
+
+typedef struct {
+ char hostname[DEV_SIGN_HOSTNAME_MAXLEN];
+ uint16_t port;
+ char clientid[DEV_SIGN_CLIENT_ID_MAXLEN];
+ char username[DEV_SIGN_USERNAME_MAXLEN];
+ char password[DEV_SIGN_PASSWORD_MAXLEN];
+} iotx_sign_mqtt_t;
+
+int32_t IOT_Sign_MQTT(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *meta, iotx_sign_mqtt_t *signout);
+
+#endif
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_config.h
new file mode 100644
index 00000000..e99dd11c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_config.h
@@ -0,0 +1,11 @@
+#ifndef _DEV_SIGN_CONFIG_H_
+#define _DEV_SIGN_CONFIG_H_
+
+#define DEV_SIGN_SOURCE_MAXLEN (200)
+#define DEV_SIGN_HOSTNAME_MAXLEN (64)
+#define DEV_SIGN_CLIENT_ID_MAXLEN (200)
+#define DEV_SIGN_USERNAME_MAXLEN (64)
+#define DEV_SIGN_PASSWORD_MAXLEN (65)
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_internal.h
new file mode 100644
index 00000000..64875279
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_internal.h
@@ -0,0 +1,13 @@
+#ifndef _DEV_SIGN_INTERNAL_H_
+#define _DEV_SIGN_INTERNAL_H_
+
+#include
+#include
+#include "infra_config.h"
+#include "infra_defs.h"
+#include "dev_sign_config.h"
+#include "dev_sign_api.h"
+#include "dev_sign_wrapper.h"
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_mqtt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_mqtt.c
new file mode 100644
index 00000000..021b98a8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_mqtt.c
@@ -0,0 +1,201 @@
+#include
+#include
+#include "infra_defs.h"
+#include "infra_config.h"
+#include "infra_sha256.h"
+
+#include "dev_sign_api.h"
+#include "dev_sign_wrapper.h"
+
+
+#define SIGN_MQTT_PORT (1883)
+
+/* all secure mode define */
+#define MODE_TLS_GUIDER "-1"
+#define MODE_TLS_DIRECT "2"
+#define MODE_TCP_DIRECT_PLAIN "3"
+
+#ifdef MQTT_PRE_AUTH
+ #define SECURE_MODE MODE_TLS_GUIDER
+#else
+ #ifdef SUPPORT_TLS
+ #define SECURE_MODE MODE_TLS_DIRECT
+ #else
+ #define SECURE_MODE MODE_TCP_DIRECT_PLAIN
+ #endif
+#endif
+
+/* use fixed timestamp */
+#define TIMESTAMP_VALUE "2524608000000"
+
+/* clientid key value pair define */
+const char *clientid_kv[][2] = {
+ {
+ "timestamp", TIMESTAMP_VALUE
+ },
+ {
+ "securemode", SECURE_MODE
+ },
+ {
+ "signmethod", "hmacsha256"
+ },
+#if defined(DEVICE_MODEL_ENABLED) && !defined(DEVICE_MODEL_CLASSIC)
+ {
+ "v", IOTX_ALINK_VERSION
+ },
+#else
+ {
+ "gw", "0"
+ },
+ {
+ "ext", "0"
+ },
+#endif
+ {
+ "_v", "sdk-c-"IOTX_SDK_VERSION
+ },
+};
+
+static void _hex2str(uint8_t *input, uint16_t input_len, char *output)
+{
+ char *zEncode = "0123456789ABCDEF";
+ int i = 0, j = 0;
+
+ for (i = 0; i < input_len; i++) {
+ output[j++] = zEncode[(input[i] >> 4) & 0xf];
+ output[j++] = zEncode[(input[i]) & 0xf];
+ }
+}
+
+int _sign_get_clientid(char *clientid_string, const char *device_id)
+{
+ uint8_t i;
+
+ if (clientid_string == NULL || device_id == NULL) {
+ return FAIL_RETURN;
+ }
+
+ memset(clientid_string, 0, DEV_SIGN_CLIENT_ID_MAXLEN);
+ memcpy(clientid_string, device_id, strlen(device_id));
+ memcpy(clientid_string + strlen(clientid_string), "|", 1);
+
+ for (i = 0; i < (sizeof(clientid_kv) / (sizeof(clientid_kv[0]))); i++) {
+ if ((strlen(clientid_string) + strlen(clientid_kv[i][0]) + strlen(clientid_kv[i][1]) + 2) >=
+ DEV_SIGN_CLIENT_ID_MAXLEN) {
+ return FAIL_RETURN;
+ }
+
+ memcpy(clientid_string + strlen(clientid_string), clientid_kv[i][0], strlen(clientid_kv[i][0]));
+ memcpy(clientid_string + strlen(clientid_string), "=", 1);
+ memcpy(clientid_string + strlen(clientid_string), clientid_kv[i][1], strlen(clientid_kv[i][1]));
+ memcpy(clientid_string + strlen(clientid_string), ",", 1);
+ }
+
+ memcpy(clientid_string + strlen(clientid_string) - 1, "|", 1);
+
+ return SUCCESS_RETURN;
+}
+
+int _iotx_generate_sign_string(const char *device_id, const char *device_name, const char *product_key, const char *device_secret, char *sign_string)
+{
+ char signsource[DEV_SIGN_SOURCE_MAXLEN] = {0};
+ uint16_t signsource_len = 0;
+ const char sign_fmt[] = "clientId%sdeviceName%sproductKey%stimestamp%s";
+ uint8_t sign_hex[32] = {0};
+
+ signsource_len = sizeof(sign_fmt) + strlen(device_id) + strlen(device_name) + strlen(product_key) + strlen(TIMESTAMP_VALUE);
+ if (signsource_len >= DEV_SIGN_SOURCE_MAXLEN) {
+ return ERROR_DEV_SIGN_SOURCE_TOO_SHORT;
+ }
+
+ memset(signsource, 0, DEV_SIGN_SOURCE_MAXLEN);
+ memcpy(signsource, "clientId", strlen("clientId"));
+ memcpy(signsource + strlen(signsource), device_id, strlen(device_id));
+ memcpy(signsource + strlen(signsource), "deviceName", strlen("deviceName"));
+ memcpy(signsource + strlen(signsource), device_name, strlen(device_name));
+ memcpy(signsource + strlen(signsource), "productKey", strlen("productKey"));
+ memcpy(signsource + strlen(signsource), product_key, strlen(product_key));
+ memcpy(signsource + strlen(signsource), "timestamp", strlen("timestamp"));
+ memcpy(signsource + strlen(signsource), TIMESTAMP_VALUE, strlen(TIMESTAMP_VALUE));
+
+ utils_hmac_sha256((uint8_t *)signsource, strlen(signsource), (uint8_t *)device_secret,
+ strlen(device_secret), sign_hex);
+
+ _hex2str(sign_hex, 32, sign_string);
+
+ return SUCCESS_RETURN;
+}
+
+int32_t IOT_Sign_MQTT(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *meta, iotx_sign_mqtt_t *signout)
+{
+ uint16_t length = 0;
+ char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = {0};
+ int res;
+
+ if (region >= IOTX_MQTT_DOMAIN_NUMBER || meta == NULL) {
+ return -1;
+ }
+
+ memset(signout, 0, sizeof(iotx_sign_mqtt_t));
+
+ memcpy(device_id, meta->product_key, strlen(meta->product_key));
+ memcpy(device_id + strlen(device_id), ".", strlen("."));
+ memcpy(device_id + strlen(device_id), meta->device_name, strlen(meta->device_name));
+
+ /* setup clientid */
+ if (_sign_get_clientid(signout->clientid, device_id) != SUCCESS_RETURN) {
+ return ERROR_DEV_SIGN_CLIENT_ID_TOO_SHORT;
+ }
+
+ /* setup password */
+ memset(signout->password, 0, DEV_SIGN_PASSWORD_MAXLEN);
+ res = _iotx_generate_sign_string(device_id, meta->device_name, meta->product_key, meta->device_secret, signout->password);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ /* setup hostname */
+ if (IOTX_CLOUD_REGION_CUSTOM == region) {
+ if (g_infra_mqtt_domain[region] == NULL) {
+ return ERROR_DEV_SIGN_CUSTOM_DOMAIN_IS_NULL;
+ }
+
+ length = strlen(g_infra_mqtt_domain[region]) + 1;
+ if (length >= DEV_SIGN_HOSTNAME_MAXLEN) {
+ return ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT;
+ }
+
+ memset(signout->hostname, 0, DEV_SIGN_HOSTNAME_MAXLEN);
+ memcpy(signout->hostname, g_infra_mqtt_domain[region], strlen(g_infra_mqtt_domain[region]));
+ }
+ else {
+ length = strlen(meta->product_key) + strlen(g_infra_mqtt_domain[region]) + 2;
+ if (length >= DEV_SIGN_HOSTNAME_MAXLEN) {
+ return ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT;
+ }
+ memset(signout->hostname, 0, DEV_SIGN_HOSTNAME_MAXLEN);
+ memcpy(signout->hostname, meta->product_key, strlen(meta->product_key));
+ memcpy(signout->hostname + strlen(signout->hostname), ".", strlen("."));
+ memcpy(signout->hostname + strlen(signout->hostname), g_infra_mqtt_domain[region],
+ strlen(g_infra_mqtt_domain[region]));
+ }
+
+ /* setup username */
+ length = strlen(meta->device_name) + strlen(meta->product_key) + 2;
+ if (length >= DEV_SIGN_USERNAME_MAXLEN) {
+ return ERROR_DEV_SIGN_USERNAME_TOO_SHORT;
+ }
+ memset(signout->username, 0, DEV_SIGN_USERNAME_MAXLEN);
+ memcpy(signout->username, meta->device_name, strlen(meta->device_name));
+ memcpy(signout->username + strlen(signout->username), "&", strlen("&"));
+ memcpy(signout->username + strlen(signout->username), meta->product_key, strlen(meta->product_key));
+
+ /* setup port */
+#ifdef SUPPORT_TLS
+ signout->port = 443;
+#else
+ signout->port = 1883;
+#endif /* #ifdef SUPPORT_TLS */
+ return SUCCESS_RETURN;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_wrapper.h
new file mode 100644
index 00000000..c3520e6b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dev_sign/dev_sign_wrapper.h
@@ -0,0 +1,4 @@
+
+
+#include "infra_types.h"
+#include "infra_defs.h"
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg.c
new file mode 100644
index 00000000..29f6af78
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include
+#include "string.h"
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_string.h"
+#include "infra_httpc.h"
+#include "infra_sha256.h"
+#include "dynreg_internal.h"
+#include "dynreg_wrapper.h"
+
+#define HTTP_RESPONSE_PAYLOAD_LEN (256)
+
+#define DYNREG_RANDOM_KEY_LENGTH (15)
+#define DYNREG_SIGN_LENGTH (65)
+#define DYNREG_SIGN_METHOD_HMACSHA256 "hmacsha256"
+
+static int _parse_string_value(char *payload, int *pos, int *start, int *end)
+{
+ int idx = 0;
+
+ for (idx = *pos + 1; idx < strlen(payload); idx++) {
+ if (payload[idx] == '\"') {
+ break;
+ }
+ }
+ *start = *pos + 1;
+ *end = idx - 1;
+ *pos = idx;
+
+ return 0;
+}
+
+static int _parse_dynreg_value(char *payload, char *key, int *pos, int *start, int *end)
+{
+ int idx = 0;
+ /* printf("=====%s\n",&payload[*pos]); */
+
+ if (memcmp(key, "code", strlen("code")) == 0) {
+ for (idx = *pos; idx < strlen(payload); idx++) {
+ if (payload[idx] < '0' || payload[idx] > '9') {
+ break;
+ }
+ }
+ *start = *pos;
+ *end = idx - 1;
+ *pos = *end;
+ return 0;
+ } else if (memcmp(key, "data", strlen("data")) == 0) {
+ int bracket_cnt = 0;
+ if (payload[*pos] != '{') {
+ return -1;
+ }
+ for (idx = *pos; idx < strlen(payload); idx++) {
+ if (payload[idx] == '{') {
+ bracket_cnt++;
+ } else if (payload[idx] == '}') {
+ bracket_cnt--;
+ }
+ if (bracket_cnt == 0) {
+ break;
+ }
+ }
+ *start = *pos;
+ *end = idx;
+ *pos = *end;
+ return 0;
+ } else {
+ if (payload[*pos] != '\"') {
+ return -1;
+ }
+ return _parse_string_value(payload, pos, start, end);
+ }
+
+ return -1;
+}
+
+static int _parse_dynreg_result(char *payload, char *key, int *start, int *end)
+{
+ int res = 0, idx = 0, pos = 0;
+
+ for (idx = 0; idx < strlen(payload); idx++) {
+ /* printf("loop start: %s\n",&payload[idx]); */
+ if (payload[idx] == '\"') {
+ for (pos = idx + 1; pos < strlen(payload); pos++) {
+ if (payload[pos] == '\"') {
+ /* printf("key: %.*s\n",pos - idx - 1, &payload[idx+1]); */
+ break;
+ }
+ }
+
+ if (pos == strlen(payload) || payload[pos + 1] != ':') {
+ return -1;
+ }
+
+ pos += 2;
+ res = _parse_dynreg_value(payload, key, &pos, start, end);
+ if (res == 0 && memcmp(key, &payload[idx + 1], strlen(key)) == 0) {
+ /* printf("value: %.*s\n",*end - *start + 1,&payload[*start]); */
+ return 0;
+ }
+
+ idx = pos;
+ }
+ }
+
+ printf("exit 4\n");
+ return -1;
+}
+
+static int _calc_dynreg_sign(
+ char product_key[IOTX_PRODUCT_KEY_LEN],
+ char product_secret[IOTX_PRODUCT_SECRET_LEN],
+ char device_name[IOTX_DEVICE_NAME_LEN],
+ char random[DYNREG_RANDOM_KEY_LENGTH + 1],
+ char sign[DYNREG_SIGN_LENGTH])
+{
+ int sign_source_len = 0;
+ uint8_t signnum[32];
+ uint8_t *sign_source = NULL;
+ const char *dynamic_register_sign_fmt = "deviceName%sproductKey%srandom%s";
+
+ /* Start Dynamic Register */
+ memcpy(random, "8Ygb7ULYh53B6OA", strlen("8Ygb7ULYh53B6OA"));
+ dynreg_info("Random Key: %s", random);
+
+ /* Calculate SHA256 Value */
+ sign_source_len = strlen(dynamic_register_sign_fmt) + strlen(device_name) + strlen(product_key) + strlen(random) + 1;
+ sign_source = dynreg_malloc(sign_source_len);
+ if (sign_source == NULL) {
+ dynreg_err("Memory Not Enough");
+ return FAIL_RETURN;
+ }
+ memset(sign_source, 0, sign_source_len);
+ HAL_Snprintf((char *)sign_source, sign_source_len, dynamic_register_sign_fmt, device_name, product_key, random);
+
+ utils_hmac_sha256(sign_source, strlen((const char *)sign_source), (uint8_t *)product_secret, strlen(product_secret),
+ signnum);
+ infra_hex2str(signnum, 32, sign);
+ dynreg_free(sign_source);
+ dynreg_info("Sign: %s", sign);
+
+ return SUCCESS_RETURN;
+}
+
+static int _fetch_dynreg_http_resp(char *request_payload, char *response_payload,
+ iotx_http_region_types_t region, char device_secret[IOTX_DEVICE_SECRET_LEN])
+{
+ int res = 0;
+ const char *domain = NULL;
+ const char *url_format = "http://%s/auth/register/device";
+ char *url = NULL;
+ int url_len = 0;
+ const char *pub_key = NULL;
+ httpclient_t http_client;
+ httpclient_data_t http_client_data;
+ int start = 0, end = 0, data_start = 0, data_end = 0;
+
+ memset(&http_client, 0, sizeof(httpclient_t));
+ memset(&http_client_data, 0, sizeof(httpclient_data_t));
+
+ domain = g_infra_http_domain[region];
+ if (NULL == domain) {
+ dynreg_err("Get domain failed");
+ return FAIL_RETURN;
+ }
+ url_len = strlen(url_format) + strlen(domain) + 1;
+ url = (char *)dynreg_malloc(url_len);
+ if (NULL == url) {
+ dynreg_err("Not Enough Memory");
+ return FAIL_RETURN;
+ }
+ memset(url, 0, url_len);
+ HAL_Snprintf(url, url_len, url_format, domain);
+
+ http_client.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n";
+
+ http_client_data.post_content_type = "application/x-www-form-urlencoded";
+ http_client_data.post_buf = request_payload;
+ http_client_data.post_buf_len = strlen(request_payload);
+ http_client_data.response_buf = response_payload;
+ http_client_data.response_buf_len = HTTP_RESPONSE_PAYLOAD_LEN;
+
+#ifdef SUPPORT_TLS
+ {
+ extern const char *iotx_ca_crt;
+ pub_key = iotx_ca_crt;
+ }
+#endif
+
+ res = httpclient_common(&http_client, url, 443, pub_key, HTTPCLIENT_POST, 10000, &http_client_data);
+ if (res != SUCCESS_RETURN) {
+ dynreg_err("Http Download Failed");
+ dynreg_free(url);
+ return FAIL_RETURN;
+ }
+ dynreg_free(url);
+ dynreg_info("Http Response Payload: %s", http_client_data.response_buf);
+
+ _parse_dynreg_result(response_payload, "code", &start, &end);
+ dynreg_info("Dynamic Register Code: %.*s", end - start + 1, &response_payload[start]);
+
+ if (memcmp(&response_payload[start], "200", strlen("200")) != 0) {
+ return FAIL_RETURN;
+ }
+
+ _parse_dynreg_result(response_payload, "data", &data_start, &data_end);
+ /* dynreg_info("value: %.*s\n",data_end - data_start + 1,&response_payload[data_start]); */
+
+ _parse_dynreg_result(&response_payload[data_start + 1], "deviceSecret", &start, &end);
+ dynreg_info("Dynamic Register Device Secret: %.*s", end - start + 1, &response_payload[data_start + 1 + start]);
+
+ if (end - start + 1 > IOTX_DEVICE_SECRET_LEN) {
+ return FAIL_RETURN;
+ }
+
+ memcpy(device_secret, &response_payload[data_start + 1 + start], end - start + 1);
+
+ return SUCCESS_RETURN;
+}
+
+int32_t IOT_Dynamic_Register(iotx_http_region_types_t region, iotx_dev_meta_info_t *meta)
+{
+ int res = 0, dynamic_register_request_len = 0;
+ char sign[DYNREG_SIGN_LENGTH] = {0};
+ char random[DYNREG_RANDOM_KEY_LENGTH + 1] = {0};
+ const char *dynamic_register_format = "productKey=%s&deviceName=%s&random=%s&sign=%s&signMethod=%s";
+ char *dynamic_register_request = NULL;
+ char *dynamic_register_response = NULL;
+
+ if (strlen(meta->product_key) > IOTX_PRODUCT_KEY_LEN ||
+ strlen(meta->product_secret) > IOTX_PRODUCT_SECRET_LEN ||
+ strlen(meta->device_name) > IOTX_DEVICE_NAME_LEN) {
+ return FAIL_RETURN;
+ }
+
+ /* Calcute Signature */
+ res = _calc_dynreg_sign(meta->product_key, meta->product_secret, meta->device_name, random, sign);
+ if (res != SUCCESS_RETURN) {
+ dynreg_err("Calculate Sign Failed");
+ return FAIL_RETURN;
+ }
+
+ /* Assemble Http Dynamic Register Request Payload */
+ dynamic_register_request_len = strlen(dynamic_register_format) + strlen(meta->product_key) + strlen(meta->device_name) +
+ strlen(random) + strlen(sign) + strlen(DYNREG_SIGN_METHOD_HMACSHA256) + 1;
+ dynamic_register_request = dynreg_malloc(dynamic_register_request_len);
+ if (dynamic_register_request == NULL) {
+ dynreg_err("Not Enough Memory");
+ return FAIL_RETURN;
+ }
+ memset(dynamic_register_request, 0, dynamic_register_request_len);
+ HAL_Snprintf(dynamic_register_request, dynamic_register_request_len, dynamic_register_format,
+ meta->product_key, meta->device_name, random, sign, DYNREG_SIGN_METHOD_HMACSHA256);
+
+ dynamic_register_response = dynreg_malloc(HTTP_RESPONSE_PAYLOAD_LEN);
+ if (dynamic_register_response == NULL) {
+ dynreg_err("Not Enough Memory");
+ dynreg_free(dynamic_register_request);
+ return FAIL_RETURN;
+ }
+
+ /* Send Http Request For Getting Device Secret */
+ res = _fetch_dynreg_http_resp(dynamic_register_request, dynamic_register_response, region, meta->device_secret);
+
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+ dynreg_dbg("Downstream Payload:");
+ iotx_facility_json_print(dynamic_register_response, LOG_DEBUG_LEVEL, '<');
+#endif
+
+ dynreg_free(dynamic_register_request);
+ dynreg_free(dynamic_register_response);
+ if (res != SUCCESS_RETURN) {
+ dynreg_err("Get Device Secret Failed");
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_api.h
new file mode 100644
index 00000000..d1fcf8fe
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_api.h
@@ -0,0 +1,10 @@
+#ifndef _DYNREG_API_H_
+#define _DYNREG_API_H_
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+int32_t IOT_Dynamic_Register(iotx_http_region_types_t region, iotx_dev_meta_info_t *meta);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_internal.h
new file mode 100644
index 00000000..79d73306
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_internal.h
@@ -0,0 +1,27 @@
+#ifndef _DYNREG_INTERNAL_H_
+#define _DYNREG_INTERNAL_H_
+
+#include "dynreg_wrapper.h"
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define dynreg_info(...) log_info("dynreg", __VA_ARGS__)
+ #define dynreg_err(...) log_err("dynreg", __VA_ARGS__)
+ #define dynreg_dbg(...) log_debug("dynreg", __VA_ARGS__)
+#else
+ #define dynreg_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define dynreg_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define dynreg_dbg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define dynreg_malloc(size) LITE_malloc(size, MEM_MAGIC, "dynreg")
+ #define dynreg_free(ptr) LITE_free(ptr)
+#else
+ #define dynreg_malloc(size) HAL_Malloc(size)
+ #define dynreg_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_wrapper.h
new file mode 100644
index 00000000..b7e52f51
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/dynamic_register/dynreg_wrapper.h
@@ -0,0 +1,12 @@
+#ifndef _DYNREG_WRAPPER_H_
+#define _DYNREG_WRAPPER_H_
+
+#include "infra_types.h"
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+void HAL_Printf(const char *fmt, ...);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_api.h
new file mode 100644
index 00000000..69bd9338
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_api.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOT_EXPORT_HTTP_H_
+#define _IOT_EXPORT_HTTP_H_
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+typedef struct {
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char device_id[IOTX_DEVICE_ID_LEN + 1];
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
+ char module_vendor_id[IOTX_MODULE_ID_LEN + 1];
+} iotx_device_info_t;
+
+/* IoTx http initial param */
+typedef struct {
+ iotx_device_info_t *device_info;
+ int keep_alive;
+ int timeout_ms;
+} iotx_http_param_t;
+
+/* IoTx http context */
+typedef struct {
+ char *p_auth_token;
+ uint32_t auth_token_len;
+ char is_authed;
+ const char *version;
+ const char *signmethod;
+ const char *sign;
+ iotx_device_info_t *p_devinfo;
+ const char *timestamp;
+ void *httpc;
+ int keep_alive;
+ int timeout_ms;
+} iotx_http_t, *iotx_http_pt;
+
+/* IoTx http message definition
+ * request_payload and response_payload need to be allocate in order to save memory.
+ * topic_path specify the topic url you want to publish message.
+ */
+typedef struct {
+ char *topic_path;
+ uint32_t request_payload_len;
+ char *request_payload;
+ uint32_t response_payload_len;
+ char *response_payload;
+ uint32_t timeout_ms;
+} iotx_http_message_param_t;
+
+/* The response code from sever */
+typedef enum {
+ IOTX_HTTP_SUCCESS = 0,
+ IOTX_HTTP_COMMON_ERROR = 10000,
+ IOTX_HTTP_PARAM_ERROR = 10001,
+ IOTX_HTTP_AUTH_CHECK_ERROR = 20000,
+ IOTX_HTTP_TOKEN_EXPIRED_ERROR = 20001,
+ IOTX_HTTP_TOKEN_NULL_ERROR = 20002,
+ IOTX_HTTP_TOKEN_CHECK_ERROR = 20003,
+ IOTX_HTTP_UPDATE_SESSION_ERROR = 20004,
+ IOTX_HTTP_PUBLISH_MESSAGE_ERROR = 30001,
+ IOTX_HTTP_REQUEST_TOO_MANY_ERROR = 40000,
+} iotx_http_upstream_response_t;
+
+/** @defgroup group_api api
+ * @{
+ */
+
+/** @defgroup group_api_http http
+ * @{
+ */
+
+/**
+ * @brief Initialize the HTTP client
+ * This function initialize the data.
+ *
+ * @param [in] pInitParams: Specify the init param infomation.
+ *
+ * @retval NULL : Initialize failed.
+ * @retval NOT_NULL : The contex of HTTP client.
+ * @see None.
+ */
+DLL_IOT_API void *IOT_HTTP_Init(iotx_http_param_t *pInitParams);
+
+/**
+ * @brief De-initialize the HTTP client
+ * This function release the related resource.
+ *
+ * @param [in] handle: pointer to http context pointer.
+ * @return None.
+ * @see None.
+ */
+DLL_IOT_API void IOT_HTTP_DeInit(void **handle);
+
+/**
+ * @brief Handle device name authentication with remote server.
+ *
+ * @param [in] handle: Pointer of context, specify the HTTP client.
+ *
+ * @retval 0 : Authenticate success.
+ * @retval -1 : Authenticate failed.
+ * @see iotx_err_t.
+ */
+DLL_IOT_API int IOT_HTTP_DeviceNameAuth(void *handle);
+
+/**
+ * @brief Send a message with specific path to server.
+ * Client must authentication with server before send message.
+ *
+ * @param [in] handle: Pointer of contex, specify the HTTP client.
+ * @param [in] msg_param: Specify the topic path and http payload configuration.
+ *
+ * @retval 0 : Success.
+ * @retval -1 : Failed.
+ * @see iotx_err_t.
+ */
+DLL_IOT_API int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param);
+
+/**
+ * @brief close tcp connection from client to server.
+ *
+ * @param [in] handle: Pointer of contex, specify the HTTP client.
+ * @return None.
+ * @see None.
+ */
+DLL_IOT_API void IOT_HTTP_Disconnect(void *handle);
+
+/** @} */ /* end of api_http */
+/** @} */ /* end of api */
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_debug.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_debug.h
new file mode 100644
index 00000000..98240001
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_debug.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef __HTTP_DEBUG_H__
+#define __HTTP_DEBUG_H__
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define http_emerg(...) log_emerg("HTTP", __VA_ARGS__)
+ #define http_crit(...) log_crit("HTTP", __VA_ARGS__)
+ #define http_err(...) log_err("HTTP", __VA_ARGS__)
+ #define http_warning(...) log_warning("HTTP", __VA_ARGS__)
+ #define http_info(...) log_info("HTTP", __VA_ARGS__)
+ #define http_debug(...) log_debug("HTTP", __VA_ARGS__)
+#else
+ #define http_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define http_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define http_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define http_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define http_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define http_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+
+#endif /* __HTTP_DEBUG_H__ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_wrapper.h
new file mode 100644
index 00000000..2e712ee0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/http_wrapper.h
@@ -0,0 +1,15 @@
+#ifndef _HTTP_WRAPPER_H
+#define _HTTP_WRAPPER_H
+
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+void HAL_Printf(const char *fmt, ...);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+uint64_t HAL_UptimeMs(void);
+void HAL_SleepMs(uint32_t ms);
+
+#endif /* #ifndef _HTTP_WRAPPER_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/iotx_http_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/iotx_http_api.c
new file mode 100644
index 00000000..2d2489c1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http/iotx_http_api.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+#include
+#include
+
+#include "infra_httpc.h"
+#include "infra_json_parser.h"
+#include "infra_timer.h"
+#include "infra_sha1.h"
+#include "infra_report.h"
+#include "http_debug.h"
+#include "http_api.h"
+#include "http_wrapper.h"
+
+
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define HTTP_API_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "http.api")
+ #define HTTP_API_FREE(ptr) LITE_free(ptr)
+#else
+ #define HTTP_API_MALLOC(size) HAL_Malloc(size)
+ #define HTTP_API_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#define HTTP_LITE_JSON_VALUE_OF(key, src) LITE_json_value_of(key, src, 0x1234, "http.api")
+
+#ifndef CONFIG_MID_HTTP_TIMEOUT
+ #define CONFIG_MID_HTTP_TIMEOUT (5 * 1000)
+#endif
+
+#ifndef CONFIG_HTTP_AUTH_TIMEOUT
+ #define CONFIG_HTTP_AUTH_TIMEOUT (5 * 1000)
+#endif
+
+/*
+#define IOTX_HTTP_TIMESTAMP_OPTIONAL_ENABLE
+*/
+#define IOTX_HTTP_SIGN_LENGTH (41)
+#define IOTX_HTTP_SIGN_SOURCE_LEN (256)
+#define IOTX_HTTP_AUTH_TOKEN_LEN (192+1)
+#define IOTX_HTTP_URL_LEN_MAX (135)
+
+#ifdef IOTX_HTTP_TIMESTAMP_OPTIONAL_ENABLE
+#define IOTX_HTTP_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%stimestamp%s"
+#define IOTX_HTTP_AUTH_DEVICENAME_STR \
+ "{" \
+ "\"version\":\"%s\", \"clientId\":\"%s\"," \
+ "\"signmethod\":\"%s\",\"sign\":\"%s\"," \
+ "\"productKey\":\"%s\",\"deviceName\":\"%s\"," \
+ "\"timestamp\":\"%s\"" \
+ "}"
+#else
+#define IOTX_HTTP_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%s"
+#define IOTX_HTTP_AUTH_DEVICENAME_STR \
+ "{" \
+ "\"version\":\"%s\", \"clientId\":\"%s\"," \
+ "\"signmethod\":\"%s\",\"sign\":\"%s\"," \
+ "\"productKey\":\"%s\",\"deviceName\":\"%s\"" \
+ "}"
+#endif
+
+#define IOTX_HTTP_AUTH_STR "auth"
+#define IOTX_HTTP_ONLINE_SERVER_URL "https://iot-as-http.cn-shanghai.aliyuncs.com"
+#define IOTX_HTTP_ONLINE_SERVER_PORT 443
+
+#define IOTX_SHA_METHOD "hmacsha1"
+
+#define IOTX_HTTP_HEADER_KEEPALIVE_STR "Connection: Keep-Alive\r\n"
+#define IOTX_HTTP_HEADER_PASSWORD_STR "password:"
+#define IOTX_HTTP_UPSTREAM_HEADER_STR \
+ IOTX_HTTP_HEADER_KEEPALIVE_STR \
+ IOTX_HTTP_HEADER_PASSWORD_STR \
+ "%s" \
+ IOTX_HTTP_HEADER_END_STR
+#define IOTX_HTTP_HEADER_END_STR "\r\n"
+
+#define HTTP_AUTH_RESP_MAX_LEN (256)
+
+static iotx_http_t *iotx_http_context_bak = NULL;
+
+
+/*
+ Http server url: https://iot-as-http.cn-shanghai.aliyuncs.com
+ Only https protocal is supported at present.
+ The /auth interface is used to get access token before any data transform which need to be requested just one time.
+ The device must call /auth to get the token before transfer any data.
+ Every data transfer need to be with access token.
+ You need to request for a new token if the current token have been expired.
+ Token can be cached in local devices, which has 48 hours term of validity.
+ POST /auth HTTP/1.1
+ Host: iot-as-http.cn-shanghai.aliyuncs.com
+ Content-Type: application/json
+ body: {"version":"default","clientId":"xxxxx","signmethod":"hmacsha1","sign":"xxxxxxxxxx","productKey":"xxxxxx","deviceName":"xxxxxxx","timestamp":"xxxxxxx"}
+*/
+
+static int iotx_calc_sign(const char *p_device_secret, const char *p_msg, char *sign)
+{
+ http_info("| method: %s", IOTX_SHA_METHOD);
+ utils_hmac_sha1(p_msg, strlen(p_msg), sign, p_device_secret, strlen(p_device_secret));
+ return SUCCESS_RETURN;
+}
+
+static int calc_snprintf_string_length(char *fmt, ...)
+{
+ va_list args;
+ int rc = 0;
+ char *p = NULL;
+ char *sval = NULL;
+
+ if (NULL == fmt) {
+ return -1;
+ }
+
+ va_start(args, fmt);
+
+ for (p = fmt; *p; p++) {
+ if (*p != '%') {
+ rc++;
+ continue;
+ }
+ switch (*++p) {
+ case 's':
+ for (sval = va_arg(args, char *); *sval; sval++) {
+ rc++;
+ }
+ break;
+ default:
+ rc++;
+ break;
+ }
+ }
+
+ va_end(args);
+
+ return rc;
+}
+
+static int construct_full_http_authenticate_url(char *buf)
+{
+ LITE_snprintf(buf, IOTX_HTTP_URL_LEN_MAX,
+ "%s/%s", IOTX_HTTP_ONLINE_SERVER_URL, IOTX_HTTP_AUTH_STR);
+ http_info("get_http_authenticate_url is %s", buf);
+ return 0;
+}
+
+static int construct_full_http_upstream_url(char *buf, const char *topic_path)
+{
+ LITE_snprintf(buf, IOTX_HTTP_URL_LEN_MAX,
+ "%s%s", IOTX_HTTP_ONLINE_SERVER_URL, topic_path);
+ http_info("construct_full_http_upstream_url is %s", buf);
+ return 0;
+}
+
+static int http_report_func(void *handle, const char *topic_name, int req_ack, void *data, int len)
+{
+ iotx_http_message_param_t msg_param;
+ char request_buf[1024];
+ char topic_path[100];
+
+ if (handle == NULL || topic_name == NULL || data == NULL) {
+ http_err("params err");
+ return -1;
+ }
+
+ HAL_Snprintf(topic_path, sizeof(topic_path), "/topic%s", topic_name);
+
+ memset(&msg_param, 0, sizeof(iotx_http_message_param_t));
+ msg_param.request_payload = (char *)data;
+ msg_param.response_payload = request_buf;
+ msg_param.timeout_ms = CONFIG_MID_HTTP_TIMEOUT;
+ msg_param.request_payload_len = len;
+ msg_param.response_payload_len = 1024;
+ msg_param.topic_path = topic_path;
+
+ return IOT_HTTP_SendMessage(handle, &msg_param);
+}
+
+static void *verify_iotx_http_context(void *handle)
+{
+ iotx_http_t *iotx_http_context = (iotx_http_t *)handle;
+
+ if (NULL == iotx_http_context ||
+ NULL == iotx_http_context_bak ||
+ iotx_http_context_bak != iotx_http_context) {
+ http_err("iotx_http_context not valid pointer!");
+
+ iotx_http_context = NULL;
+ }
+
+ return iotx_http_context;
+}
+
+void *IOT_HTTP_Init(iotx_http_param_t *pInitParams)
+{
+ iotx_device_info_t *p_devinfo;
+ iotx_http_t *iotx_http_context;
+
+ /* currently http is singleton, init twice not allowed. */
+ if (NULL != iotx_http_context_bak) {
+ http_err("Init twice not allowed, please deinit first");
+ return NULL;
+ }
+
+ if (NULL == pInitParams || NULL == pInitParams->device_info) {
+ http_err("Invalid argument: pInitParams or device_info = NULL");
+ return NULL;
+ }
+
+ p_devinfo = pInitParams->device_info;
+
+/*
+ HAL_SetProductKey(p_devinfo->product_key);
+ HAL_SetDeviceName(p_devinfo->device_name);
+ HAL_SetDeviceSecret(p_devinfo->device_secret);
+*/
+
+ iotx_http_context = (iotx_http_t *)HTTP_API_MALLOC(sizeof(iotx_http_t));
+
+ if (NULL == iotx_http_context) {
+ http_err("Allocate memory for iotx_http_context failed");
+ return NULL;
+ }
+
+ memset(iotx_http_context, 0x00, sizeof(iotx_http_t));
+
+ iotx_http_context->keep_alive = pInitParams->keep_alive;
+ iotx_http_context->timeout_ms = pInitParams->timeout_ms;
+ iotx_http_context->p_auth_token = HTTP_API_MALLOC(IOTX_HTTP_AUTH_TOKEN_LEN);
+ if (NULL == iotx_http_context->p_auth_token) {
+ http_err("Allocate memory for auth token failed");
+ goto err;
+ }
+ memset(iotx_http_context->p_auth_token, 0x00, IOTX_HTTP_AUTH_TOKEN_LEN);
+ iotx_http_context->is_authed = 0;
+ iotx_http_context->auth_token_len = IOTX_HTTP_AUTH_TOKEN_LEN;
+
+ /*Get deivce information*/
+ iotx_http_context->p_devinfo = (iotx_device_info_t *)HTTP_API_MALLOC(sizeof(iotx_device_info_t));
+ if (NULL == iotx_http_context->p_devinfo) {
+ http_err("Allocate memory for iotx_http_context->p_devinfo failed");
+ goto err;
+ }
+ memset(iotx_http_context->p_devinfo, 0x00, sizeof(iotx_device_info_t));
+
+ /*It should be implement by the user*/
+ memset(iotx_http_context->p_devinfo, 0x00, sizeof(iotx_device_info_t));
+ strncpy(iotx_http_context->p_devinfo->device_id, p_devinfo->device_id, strlen(p_devinfo->device_id));
+ strncpy(iotx_http_context->p_devinfo->product_key, p_devinfo->product_key, strlen(p_devinfo->product_key));
+ strncpy(iotx_http_context->p_devinfo->device_secret, p_devinfo->device_secret, strlen(p_devinfo->device_secret));
+ strncpy(iotx_http_context->p_devinfo->device_name, p_devinfo->device_name, strlen(p_devinfo->device_name));
+
+ iotx_http_context->httpc = HTTP_API_MALLOC(sizeof(httpclient_t));
+ if (NULL == iotx_http_context->httpc) {
+ http_err("Allocate memory for iotx_http_context->httpc failed");
+ goto err;
+ }
+ memset(iotx_http_context->httpc, 0x00, sizeof(httpclient_t));
+
+ iotx_http_context_bak = iotx_http_context;
+
+ return iotx_http_context;
+err:
+ /* Error, release the memory */
+ if (NULL != iotx_http_context) {
+ if (NULL != iotx_http_context->p_devinfo) {
+ HTTP_API_FREE(iotx_http_context->p_devinfo);
+ }
+ if (NULL != iotx_http_context->p_auth_token) {
+ HTTP_API_FREE(iotx_http_context->p_auth_token);
+ }
+
+ iotx_http_context->auth_token_len = 0;
+ HTTP_API_FREE(iotx_http_context);
+ }
+ return NULL;
+}
+
+void IOT_HTTP_DeInit(void **handle)
+{
+ iotx_http_t *iotx_http_context;
+ if (NULL == handle) {
+ http_err("handle is NULL pointer");
+ return;
+ }
+ if (NULL == (iotx_http_context = verify_iotx_http_context(*handle))) {
+ return;
+ }
+
+ if (NULL != iotx_http_context->p_devinfo) {
+ HTTP_API_FREE(iotx_http_context->p_devinfo);
+ }
+ if (NULL != iotx_http_context->p_auth_token) {
+ HTTP_API_FREE(iotx_http_context->p_auth_token);
+ }
+ if (NULL != iotx_http_context->httpc) {
+ HTTP_API_FREE(iotx_http_context->httpc);
+ }
+
+ iotx_http_context->auth_token_len = 0;
+ HTTP_API_FREE(iotx_http_context);
+ iotx_http_context_bak = NULL;
+}
+
+int IOT_HTTP_DeviceNameAuth(void *handle)
+{
+ int ret = -1;
+ int ret_code = 0;
+ char *pvalue = NULL;
+ char *response_message = NULL;
+ char sign[IOTX_HTTP_SIGN_LENGTH] = {0};
+ char http_url[IOTX_HTTP_URL_LEN_MAX] = {0};
+ char timestamp[14] = {0};
+ httpclient_t *httpc;
+ httpclient_data_t httpc_data = {0};
+ char *req_payload = NULL;
+ char *rsp_payload = NULL;
+ int len = 0;
+ char p_msg_unsign[IOTX_HTTP_SIGN_SOURCE_LEN] = {0};
+ iotx_time_t timer;
+ iotx_http_t *iotx_http_context;
+ const char *pub_key = NULL;
+ /* */
+ /* body: */
+ /* { */
+ /* "version": "default",//默认default */
+ /* "clientId": "xxxxxx",//必填 */
+ /* "signmethod": "hmacsha1",//只支持hmacmd5和hmacsha1,默认hmacmd5 */
+ /* "sign": "xxxxxxxxxxxxx",//必填,signmethod(deviceSecret,content), content = 将所有提交给服务器的参数(version,sign,signmethod除外), 按照字母顺序排序, 然后将参数值依次拼接,无拼接符号 */
+ /* "productKey": "xxxxxx",//必填 */
+ /* "deviceName": "xxxxxx",//必填 */
+ /* "timestamp": "xxxxxx"//选填 13byte */
+ /* } */
+
+ if (NULL == (iotx_http_context = verify_iotx_http_context(handle))) {
+ goto do_exit;
+ }
+ iotx_http_context->is_authed = 0;
+
+ /* FIXME:some compile error when calling this function. Get TimeStamp */
+ /*
+ if(!utils_get_epoch_time_from_ntp(timestamp, sizeof(timestamp)))
+ {
+ http_info("http time response: \r\n\r\n%s", timestamp);
+ goto do_exit;
+ }
+ */
+
+ /* Calculate Sign */
+ LITE_snprintf(p_msg_unsign, IOTX_HTTP_SIGN_SOURCE_LEN,
+ IOTX_HTTP_SIGN_SRC_STR,
+ iotx_http_context->p_devinfo->device_id,
+ iotx_http_context->p_devinfo->device_name,
+ iotx_http_context->p_devinfo->product_key
+#ifdef IOTX_HTTP_TIMESTAMP_OPTIONAL_ENABLE
+ , timestamp
+#endif
+ );
+
+ iotx_calc_sign(iotx_http_context->p_devinfo->device_secret, p_msg_unsign, sign);
+
+ /* to save stack memory*/
+ len = calc_snprintf_string_length(IOTX_HTTP_AUTH_DEVICENAME_STR,
+ "default",
+ iotx_http_context->p_devinfo->device_id,
+ IOTX_SHA_METHOD,
+ sign,
+ iotx_http_context->p_devinfo->product_key,
+ iotx_http_context->p_devinfo->device_name,
+ timestamp
+ );
+
+ if (len < 0) {
+ goto do_exit;
+ }
+
+ req_payload = (char *)HTTP_API_MALLOC(len + 1);
+ memset(req_payload, 0, len + 1);
+
+ http_debug("allocate req_payload: len = %d", len);
+
+ len = HAL_Snprintf(req_payload, len + 1,
+ IOTX_HTTP_AUTH_DEVICENAME_STR,
+ "default",
+ iotx_http_context->p_devinfo->device_id,
+ IOTX_SHA_METHOD,
+ sign,
+ iotx_http_context->p_devinfo->product_key,
+ iotx_http_context->p_devinfo->device_name,
+ timestamp
+ );
+ http_debug("len = %d, req_payload: \r\n%s", len, req_payload);
+
+ /* Malloc Http Response Payload */
+ rsp_payload = (char *)HTTP_API_MALLOC(HTTP_AUTH_RESP_MAX_LEN);
+ if (NULL == rsp_payload) {
+ http_err("Allocate HTTP rsp_payload buf failed!");
+ goto do_exit;
+ }
+ memset(rsp_payload, 0, HTTP_AUTH_RESP_MAX_LEN);
+
+ /* Construct Auth Url */
+ construct_full_http_authenticate_url(http_url);
+
+ /* Set httpclient and httpclient_data */
+ httpc = (httpclient_t *)iotx_http_context->httpc;
+
+ httpc_data.post_content_type = "application/json";
+ httpc_data.post_buf = req_payload;
+ httpc_data.post_buf_len = len;
+ httpc_data.response_buf = rsp_payload;
+ httpc_data.response_buf_len = HTTP_AUTH_RESP_MAX_LEN;
+
+ httpc->header = "Connection: Keep-Alive\r\n";
+
+ /*
+ Test Code
+ iotx_http_context->p_auth_token = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiaG1hY3NoYTEifQ.eyJleHBpcmUiOjE1MDQ3ODE4MzQ5MDAsInRva2VuIjoiM2EyZTRmYzMyNjk5NDE0Y2E3MDFjNzIzNzI1YjIyNDgifQ.e87AFhkvNKiqF5xdgm1P47f9DwY";
+ iotx_http_context->is_authed = 1;
+ ret = 0;
+ goto do_exit;
+ Test Code
+ */
+
+ {
+ extern const char *iotx_ca_crt;
+ pub_key = iotx_ca_crt;
+ }
+
+ /* Send Request and Get Response */
+ if (0 != iotx_post(httpc,
+ http_url,
+ IOTX_HTTP_ONLINE_SERVER_PORT,
+ pub_key,
+ &httpc_data)) {
+ goto do_exit;
+ }
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, CONFIG_HTTP_AUTH_TIMEOUT);
+
+
+ ret = httpclient_recv_response(httpc, iotx_time_left(&timer), &httpc_data);
+ if (ret < 0) {
+ http_err("httpclient_recv_response error, ret = %d", ret);
+ httpclient_close(httpc);
+ return ret;
+ }
+ if (0 == iotx_http_context->keep_alive) {
+ http_info("http not keepalive");
+ httpclient_close(httpc);
+ }
+ /*
+ body:
+ {
+ "code": 0,//业务状态码
+ "message": "success",//业务信息
+ "info": {
+ "token": "eyJ0eXBlIjoiSldUIiwiYWxnIjoiaG1hY3NoYTEifQ.eyJleHBpcmUiOjE1MDI1MzE1MDc0NzcsInRva2VuIjoiODA0ZmFjYTBiZTE3NGUxNjliZjY0ODVlNWNiNDg3MTkifQ.OjMwu29F0CY2YR_6oOyiOLXz0c8"
+ }
+ }
+ */
+ http_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf);
+
+ pvalue = HTTP_LITE_JSON_VALUE_OF("code", httpc_data.response_buf);
+ if (!pvalue) {
+ goto do_exit;
+ }
+ ret_code = atoi(pvalue);
+ http_info("ret_code = %d", ret_code);
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+
+ pvalue = HTTP_LITE_JSON_VALUE_OF("message", httpc_data.response_buf);
+ if (NULL == pvalue) {
+ goto do_exit;
+ }
+ response_message = pvalue;
+ http_info("response_message: %s", response_message);
+ (void)response_message;
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+
+ switch (ret_code) {
+ case IOTX_HTTP_SUCCESS:
+ break;
+ case IOTX_HTTP_COMMON_ERROR:
+ case IOTX_HTTP_PARAM_ERROR:
+ case IOTX_HTTP_AUTH_CHECK_ERROR:
+ case IOTX_HTTP_UPDATE_SESSION_ERROR:
+ case IOTX_HTTP_REQUEST_TOO_MANY_ERROR:
+ default:
+ ret = FAIL_RETURN;
+ goto do_exit;
+ }
+
+ pvalue = HTTP_LITE_JSON_VALUE_OF("info.token", httpc_data.response_buf);
+ if (NULL == pvalue) {
+ http_err("can't get token from json, Abort!");
+ goto do_exit;
+ }
+
+ strcpy(iotx_http_context->p_auth_token, pvalue);
+ iotx_http_context->is_authed = 1;
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+
+
+ iotx_set_report_func(http_report_func);
+ /* report module id */
+ ret = iotx_report_mid(iotx_http_context);
+ if (SUCCESS_RETURN != ret) {
+ http_err("Send ModuleId message to server(Http) failed, ret = %d", ret);
+ goto do_exit;
+ }
+ /* report device information */
+ ret = iotx_report_devinfo(iotx_http_context);
+ if (SUCCESS_RETURN != ret) {
+ http_err("Send devinfo message to server(Http) failed, ret = %d", ret);
+ goto do_exit;
+ }
+ /* report firmware */
+ ret = iotx_report_firmware_version(iotx_http_context);
+ if (SUCCESS_RETURN != ret) {
+ http_err("Send firmware message to server(Http) failed, ret = %d", ret);
+ goto do_exit;
+ }
+
+ ret = 0;
+
+do_exit:
+ if (pvalue) {
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+ }
+ if (req_payload) {
+ HTTP_API_FREE(req_payload);
+ req_payload = NULL;
+ }
+ if (rsp_payload) {
+ HTTP_API_FREE(rsp_payload);
+ rsp_payload = NULL;
+ }
+
+ return ret;
+}
+
+int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param)
+{
+ int ret = -1;
+ int response_code = 0;
+ char *pvalue = NULL;
+ char http_url[IOTX_HTTP_URL_LEN_MAX] = {0};
+ httpclient_t *httpc = NULL;
+ httpclient_data_t httpc_data = {0};
+ char *messageId = NULL;
+ char *user_data = NULL;
+ int len = 0;
+ uint32_t payload_len = 0;
+ iotx_time_t timer;
+ iotx_http_t *iotx_http_context;
+ const char *pub_key = NULL;
+ /*
+ POST /topic/${topic} HTTP/1.1
+ Host: iot-as-http.cn-shanghai.aliyuncs.com
+ password:${token}
+ Content-Type: application/octet-stream
+ body: ${your_data}
+ */
+ if (NULL == (iotx_http_context = verify_iotx_http_context(handle))) {
+ goto do_exit;
+ }
+
+ if (NULL == msg_param) {
+ http_err("iotx_http_context or msg_param NULL pointer!");
+ goto do_exit;
+ }
+
+ httpc = (httpclient_t *)iotx_http_context->httpc;
+
+ if (NULL == httpc) {
+ http_err("httpc null pointer");
+ goto do_exit;
+ }
+
+ if (0 == iotx_http_context->is_authed) {
+ http_err("Device is not authed");
+ goto do_exit;
+ }
+
+ if (NULL == msg_param->request_payload) {
+ http_err("IOT_HTTP_SendMessage request_payload NULL!");
+ goto do_exit;
+ }
+
+ if (NULL == msg_param->response_payload) {
+ http_err("IOT_HTTP_SendMessage response_payload NULL!");
+ goto do_exit;
+ }
+
+ if (NULL == msg_param->topic_path) {
+ http_err("IOT_HTTP_SendMessage topic_path NULL!");
+ goto do_exit;
+ }
+
+ payload_len = strlen(msg_param->request_payload) + 1;
+ msg_param->request_payload_len = msg_param->request_payload_len > payload_len \
+ ? payload_len : msg_param->request_payload_len;
+
+ /* Construct Auth Url */
+ construct_full_http_upstream_url(http_url, msg_param->topic_path);
+
+ len = strlen(IOTX_HTTP_HEADER_PASSWORD_STR) + strlen(iotx_http_context->p_auth_token) + strlen(
+ IOTX_HTTP_HEADER_KEEPALIVE_STR) + strlen(IOTX_HTTP_HEADER_END_STR);
+ httpc->header = HTTP_API_MALLOC(len + 1);
+ if (NULL == httpc->header) {
+ http_err("Allocate memory for httpc->header failed");
+ goto do_exit;
+ }
+ LITE_snprintf(httpc->header, len + 1,
+ IOTX_HTTP_UPSTREAM_HEADER_STR, iotx_http_context->p_auth_token);
+ http_info("httpc->header = %s", httpc->header);
+
+ httpc_data.post_content_type = "application/octet-stream";
+ httpc_data.post_buf = msg_param->request_payload;
+ httpc_data.post_buf_len = msg_param->request_payload_len;
+ httpc_data.response_buf = msg_param->response_payload;
+ httpc_data.response_buf_len = msg_param->response_payload_len;
+
+ http_info("request_payload: \r\n\r\n%s\r\n", httpc_data.post_buf);
+
+ {
+ extern const char *iotx_ca_crt;
+ pub_key = iotx_ca_crt;
+ }
+
+ /* Send Request and Get Response */
+ if (iotx_post(httpc,
+ http_url,
+ IOTX_HTTP_ONLINE_SERVER_PORT,
+ pub_key,
+ &httpc_data)) {
+ goto do_exit_pre;
+ }
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, msg_param->timeout_ms);
+
+ ret = httpclient_recv_response(httpc, iotx_time_left(&timer), &httpc_data);
+ if (ret < 0) {
+ http_err("httpclient_recv_response error, ret = %d", ret);
+ httpclient_close(httpc);
+ goto do_exit_pre;
+ }
+
+ if (0 == iotx_http_context->keep_alive) {
+ httpclient_close(httpc);
+ }
+
+ /*
+ body:
+ {
+ "code": 0,
+ "message": "success",
+ "info": {
+ "messageId": 892687627916247040,
+ "data": byte[]//may be NULL
+ }
+ }
+ */
+ http_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf);
+
+ pvalue = HTTP_LITE_JSON_VALUE_OF("code", httpc_data.response_buf);
+ if (!pvalue) {
+ goto do_exit_pre;
+ }
+
+ response_code = atoi(pvalue);
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+ http_info("response code: %d", response_code);
+
+ pvalue = HTTP_LITE_JSON_VALUE_OF("message", httpc_data.response_buf);
+ if (NULL == pvalue) {
+ goto do_exit_pre;
+ }
+ http_info("response_message: %s", pvalue);
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+
+ switch (response_code) {
+ case IOTX_HTTP_SUCCESS:
+ break;
+ case IOTX_HTTP_TOKEN_EXPIRED_ERROR:
+ iotx_http_context->is_authed = IOT_FALSE;
+ IOT_HTTP_DeviceNameAuth((iotx_http_t *)iotx_http_context);
+ case IOTX_HTTP_COMMON_ERROR:
+ case IOTX_HTTP_PARAM_ERROR:
+ case IOTX_HTTP_AUTH_CHECK_ERROR:
+ case IOTX_HTTP_TOKEN_NULL_ERROR:
+ case IOTX_HTTP_TOKEN_CHECK_ERROR:
+ case IOTX_HTTP_UPDATE_SESSION_ERROR:
+ case IOTX_HTTP_PUBLISH_MESSAGE_ERROR:
+ case IOTX_HTTP_REQUEST_TOO_MANY_ERROR:
+ default:
+ goto do_exit_pre;
+ }
+
+ /* info.messageId */
+ pvalue = HTTP_LITE_JSON_VALUE_OF("info.messageId", httpc_data.response_buf);
+ if (NULL == pvalue) {
+ http_err("messageId: NULL");
+ goto do_exit_pre;
+ }
+ messageId = pvalue;
+ http_info("messageId: %s", messageId);
+ (void)messageId;
+ HTTP_API_FREE(pvalue);
+ pvalue = NULL;
+
+ /* info.data */
+ pvalue = HTTP_LITE_JSON_VALUE_OF("info.data", httpc_data.response_buf);
+ user_data = pvalue;
+
+ /* Maybe NULL */
+ if (user_data) {
+ http_info("user_data: %s", user_data);
+ } else {
+ http_info("user_data: %p", user_data);
+ }
+ if (NULL != pvalue) {
+ HTTP_API_FREE(pvalue);
+ }
+ pvalue = NULL;
+
+ ret = 0;
+
+do_exit_pre:
+
+ if (pvalue) {
+ HTTP_API_FREE(pvalue);
+ }
+
+ if (httpc != NULL && httpc->header) {
+ HTTP_API_FREE(httpc->header);
+ }
+
+do_exit:
+
+ return ret;
+}
+
+void IOT_HTTP_Disconnect(void *handle)
+{
+ iotx_http_t *iotx_http_context;
+ if (NULL != (iotx_http_context = verify_iotx_http_context(handle))) {
+ httpclient_close(iotx_http_context->httpc);
+ }
+}
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_api.c
new file mode 100644
index 00000000..b03b01d9
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_api.c
@@ -0,0 +1,1159 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+#include
+#include
+
+#include "infra_defs.h"
+#include "infra_types.h"
+#include "infra_httpc.h"
+#include "infra_sha1.h"
+#include "infra_timer.h"
+#include "infra_list.h"
+#include "infra_log.h"
+
+#include "http2_internal.h"
+#include "http2_api.h"
+#include "http2_config.h"
+#include "http2_wrapper.h"
+
+#include "wrappers_defs.h"
+
+#define URL_MAX_LEN (100)
+
+typedef enum {
+ NUM_STRING_ENUM = 0,
+ PATH_CREATE_STR_ENUM = 1,
+ PATH_UPLOAD_STR_ENUM = 2,
+ CID_STRING_ENUM = 3,
+ ORI_SIGN_STR_ENUM = 4,
+ FS_STRING_ENUM = 5,
+ REAL_SIGN_STR_ENUM = 6,
+} HEADER_TYPE_ENUM;
+
+
+typedef struct _device_info_struct_ {
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
+ char url[URL_MAX_LEN + 1];
+ int port;
+} device_info;
+
+typedef struct {
+ unsigned int stream_id; /* http2 protocol stream id */
+ char *channel_id; /* string return by server to identify a specific stream channel, different from stream identifier which is a field in http2 frame */
+ stream_type_t stream_type; /* check @stream_type_t */
+ void *semaphore; /* semaphore for http2 response sync */
+ char status_code[5]; /* http2 response status code */
+ uint8_t rcv_hd_cnt; /* the number of concerned heads received*/
+ void *user_data; /* data passed to the stream callback function */
+ http2_list_t list; /* list_head */
+} http2_stream_node_t;
+
+static device_info g_device_info;
+
+static stream_handle_t *g_stream_handle = NULL;
+static httpclient_t g_client;
+
+static int _set_device_info(device_conn_info_t *device_info)
+{
+ memset(g_device_info.product_key, 0, IOTX_PRODUCT_KEY_LEN + 1);
+ memset(g_device_info.device_name, 0, IOTX_DEVICE_NAME_LEN + 1);
+ memset(g_device_info.device_secret, 0, IOTX_DEVICE_SECRET_LEN + 1);
+ memset(g_device_info.url, 0, URL_MAX_LEN + 1);
+
+ strncpy(g_device_info.product_key, device_info->product_key, IOTX_PRODUCT_KEY_LEN);
+ strncpy(g_device_info.device_name, device_info->device_name, IOTX_DEVICE_NAME_LEN);
+ strncpy(g_device_info.device_secret, device_info->device_secret, IOTX_DEVICE_SECRET_LEN);
+ if (device_info->url != NULL) {
+ strncpy(g_device_info.url, device_info->url, URL_MAX_LEN);
+ }
+ g_device_info.port = device_info->port;
+
+ return 0;
+}
+
+static int http2_nv_copy(http2_header *nva, int start, http2_header *nva_copy, int num)
+{
+ int i, j;
+ for (i = start, j = 0; j < num; i++, j++) {
+ nva[i].name = nva_copy[j].name;
+ nva[i].value = nva_copy[j].value;
+ nva[i].namelen = nva_copy[j].namelen;
+ nva[i].valuelen = nva_copy[j].valuelen;
+ }
+ return i;
+}
+
+static int iotx_http2_get_url(char *buf, char *productkey)
+{
+ if (strlen(g_device_info.url) != 0) {
+ strncpy(buf, g_device_info.url, URL_MAX_LEN);
+ return g_device_info.port;
+ }
+#if defined(ON_DAILY)
+ sprintf(buf, "%s", "10.101.12.205");
+ return 9999;
+#elif defined(ON_PRE)
+ sprintf(buf, "%s", "100.67.141.158");
+ return 8443;
+#else
+ sprintf(buf, "%s", productkey);
+ strcat(buf, ".iot-as-http2.cn-shanghai.aliyuncs.com");
+ return 443;
+#endif
+}
+
+static void file_upload_gen_string(char *str, int type, char *para1, int para2)
+{
+ switch (type) {
+ case NUM_STRING_ENUM: {
+ sprintf(str, "%d", para2);
+ break;
+ }
+ case PATH_CREATE_STR_ENUM:
+ case PATH_UPLOAD_STR_ENUM:
+ case ORI_SIGN_STR_ENUM:
+ case CID_STRING_ENUM: {
+ if (type == PATH_CREATE_STR_ENUM) {
+ sprintf(str, "/message/pub_with_resp/sys/%s/%s/thing/%s/create",
+ g_device_info.product_key,
+ g_device_info.device_name,
+ para1);
+ } else if (type == PATH_UPLOAD_STR_ENUM) {
+ sprintf(str, "/message/pub_with_resp/sys/%s/%s/thing/%s/upload",
+ g_device_info.product_key,
+ g_device_info.device_name,
+ para1);
+ } else if (type == ORI_SIGN_STR_ENUM) {
+ sprintf(str, "clientId%sdeviceName%sproductKey%s",
+ para1,
+ g_device_info.device_name,
+ g_device_info.product_key);
+ } else {
+ sprintf(str, "%s.%s", g_device_info.product_key, g_device_info.device_name);
+ }
+ break;
+ }
+ case REAL_SIGN_STR_ENUM: {
+ utils_hmac_sha1(para1, strlen(para1), str, g_device_info.device_secret, strlen(g_device_info.device_secret));
+ break;
+ }
+ default: {
+ h2_err("ASSERT\n");
+ break;
+ }
+ }
+}
+
+static int http2_stream_node_search(stream_handle_t *handle, unsigned int stream_id, http2_stream_node_t **p_node)
+{
+ http2_stream_node_t *search_node = NULL;
+ *p_node = NULL;
+
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(p_node, NULL_VALUE_ERROR);
+
+ list_for_each_entry(search_node, &handle->stream_list, list, http2_stream_node_t) {
+ if (search_node->stream_id == stream_id) {
+ *p_node = search_node;
+ return SUCCESS_RETURN;
+ }
+ }
+
+ h2_debug("stream node not exist, stream_id = %d", stream_id);
+ return FAIL_RETURN;
+}
+
+static void on_stream_header(int32_t stream_id, int cat, const uint8_t *name, uint32_t namelen,
+ const uint8_t *value, uint32_t valuelen, uint8_t flags)
+{
+ http2_stream_node_t *node = NULL;
+ char *channel_id = NULL;
+ char *user_data = NULL;
+
+ if (g_stream_handle == NULL) {
+ return;
+ }
+ http2_stream_node_search(g_stream_handle, stream_id, &node);
+ if (node != NULL) {
+ channel_id = node->channel_id;
+ user_data = node->user_data;
+
+ switch (cat) {
+ case 0x01:
+ if (strncmp((char *)name, "x-data-stream-id", (int)namelen) == 0) {
+ node->channel_id = HTTP2_STREAM_MALLOC(valuelen + 1);
+ if (node->channel_id == NULL) {
+ return;
+ }
+ memset(node->channel_id, 0, (int)valuelen + 1);
+ memcpy(node->channel_id, (char *)value, (int)valuelen);
+ if (++node->rcv_hd_cnt == 2) {
+ HAL_SemaphorePost(node->semaphore);
+ }
+ }
+#ifdef FS_ENABLED
+ else if (strncmp((char *)name, "x-file-upload-id", (int)namelen) == 0) {
+ fs_rsp_header_val_t *rsp_data = (fs_rsp_header_val_t *)user_data;
+ memcpy(rsp_data->fs_upload_id, value, valuelen);
+ }
+ else if (strncmp((char *)name, "x-next-append-position", (int)namelen) == 0) {
+ fs_rsp_header_val_t *rsp_data = (fs_rsp_header_val_t *)user_data;
+ rsp_data->fs_offset = atoi((char *)value);
+ }
+ else if (strncmp((char *)name, "x-response-status", (int)namelen) == 0) {
+ strncpy(node->status_code, (char *)value, sizeof(node->status_code) - 1);
+ if (++node->rcv_hd_cnt == 2) {
+ HAL_SemaphorePost(node->semaphore);
+ }
+ }
+#else
+ else if (strncmp((char *)name, ":status", (int)namelen) == 0) {
+ strncpy(node->status_code, (char *)value, sizeof(node->status_code) - 1);
+ if (++node->rcv_hd_cnt == 2) {
+ HAL_SemaphorePost(node->semaphore);
+ }
+ }
+#endif
+ }
+ }
+
+ if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_header_cb) {
+ g_stream_handle->cbs->on_stream_header_cb(stream_id, channel_id, cat, name, namelen, value, valuelen,
+ flags, user_data);
+ }
+}
+
+static void on_stream_chunk_recv(int32_t stream_id, const uint8_t *data, uint32_t len, uint8_t flags)
+{
+ http2_stream_node_t *node;
+ char *channel_id = NULL;
+ char *user_data = NULL;
+
+ if (g_stream_handle == NULL) {
+ return;
+ }
+ http2_stream_node_search(g_stream_handle, stream_id, &node);
+ if (node != NULL) {
+ channel_id = node->channel_id;
+ user_data = node->user_data;
+ }
+
+ if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_chunk_recv_cb) {
+ g_stream_handle->cbs->on_stream_chunk_recv_cb(stream_id, channel_id, data, len, flags, user_data);
+ }
+}
+
+static void on_stream_close(int32_t stream_id, uint32_t error_code)
+{
+ http2_stream_node_t *node;
+ char *channel_id = NULL;
+ char *user_data = NULL;
+
+ if (g_stream_handle == NULL) {
+ return;
+ }
+ http2_stream_node_search(g_stream_handle, stream_id, &node);
+ if (node != NULL) {
+ channel_id = node->channel_id;
+ user_data = node->user_data;
+ }
+ if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_close_cb) {
+ g_stream_handle->cbs->on_stream_close_cb(stream_id, channel_id, error_code, user_data);
+ }
+}
+
+static void on_stream_frame_send(int32_t stream_id, int type, uint8_t flags)
+{
+ http2_stream_node_t *node;
+ char *channel_id = NULL;
+ char *user_data = NULL;
+
+ if (g_stream_handle == NULL) {
+ return;
+ }
+ http2_stream_node_search(g_stream_handle, stream_id, &node);
+ if (node != NULL) {
+ channel_id = node->channel_id;
+ user_data = node->user_data;
+ }
+ if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_frame_send_cb) {
+ g_stream_handle->cbs->on_stream_frame_send_cb(stream_id, channel_id, type, flags, user_data);
+ }
+}
+
+static void on_stream_frame_recv(int32_t stream_id, int type, uint8_t flags)
+{
+ http2_stream_node_t *node;
+ char *channel_id = NULL;
+ char *user_data = NULL;
+ if (g_stream_handle == NULL) {
+ return;
+ }
+ http2_stream_node_search(g_stream_handle, stream_id, &node);
+ if (node != NULL) {
+ channel_id = node->channel_id;
+ user_data = node->user_data;
+ }
+
+ if (g_stream_handle->cbs && g_stream_handle->cbs->on_stream_frame_recv_cb) {
+ g_stream_handle->cbs->on_stream_frame_recv_cb(stream_id, channel_id, type, flags, user_data);
+ }
+}
+
+static http2_user_cb_t my_cb = {
+ .on_user_header_cb = on_stream_header,
+ .on_user_chunk_recv_cb = on_stream_chunk_recv,
+ .on_user_stream_close_cb = on_stream_close,
+ .on_user_frame_send_cb = on_stream_frame_send,
+ .on_user_frame_recv_cb = on_stream_frame_recv,
+};
+
+static int reconnect(stream_handle_t *handle)
+{
+ char buf[100] = {0};
+ http2_connection_t *conn = NULL;
+ int port = 0;
+
+ iotx_http2_client_disconnect(handle->http2_connect);
+ handle->http2_connect = NULL;
+ port = iotx_http2_get_url(buf, g_device_info.product_key);
+ conn = iotx_http2_client_connect_with_cb((void *)&g_client, buf, port, &my_cb);
+ if (conn == NULL) {
+ return -1;
+ }
+ handle->http2_connect = conn;
+ return 0;
+}
+
+static void *http2_io(void *user_data)
+{
+ stream_handle_t *handle = (stream_handle_t *)user_data;
+ int rv = 0;
+ iotx_time_t timer, timer_rsp;
+ static uint8_t timer_valid = 0;
+ POINTER_SANITY_CHECK(handle, NULL);
+ iotx_time_init(&timer);
+ iotx_time_init(&timer_rsp);
+ while (handle->init_state) {
+ if (handle->connect_state) {
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_exec_io(handle->http2_connect);
+ HAL_MutexUnlock(handle->mutex);
+ }
+ if (utils_time_is_expired(&timer)) {
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_client_send_ping(handle->http2_connect);
+ HAL_MutexUnlock(handle->mutex);
+ utils_time_countdown_ms(&timer, IOT_HTTP2_KEEP_ALIVE_TIME);
+ if (rv >= 0) {
+ utils_time_countdown_ms(&timer_rsp, 3000);
+ timer_valid = 1;
+ }
+ }
+
+ if (timer_valid && utils_time_is_expired(&timer_rsp)) {
+ timer_valid = 0;
+ rv = iotx_http2_client_recv_ping();
+ }
+
+ if (rv < 0) {
+ if (handle->retry_cnt == IOT_HTTP2_KEEP_ALIVE_CNT - 1) {
+ h2_info("rv =%d, try reconnect\n", rv);
+ if (handle->connect_state != 0) {
+ handle->connect_state = 0;
+ if (handle->cbs && handle->cbs->on_disconnect_cb) {
+ handle->cbs->on_disconnect_cb();
+ }
+ }
+ rv = reconnect(handle);
+ continue;
+ } else {
+ handle->retry_cnt++;
+ }
+ } else {
+ if (handle->connect_state == 0) {
+ handle->connect_state = 1;
+ handle->retry_cnt = 0;
+ if (handle->cbs && handle->cbs->on_reconnect_cb) {
+ handle->cbs->on_reconnect_cb();
+ }
+ }
+ }
+ HAL_SleepMs(100);
+ }
+ HAL_SemaphorePost(handle->semaphore);
+
+ return NULL;
+}
+
+static int http2_stream_node_insert(stream_handle_t *handle, unsigned int id, void *user_data,
+ http2_stream_node_t **p_node)
+{
+ http2_stream_node_t *node = NULL;
+ void *semaphore = NULL;
+
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+
+ ARGUMENT_SANITY_CHECK(id != 0, FAIL_RETURN);
+
+ if (p_node != NULL) {
+ *p_node = NULL;
+ }
+
+ node = (http2_stream_node_t *)HTTP2_STREAM_MALLOC(sizeof(http2_stream_node_t));
+ if (node == NULL) {
+ return FAIL_RETURN;
+ }
+
+ memset(node, 0, sizeof(http2_stream_node_t));
+ node->stream_id = id;
+ node->user_data = user_data;
+ semaphore = HAL_SemaphoreCreate();
+ if (semaphore == NULL) {
+ HTTP2_STREAM_FREE(node);
+ return FAIL_RETURN;
+ }
+ node->semaphore = semaphore;
+
+ INIT_LIST_HEAD((list_head_t *)&node->list);
+ list_add((list_head_t *)&node->list, (list_head_t *)&handle->stream_list);
+
+ if (p_node != NULL) {
+ *p_node = node;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int http2_stream_node_remove(stream_handle_t *handle, unsigned int id)
+{
+ http2_stream_node_t *search_node;
+
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ ARGUMENT_SANITY_CHECK(id != 0, FAIL_RETURN);
+
+ list_for_each_entry(search_node, &handle->stream_list, list, http2_stream_node_t) {
+ if (id == search_node->stream_id) {
+ h2_info("stream_node found, delete\n");
+
+ list_del((list_head_t *)&search_node->list);
+ HTTP2_STREAM_FREE(search_node->channel_id);
+ HAL_SemaphoreDestroy(search_node->semaphore);
+ HTTP2_STREAM_FREE(search_node);
+ return SUCCESS_RETURN;
+ }
+ }
+ return FAIL_RETURN;
+}
+
+static int get_version_int()
+{
+ const char *p_version = IOTX_SDK_VERSION;
+ int v_int = 0;
+
+ while (*p_version != 0) {
+ if (*p_version <= '9' && *p_version >= '0') {
+ v_int = v_int * 10 + *p_version - '0';
+ }
+ p_version ++;
+ }
+ return v_int;
+}
+
+void *IOT_HTTP2_Connect(device_conn_info_t *conn_info, http2_stream_cb_t *user_cb)
+{
+ stream_handle_t *stream_handle = NULL;
+ http2_connection_t *conn = NULL;
+ hal_os_thread_param_t thread_parms = {0};
+ char buf[URL_MAX_LEN + 1] = {0};
+ int port = 0;
+ int ret = 0;
+
+ POINTER_SANITY_CHECK(conn_info, NULL);
+ POINTER_SANITY_CHECK(conn_info->product_key, NULL);
+ POINTER_SANITY_CHECK(conn_info->device_name, NULL);
+ POINTER_SANITY_CHECK(conn_info->device_secret, NULL);
+
+ memset(&g_client, 0, sizeof(httpclient_t));
+
+ stream_handle = HTTP2_STREAM_MALLOC(sizeof(stream_handle_t));
+ if (stream_handle == NULL) {
+ return NULL;
+ }
+
+ memset(stream_handle, 0, sizeof(stream_handle_t));
+ stream_handle->mutex = HAL_MutexCreate();
+ if (stream_handle->mutex == NULL) {
+ HTTP2_STREAM_FREE(stream_handle);
+ h2_err("mutex create error\n");
+ return NULL;
+ }
+ stream_handle->semaphore = HAL_SemaphoreCreate();
+ if (stream_handle->semaphore == NULL) {
+ h2_err("semaphore create error\n");
+ HAL_MutexDestroy(stream_handle->mutex);
+ HTTP2_STREAM_FREE(stream_handle);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD((list_head_t *) & (stream_handle->stream_list));
+
+ _set_device_info(conn_info);
+ g_stream_handle = stream_handle;
+ g_stream_handle->cbs = user_cb;
+
+ port = iotx_http2_get_url(buf, conn_info->product_key);
+ conn = iotx_http2_client_connect_with_cb((void *)&g_client, buf, port, &my_cb);
+ if (conn == NULL) {
+ HAL_MutexDestroy(stream_handle->mutex);
+ HAL_SemaphoreDestroy(stream_handle->semaphore);
+ HTTP2_STREAM_FREE(stream_handle);
+ return NULL;
+ }
+ stream_handle->http2_connect = conn;
+ stream_handle->init_state = 1;
+
+ thread_parms.stack_size = 6144;
+ thread_parms.name = "http2_io";
+ ret = HAL_ThreadCreate(&stream_handle->rw_thread, http2_io, stream_handle, &thread_parms, NULL);
+ if (ret != 0) {
+ h2_err("thread create error\n");
+ IOT_HTTP2_Disconnect(stream_handle);
+ return NULL;
+ }
+ HAL_ThreadDetach(stream_handle->rw_thread);
+
+ return stream_handle;
+}
+
+int IOT_HTTP2_Stream_Open(void *hd, stream_data_info_t *info, header_ext_info_t *header)
+{
+ char client_id[64 + 1] = {0};
+ char sign_str[256 + 1] = {0};
+ char sign[41 + 1] = {0};
+ char path[128] = {0};
+ char version[33] = {0};
+ int header_count = 0;
+ int header_num;
+ int rv = 0;
+ http2_data h2_data;
+ http2_stream_node_t *node = NULL;
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ http2_header *nva = NULL;
+
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info->identify, NULL_VALUE_ERROR);
+
+
+ memset(&h2_data, 0, sizeof(http2_data));
+
+ HAL_Snprintf(path, sizeof(path), "/stream/open/%s", info->identify);
+
+ file_upload_gen_string(client_id, CID_STRING_ENUM, NULL, 0);
+ file_upload_gen_string(sign_str, ORI_SIGN_STR_ENUM, client_id, 0);
+ file_upload_gen_string(sign, REAL_SIGN_STR_ENUM, sign_str, 0);
+
+ HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
+
+ {
+ const http2_header static_header[] = { MAKE_HEADER(":method", "POST"),
+ MAKE_HEADER_CS(":path", path),
+ MAKE_HEADER(":scheme", "https"),
+ MAKE_HEADER("x-auth-name", "devicename"),
+ MAKE_HEADER_CS("x-auth-param-client-id", client_id),
+ MAKE_HEADER("x-auth-param-signmethod", "hmacsha1"),
+ MAKE_HEADER_CS("x-auth-param-product-key", g_device_info.product_key),
+ MAKE_HEADER_CS("x-auth-param-device-name", g_device_info.device_name),
+ MAKE_HEADER_CS("x-auth-param-sign", sign),
+ MAKE_HEADER_CS("x-sdk-version", version),
+ MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
+ MAKE_HEADER("x-sdk-platform", "c"),
+ MAKE_HEADER("content-length", "0"),
+ };
+
+ header_num = sizeof(static_header) / sizeof(static_header[0]);
+ if (header != NULL) {
+ header_num += header->num;
+ }
+ nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) * header_num);
+ if (nva == NULL) {
+ h2_err("nva malloc failed\n");
+ return FAIL_RETURN;
+ }
+
+ /* add external header if it's not NULL */
+ header_count = http2_nv_copy(nva, 0, (http2_header *)static_header, sizeof(static_header) / sizeof(static_header[0]));
+ if (header != NULL) {
+ header_count = http2_nv_copy(nva, header_count, (http2_header *)header->nva, header->num);
+ }
+
+ h2_data.header = (http2_header *)nva;
+ h2_data.header_count = header_count;
+ h2_data.data = NULL;
+ h2_data.len = 0;
+ h2_data.flag = 1 ;
+ h2_data.stream_id = 0;
+
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ http2_stream_node_insert(handle, h2_data.stream_id, info->user_data, &node);
+ HTTP2_STREAM_FREE(nva);
+ }
+
+ if (rv < 0) {
+ h2_err("client send error\n");
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+
+ if (node == NULL) {
+ h2_err("node insert failed!");
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+
+ node->stream_type = STREAM_TYPE_AUXILIARY;
+ HAL_MutexUnlock(handle->mutex);
+
+ rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
+ if (rv < 0 || memcmp(node->status_code, "200", 3)) {
+ h2_err("semaphore wait overtime or status code error\n");
+ HAL_MutexLock(handle->mutex);
+ http2_stream_node_remove(handle, node->stream_id);
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+ info->channel_id = HTTP2_STREAM_MALLOC(strlen(node->channel_id) + 1);
+ if (info->channel_id == NULL) {
+ h2_err("channel_id malloc failed\n");
+ HAL_MutexLock(handle->mutex);
+ http2_stream_node_remove(handle, node->stream_id);
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+ memset(info->channel_id, 0, strlen(node->channel_id) + 1);
+ strcpy(info->channel_id, node->channel_id);
+
+ return SUCCESS_RETURN;
+}
+
+int IOT_HTTP2_Stream_Send_Message(void *hd, const char *identify,char *channel_id, char *data, uint32_t data_len, header_ext_info_t *header)
+{
+ int rv = 0;
+ http2_data h2_data;
+ char path[128] = {0};
+ char data_len_str[33] = {0};
+ int windows_size;
+ int count = 0;
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ http2_header *nva = NULL;
+ int header_count, header_num;
+ char version[33] = {0};
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(identify, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(channel_id, NULL_VALUE_ERROR);
+
+ windows_size = iotx_http2_get_available_window_size(handle->http2_connect);
+ while (windows_size < data_len) {
+ h2_warning("windows_size < info->packet_len ,wait ...\n");
+ HAL_SleepMs(100);
+ if (++count > 50) {
+ return FAIL_RETURN;
+ }
+ windows_size = iotx_http2_get_available_window_size(handle->http2_connect);
+ }
+
+ HAL_Snprintf(data_len_str, sizeof(data_len_str), "%d", data_len);
+ HAL_Snprintf(path, sizeof(path), "/stream/send/%s", identify);
+ HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
+
+ {
+ const http2_header static_header[] = { MAKE_HEADER(":method", "POST"),
+ MAKE_HEADER_CS(":path", path),
+ MAKE_HEADER(":scheme", "https"),
+ MAKE_HEADER_CS("content-length", data_len_str),
+ MAKE_HEADER_CS("x-data-stream-id", channel_id),
+ MAKE_HEADER_CS("x-sdk-version", version),
+ MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
+ MAKE_HEADER("x-sdk-platform", "c"),
+ };
+
+ header_num = sizeof(static_header) / sizeof(static_header[0]);
+ if (header != NULL) {
+ header_num += header->num;
+ }
+ nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) * header_num);
+ if (nva == NULL) {
+ h2_err("nva malloc failed\n");
+ return FAIL_RETURN;
+ }
+
+ /* add external header if it's not NULL */
+ header_count = http2_nv_copy(nva, 0, (http2_header *)static_header, sizeof(static_header) / sizeof(static_header[0]));
+ if (header != NULL) {
+ header_count = http2_nv_copy(nva, header_count, (http2_header *)header->nva, header->num);
+ }
+ memset(&h2_data, 0, sizeof(h2_data));
+ h2_data.header = (http2_header *)nva;
+ h2_data.header_count = header_count;
+ h2_data.data = data;
+ h2_data.len = data_len;
+ h2_data.flag = 1;
+
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ HAL_MutexUnlock(handle->mutex);
+ HTTP2_STREAM_FREE(nva);
+ }
+
+ if (rv < 0) {
+ h2_err("send failed!");
+ return rv;
+ }
+
+ return h2_data.stream_id;
+}
+
+int IOT_HTTP2_Stream_Send(void *hd, stream_data_info_t *info, header_ext_info_t *header)
+{
+ int rv = 0;
+ http2_data h2_data;
+ char path[128] = {0};
+ char data_len_str[33] = {0};
+ int windows_size;
+ int count = 0;
+ http2_stream_node_t *node = NULL;
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ http2_header *nva = NULL;
+
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info->stream, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
+ ARGUMENT_SANITY_CHECK(info->stream_len != 0, FAIL_RETURN);
+ ARGUMENT_SANITY_CHECK(info->packet_len != 0, FAIL_RETURN);
+
+ windows_size = iotx_http2_get_available_window_size(handle->http2_connect);
+ while (windows_size < info->packet_len) {
+ h2_warning("windows_size < info->packet_len ,wait ...\n");
+ HAL_SleepMs(100);
+ if (++count > 50) {
+ return FAIL_RETURN;
+ }
+ windows_size = iotx_http2_get_available_window_size(handle->http2_connect);
+ }
+
+ HAL_Snprintf(data_len_str, sizeof(data_len_str), "%d", info->stream_len);
+ HAL_Snprintf(path, sizeof(path), "/stream/send/%s", info->identify);
+ if (info->send_len == 0) { /* first send,need header */
+ int header_count, header_num;
+ char version[33] = {0};
+ HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
+ {
+ const http2_header static_header[] = { MAKE_HEADER(":method", "POST"),
+ MAKE_HEADER_CS(":path", path),
+ MAKE_HEADER(":scheme", "https"),
+ MAKE_HEADER_CS("content-length", data_len_str),
+ MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
+ MAKE_HEADER_CS("x-sdk-version", version),
+ MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
+ MAKE_HEADER("x-sdk-platform", "c"),
+ };
+
+ header_num = sizeof(static_header) / sizeof(static_header[0]);
+ if (header != NULL) {
+ header_num += header->num;
+ }
+ nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) * header_num);
+ if (nva == NULL) {
+ h2_err("nva malloc failed\n");
+ return FAIL_RETURN;
+ }
+
+ /* add external header if it's not NULL */
+ header_count = http2_nv_copy(nva, 0, (http2_header *)static_header, sizeof(static_header) / sizeof(static_header[0]));
+ if (header != NULL) {
+ header_count = http2_nv_copy(nva, header_count, (http2_header *)header->nva, header->num);
+ }
+ memset(&h2_data, 0, sizeof(h2_data));
+ h2_data.header = (http2_header *)nva;
+ h2_data.header_count = header_count;
+ h2_data.data = info->stream;
+ h2_data.len = info->packet_len; /* TODO */
+
+ if (info->packet_len + info->send_len == info->stream_len) { /* last frame */
+ h2_data.flag = 1;
+ } else {
+ h2_data.flag = 0;
+ }
+
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ http2_stream_node_insert(handle, h2_data.stream_id, info->user_data, &node);
+ HTTP2_STREAM_FREE(nva);
+ }
+
+ if (rv < 0) {
+ h2_err("send failed!");
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+
+ if (node == NULL) {
+ h2_err("node insert failed!");
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+
+ node->stream_type = STREAM_TYPE_UPLOAD;
+ HAL_MutexUnlock(handle->mutex);
+
+ info->h2_stream_id = h2_data.stream_id;
+ info->send_len += info->packet_len;
+ } else {
+ h2_data.header = NULL;
+ h2_data.header_count = 0;
+ h2_data.data = info->stream;
+ h2_data.len = info->packet_len;
+
+ h2_data.stream_id = info->h2_stream_id;
+ if (info->packet_len + info->send_len == info->stream_len) { /* last frame */
+ h2_data.flag = 1;
+ } else {
+ h2_data.flag = 0;
+ }
+
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ HAL_MutexUnlock(handle->mutex);
+ if (rv < 0) {
+ return FAIL_RETURN;
+ }
+ info->send_len += info->packet_len;
+ }
+
+ if (h2_data.flag == 1) {
+ http2_stream_node_t *node = NULL;
+ HAL_MutexLock(handle->mutex);
+ http2_stream_node_search(handle, h2_data.stream_id, &node);
+ HAL_MutexUnlock(handle->mutex);
+ if (node == NULL) {
+ h2_err("node search failed!");
+ return FAIL_RETURN;
+ }
+ rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
+ if (rv < 0 || memcmp(node->status_code, "200", 3)) {
+ h2_err("semaphore wait overtime or status code error,h2_data.stream_id %d\n", h2_data.stream_id);
+ HAL_MutexLock(handle->mutex);
+ http2_stream_node_remove(handle, node->stream_id);
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+ }
+
+ return rv;
+}
+
+int IOT_HTTP2_Stream_Query(void *hd, stream_data_info_t *info, header_ext_info_t *header)
+{
+ int rv = 0;
+ http2_data h2_data;
+ http2_stream_node_t *node = NULL;
+ char path[128] = {0};
+ int header_count, header_num;
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ http2_header *nva = NULL;
+ char version[33] = {0};
+
+ POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
+ HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
+ HAL_Snprintf(path, sizeof(path), "/stream/send/%s", info->identify);
+ {
+ const http2_header static_header[] = { MAKE_HEADER(":method", "GET"),
+ MAKE_HEADER_CS(":path", path),
+ MAKE_HEADER(":scheme", "https"),
+ MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
+ MAKE_HEADER("x-test-downstream", "1"),
+ MAKE_HEADER_CS("x-sdk-version", version),
+ MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
+ MAKE_HEADER("x-sdk-platform", "c"),
+ };
+
+ header_num = sizeof(static_header) / sizeof(static_header[0]);
+ if (header != NULL) {
+ header_num += header->num;
+ }
+ nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) * header_num);
+ if (nva == NULL) {
+ h2_err("nva malloc failed\n");
+ return FAIL_RETURN;
+ }
+
+ /* add external header if it's not NULL */
+ header_count = http2_nv_copy(nva, 0, (http2_header *)static_header, sizeof(static_header) / sizeof(static_header[0]));
+ if (header != NULL) {
+ header_count = http2_nv_copy(nva, header_count, (http2_header *)header->nva, header->num);
+ }
+ h2_data.header = (http2_header *)nva;
+ h2_data.header_count = header_count;
+ h2_data.data = NULL;
+ h2_data.len = 0;
+ h2_data.flag = 1;
+ h2_data.stream_id = 0;
+
+ HAL_MutexLock(handle->mutex);
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ http2_stream_node_insert(handle, h2_data.stream_id, info->user_data, &node);
+ HTTP2_STREAM_FREE(nva);
+ }
+
+ if (rv < 0) {
+ h2_err("client send error\n");
+ HAL_MutexUnlock(handle->mutex);
+ return rv;
+ }
+
+ if (node == NULL) {
+ h2_err("node insert failed!");
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+
+ node->stream_type = STREAM_TYPE_DOWNLOAD;
+ HAL_MutexUnlock(handle->mutex);
+
+ rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
+ if (rv < 0 || memcmp(node->status_code, "200", 3)) {
+ h2_err("semaphore wait overtime or status code error\n");
+ HAL_MutexLock(handle->mutex);
+ http2_stream_node_remove(handle, node->stream_id);
+ HAL_MutexUnlock(handle->mutex);
+ return FAIL_RETURN;
+ }
+
+ return rv;
+}
+
+#ifdef FS_ENABLED
+int IOT_HTTP2_FS_Close(void *hd, stream_data_info_t *info, header_ext_info_t *header)
+{
+ int rv = 0;
+ http2_data h2_data;
+ char path[128] = {0};
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ char version[33] = {0};
+ char *stream_id = info->channel_id;
+ int len = strlen(stream_id);
+ http2_stream_node_t *node, *next;
+ http2_header *nva = NULL;
+ int header_count, header_num;
+
+ POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
+ HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
+ HAL_Snprintf(path, sizeof(path), "/stream/close/%s", info->identify);
+ {
+ const http2_header static_header[] = { MAKE_HEADER(":method", "POST"),
+ MAKE_HEADER_CS(":path", path),
+ MAKE_HEADER(":scheme", "https"),
+ MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
+ MAKE_HEADER_CS("x-sdk-version", version),
+ MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
+ MAKE_HEADER("x-sdk-platform", "c"),
+ };
+
+ header_num = sizeof(static_header) / sizeof(static_header[0]);
+ if (header != NULL) {
+ header_num += header->num;
+ }
+ nva = (http2_header *)HTTP2_STREAM_MALLOC(sizeof(http2_header) * header_num);
+ if (nva == NULL) {
+ h2_err("nva malloc failed\n");
+ HTTP2_STREAM_FREE(info->channel_id);
+ return FAIL_RETURN;
+ }
+
+ /* add external header if it's not NULL */
+ header_count = http2_nv_copy(nva, 0, (http2_header *)static_header, sizeof(static_header) / sizeof(static_header[0]));
+ if (header != NULL) {
+ header_count = http2_nv_copy(nva, header_count, (http2_header *)header->nva, header->num);
+ }
+
+ header_count = sizeof(static_header) / sizeof(static_header[0]);
+ h2_data.header = (http2_header *)static_header;
+ h2_data.header_count = header_count;
+ h2_data.data = NULL;
+ h2_data.len = 0;
+ h2_data.flag = 1;
+ h2_data.stream_id = 0;
+
+ HAL_MutexLock(handle->mutex);
+ if(info->send_len < info->stream_len) {
+ iotx_http2_reset_stream(handle->http2_connect,info->h2_stream_id);
+ }
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ http2_stream_node_insert(handle, h2_data.stream_id, info->user_data, &node);
+ HTTP2_STREAM_FREE(nva);
+ }
+
+ if (rv < 0) {
+ h2_err("client send error\n");
+ HAL_MutexUnlock(handle->mutex);
+ HTTP2_STREAM_FREE(info->channel_id);
+ return rv;
+ }
+
+ if (node == NULL) {
+ h2_err("node insert failed!");
+ HAL_MutexUnlock(handle->mutex);
+ HTTP2_STREAM_FREE(info->channel_id);
+ return FAIL_RETURN;
+ }
+
+ node->stream_type = STREAM_TYPE_AUXILIARY;
+ HAL_MutexUnlock(handle->mutex);
+
+ rv = HAL_SemaphoreWait(node->semaphore, IOT_HTTP2_RES_OVERTIME_MS);
+ if (rv < 0 || memcmp(node->status_code, "200", 3)) {
+ h2_err("semaphore wait overtime or status code error\n");
+ }
+
+ /* just delete stream node */
+ HAL_MutexLock(handle->mutex);
+ list_for_each_entry_safe(node, next, &handle->stream_list, list, http2_stream_node_t) {
+ if (info->h2_stream_id == node->stream_id) {
+ h2_info("stream_node found:stream_id= %d, Delete It", node->stream_id);
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node->channel_id);
+ HAL_SemaphoreDestroy(node->semaphore);
+ HTTP2_STREAM_FREE(node);
+ continue;
+ }
+ if ((node->channel_id != NULL) && (stream_id != NULL) &&
+ (len == strlen(node->channel_id) && !strncmp(node->channel_id, stream_id, len))) {
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node->channel_id);
+ HAL_SemaphoreDestroy(node->semaphore);
+ HTTP2_STREAM_FREE(node);
+ }
+ }
+ HTTP2_STREAM_FREE(info->channel_id);
+ info->channel_id = NULL;
+ HAL_MutexUnlock(handle->mutex);
+
+ return rv;
+}
+#endif /* #ifdef FS_ENABLED */
+
+int IOT_HTTP2_Stream_Close(void *hd, stream_data_info_t *info)
+{
+ int rv = 0;
+ http2_data h2_data;
+ char path[128] = {0};
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ char version[33] = {0};
+ char *stream_id = info->channel_id;
+ int len = strlen(stream_id);
+ http2_stream_node_t *node, *next;
+
+ POINTER_SANITY_CHECK(info, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ POINTER_SANITY_CHECK(info->channel_id, NULL_VALUE_ERROR);
+ HAL_Snprintf(version, sizeof(version), "%d", get_version_int());
+ HAL_Snprintf(path, sizeof(path), "/stream/close/%s", info->identify);
+ {
+ const http2_header static_header[] = { MAKE_HEADER(":method", "POST"),
+ MAKE_HEADER_CS(":path", path),
+ MAKE_HEADER(":scheme", "https"),
+ MAKE_HEADER_CS("x-data-stream-id", info->channel_id),
+ MAKE_HEADER_CS("x-sdk-version", version),
+ MAKE_HEADER_CS("x-sdk-version-name", IOTX_SDK_VERSION),
+ MAKE_HEADER("x-sdk-platform", "c"),
+ };
+
+ int header_count = sizeof(static_header) / sizeof(static_header[0]);
+ h2_data.header = (http2_header *)static_header;
+ h2_data.header_count = header_count;
+ h2_data.data = NULL;
+ h2_data.len = 0;
+ h2_data.flag = 1;
+ h2_data.stream_id = 0;
+
+ HAL_MutexLock(handle->mutex);
+ if(info->send_len < info->stream_len)
+ iotx_http2_reset_stream(handle->http2_connect,info->h2_stream_id);
+ rv = iotx_http2_client_send((void *)handle->http2_connect, &h2_data);
+ HAL_MutexUnlock(handle->mutex);
+ }
+
+ if (rv < 0) {
+ h2_warning("client send error\n");
+ }
+
+ /* just delete stream node */
+ HAL_MutexLock(handle->mutex);
+ list_for_each_entry_safe(node, next, &handle->stream_list, list, http2_stream_node_t) {
+ if (info->h2_stream_id == node->stream_id) {
+ h2_info("stream_node found:stream_id= %d, Delete It", node->stream_id);
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node->channel_id);
+ HAL_SemaphoreDestroy(node->semaphore);
+ HTTP2_STREAM_FREE(node);
+ continue;
+ }
+ if ((node->channel_id != NULL) && (stream_id != NULL) &&
+ (len == strlen(node->channel_id) && !strncmp(node->channel_id, stream_id, len))) {
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node->channel_id);
+ HAL_SemaphoreDestroy(node->semaphore);
+ HTTP2_STREAM_FREE(node);
+ }
+ }
+ HTTP2_STREAM_FREE(info->channel_id);
+ info->channel_id = NULL;
+ HAL_MutexUnlock(handle->mutex);
+ return rv;
+}
+
+int IOT_HTTP2_Disconnect(void *hd)
+{
+ int ret;
+ stream_handle_t *handle = (stream_handle_t *)hd;
+ http2_stream_node_t *node, *next;
+
+ POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR);
+ handle->init_state = 0;
+
+ ret = HAL_SemaphoreWait(handle->semaphore, PLATFORM_WAIT_INFINITE);
+ if (ret < 0) {
+ h2_err("semaphore wait err\n");
+ return FAIL_RETURN;
+ }
+
+ HAL_MutexLock(handle->mutex);
+ list_for_each_entry_safe(node, next, &handle->stream_list, list, http2_stream_node_t) {
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node->channel_id);
+ HAL_SemaphoreDestroy(node->semaphore);
+ HTTP2_STREAM_FREE(node);
+ }
+ HAL_MutexUnlock(handle->mutex);
+ g_stream_handle = NULL;
+
+ HAL_MutexDestroy(handle->mutex);
+ HAL_SemaphoreDestroy(handle->semaphore);
+
+ ret = iotx_http2_client_disconnect(handle->http2_connect);
+ HTTP2_STREAM_FREE(handle);
+ return ret;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_api.h
new file mode 100644
index 00000000..55fd4fee
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_api.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef IOT_EXPORT_HTTP2_STREAM_H
+#define IOT_EXPORT_HTTP2_STREAM_H
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IOT_HTTP2_RES_OVERTIME_MS (10000)
+#define IOT_HTTP2_KEEP_ALIVE_CNT (1)
+#define IOT_HTTP2_KEEP_ALIVE_TIME (30*1000) /* in seconds */
+
+#define MAKE_HEADER(NAME, VALUE) \
+ { \
+ (char *) NAME, (char *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 \
+ }
+
+#define MAKE_HEADER_CS(NAME, VALUE) \
+ { \
+ (char *) NAME, (char *)VALUE, strlen(NAME) , strlen(VALUE) \
+ }
+
+typedef struct {
+ char *product_key;
+ char *device_name;
+ char *device_secret;
+ char *url;
+ int port;
+} device_conn_info_t;
+
+typedef struct http2_header_struct {
+ char *name; /* header name */
+ char *value; /* the value of name */
+ int namelen; /* the length of header name */
+ int valuelen; /* the length of value */
+} http2_header;
+
+typedef struct {
+ http2_header *nva;
+ int num;
+} header_ext_info_t;
+
+typedef enum {
+ STREAM_TYPE_DOWNLOAD,
+ STREAM_TYPE_UPLOAD,
+ STREAM_TYPE_AUXILIARY,
+ STREAM_TYPE_NUM
+} stream_type_t;
+
+typedef void (*on_stream_header_callback)(uint32_t stream_id, char *channel_id, int cat, const uint8_t *name,
+ uint32_t namelen, const uint8_t *value, uint32_t valuelen, uint8_t flags, void *user_data);
+
+typedef void (*on_stream_chunk_recv_callback)(uint32_t stream_id, char *channel_id,
+ const uint8_t *data, uint32_t len, uint8_t flags, void *user_data);
+
+typedef void (*on_stream_close_callback)(uint32_t stream_id, char *channel_id, uint32_t error_code, void *user_data);
+
+typedef void (*on_stream_frame_send_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags, void *user_data);
+
+typedef void (*on_stream_frame_recv_callback)(uint32_t stream_id, char *channel_id, int type, uint8_t flags,void *user_data);
+
+typedef void (*on_reconnect_callback)();
+typedef void (*on_disconnect_callback)();
+
+typedef struct {
+ on_stream_header_callback on_stream_header_cb;
+ on_stream_chunk_recv_callback on_stream_chunk_recv_cb;
+ on_stream_close_callback on_stream_close_cb;
+ on_stream_frame_send_callback on_stream_frame_send_cb;
+ on_stream_frame_recv_callback on_stream_frame_recv_cb;
+ on_reconnect_callback on_reconnect_cb;
+ on_disconnect_callback on_disconnect_cb;
+} http2_stream_cb_t;
+
+typedef struct {
+ char *stream; /* point to stream data buffer */
+ uint32_t stream_len; /* file content length */
+ uint32_t send_len; /* data had sent length */
+ uint32_t packet_len; /* one packet length */
+ const char *identify; /* path string to identify a stream service */
+ int h2_stream_id; /* stream identifier which is a field in HTTP2 frame */
+ char *channel_id; /* string return by server to identify a specific stream channel,
+ different from stream identifier which is a field in HTTP2 frame */
+ void *user_data; /* user data brought in at stream open */
+} stream_data_info_t;
+
+DLL_IOT_API void *IOT_HTTP2_Connect(device_conn_info_t *conn_info, http2_stream_cb_t *user_cb);
+DLL_IOT_API int IOT_HTTP2_Stream_Open(void *handle, stream_data_info_t *info, header_ext_info_t *header);
+DLL_IOT_API int IOT_HTTP2_Stream_Send(void *handle, stream_data_info_t *info, header_ext_info_t *header);
+DLL_IOT_API int IOT_HTTP2_Stream_Query(void *handle, stream_data_info_t *info, header_ext_info_t *header);
+DLL_IOT_API int IOT_HTTP2_Stream_Close(void *handle, stream_data_info_t *info);
+DLL_IOT_API int IOT_HTTP2_Stream_Send_Message(void *handle, const char *identify,char *channel_id, char *data,
+ uint32_t data_len, header_ext_info_t *header);
+DLL_IOT_API int IOT_HTTP2_Disconnect(void *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOT_EXPORT_FILE_UPLOADER_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_config.h
new file mode 100644
index 00000000..d1bc5d38
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_config.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _HTTP2_CONFIG_H
+#define _HTTP2_CONFIG_H
+
+/* maximum packet len in one http2 frame */
+#ifndef FS_UPLOAD_PACKET_LEN
+#define FS_UPLOAD_PACKET_LEN 10240 /* must < 16384 */
+#endif
+
+/* maximum content len of the http2 request */
+#ifndef FS_UPLOAD_PART_LEN
+#define FS_UPLOAD_PART_LEN (1024 * 1024 * 4) /* 100KB ~ 100MB */
+#endif
+
+
+#endif /* #ifdef _HTTP2_CONFIG_H */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_internal.h
new file mode 100644
index 00000000..0b97aa38
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_internal.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef IOT_EXPORT_HTTP2_H
+#define IOT_EXPORT_HTTP2_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "http2_api.h"
+#include "http2_wrapper.h"
+
+#ifdef INFRA_LOG
+#include "infra_log.h"
+#define h2_emerg(...) log_emerg("h2", __VA_ARGS__)
+#define h2_crit(...) log_crit("h2", __VA_ARGS__)
+#define h2_err(...) log_err("h2", __VA_ARGS__)
+#define h2_warning(...) log_warning("h2", __VA_ARGS__)
+#define h2_info(...) log_info("h2", __VA_ARGS__)
+#define h2_debug(...) log_debug("h2", __VA_ARGS__)
+#else
+#define h2_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define h2_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define h2_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define h2_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define h2_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define h2_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#define HTTP2_STREAM_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "http2.stream")
+#define HTTP2_STREAM_FREE(ptr) LITE_free(ptr)
+#else
+#define HTTP2_STREAM_MALLOC(size) HAL_Malloc(size)
+#define HTTP2_STREAM_FREE(ptr) do{if(ptr != NULL) {HAL_Free(ptr);ptr = NULL;}}while(0)
+#endif /* #ifdef INFRA_MEM_STATS */
+
+#define POINTER_SANITY_CHECK(ptr, err) \
+ do { \
+ if (NULL == (ptr)) { \
+ return (err); \
+ } \
+ } while(0)
+
+#define ARGUMENT_SANITY_CHECK(expr, err) \
+ do { \
+ if (!(expr)) { \
+ return (err); \
+ } \
+ } while(0)
+
+
+typedef enum {
+
+ HTTP2_FLAG_NONE = 0,
+
+ HTTP2_FLAG_END_STREAM = 0x01,
+
+} http2_flag;
+
+typedef struct http2_list_s {
+ struct http2_list_s *prev;
+ struct http2_list_s *next;
+} http2_list_t;
+
+typedef void (*on_user_header_callback)(int32_t stream_id, int cat, const uint8_t *name, uint32_t namelen,
+ const uint8_t *value, uint32_t valuelen, uint8_t flags);
+
+typedef void (*on_user_chunk_recv_callback)(int32_t stream_id,
+ const uint8_t *data, uint32_t len, uint8_t flags);
+
+typedef void (*on_user_stream_close_callback)(int32_t stream_id, uint32_t error_code);
+
+typedef void (*on_user_frame_send_callback)(int32_t stream_id, int type, uint8_t flags);
+
+typedef void (*on_user_frame_recv_callback)(int32_t stream_id, int type, uint8_t flags);
+
+typedef struct {
+ on_user_header_callback on_user_header_cb;
+ on_user_chunk_recv_callback on_user_chunk_recv_cb;
+ on_user_stream_close_callback on_user_stream_close_cb;
+ on_user_frame_send_callback on_user_frame_send_cb;
+ on_user_frame_recv_callback on_user_frame_recv_cb;
+} http2_user_cb_t;
+
+typedef struct http2_connection {
+ void *network; /* iot network ptr */
+ void *session; /* http2 session */
+ int flag; /* check the stream is end or not */
+ int status;
+ http2_user_cb_t *cbs;
+} http2_connection_t;
+
+typedef struct http2_data_struct {
+ http2_header *header; /* header data. */
+ int header_count; /* the count of header data. */
+ char *data; /* send data. */
+ int len; /* send data length. */
+ int stream_id; /* send data over specify stream */
+ int flag; /* send data flag. */
+} http2_data;
+
+typedef struct {
+ http2_connection_t *http2_connect;
+ void *mutex;
+ void *semaphore;
+ void *rw_thread;
+ http2_list_t stream_list;
+ int init_state;
+ http2_stream_cb_t *cbs;
+ uint8_t connect_state;
+ uint8_t retry_cnt;
+} stream_handle_t;
+
+#ifdef FS_ENABLED
+
+typedef struct {
+ char fs_upload_id[50];
+ int fs_offset;
+} fs_rsp_header_val_t;
+
+int IOT_HTTP2_FS_Close(void *hd, stream_data_info_t *info, header_ext_info_t *header);
+
+#endif /* #ifdef FS_ENABLED */
+
+/**
+* @brief the http2 client connect.
+* @param[in] pclient: http client.
+* @return http2 client connection handler.
+*/
+extern http2_connection_t *iotx_http2_client_connect(void *pclient, char *url, int port);
+
+http2_connection_t *iotx_http2_client_connect_with_cb(void *pclient, char *url, int port, http2_user_cb_t *cb);
+/**
+* @brief the http2 client send data.
+* @param[in] handler: http2 client connection handler.
+* @param[in] data: send data.
+* @return The result. 0 is ok.
+*/
+extern int iotx_http2_client_send(http2_connection_t *conn, http2_data *h2_data);
+/**
+* @brief the http2 client receive data.
+* @param[in] handler: http2 client connection handler.
+* @param[in] data: receive data buffer.
+* @param[in] data_len: buffer length.
+* @param[in] len: receive data length.
+* @param[in] timeout: receive data timeout.
+* @return The result. 0 is ok.
+*/
+extern int iotx_http2_client_recv(http2_connection_t *conn, char *data, int data_len, int *len, int timeout);
+/**
+* @brief the http2 client connect.
+* @param[in] handler: http2 client connection handler.
+* @return The result. 0 is ok.
+*/
+extern int iotx_http2_client_disconnect(http2_connection_t *conn);
+/**
+* @brief the http2 client send ping to keep alive.
+* @param[in] handler: http2 client connection handler.
+* @return The result. 0 is ok.
+*/
+extern int iotx_http2_client_send_ping(http2_connection_t *conn);
+/**
+* @brief the http2 client get available windows size.
+* @param[in] handler: http2 client connection handler.
+* @return The window size.
+*/
+extern int iotx_http2_get_available_window_size(http2_connection_t *conn);
+/**
+* @brief the http2 client receive windows size packet to update window.
+* @param[in] handler: http2 client connection handler.
+* @return The result. 0 is ok.
+*/
+extern int iotx_http2_update_window_size(http2_connection_t *conn);
+/**
+* @brief the http2 client performs the network I/O.
+* @param[in] handler: http2 client connection handler.
+* @return The result. 0 is ok.
+*/
+extern int iotx_http2_exec_io(http2_connection_t *connection);
+
+extern int iotx_http2_client_recv_ping(void);
+
+int iotx_http2_reset_stream(http2_connection_t *connection, int32_t stream_id);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IOT_EXPORT_HTTP2_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_upload_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_upload_api.c
new file mode 100644
index 00000000..0f9f2067
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_upload_api.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "infra_config.h"
+#ifdef FS_ENABLED
+
+#include
+#include
+#include
+#include
+
+#include "infra_defs.h"
+#include "infra_types.h"
+#include "infra_httpc.h"
+#include "infra_sha1.h"
+#include "infra_timer.h"
+#include "infra_list.h"
+#include "infra_log.h"
+
+#include "http2_internal.h"
+#include "http2_api.h"
+#include "http2_upload_api.h"
+#include "http2_config.h"
+#include "http2_wrapper.h"
+
+#include "wrappers_defs.h"
+
+#define PACKET_LEN 16384
+#define HTTP2_FS_SERVICE_ID "c/iot/sys/thing/file/upload"
+
+
+typedef enum {
+ FS_STATUS_WAITING,
+ FS_STATUS_UPLOADING,
+ FS_STATUS_BREAK,
+ FS_STATUS_END,
+ FS_STATUS_NUM
+} file_stream_status_t;
+
+typedef enum {
+ FS_TYPE_NORMAL,
+ FS_TYPE_CONTINUE,
+ FS_TYPE_OVERRIDE,
+} file_stream_type_t;
+
+typedef struct {
+ int idx;
+ const char *file_path;
+ char upload_id[40];
+ uint32_t spec_len;
+ uint32_t file_offset;
+ uint32_t part_len;
+ file_stream_type_t type;
+ http2_upload_id_received_cb_t opened_cb;
+ http2_upload_completed_cb_t end_cb;
+ void *user_data;
+
+ uint8_t if_stop;
+
+ http2_list_t list;
+} http2_file_stream_t;
+
+typedef struct {
+ stream_handle_t *http2_handle;
+ const char *service_id;
+ http2_list_t file_list;
+ void *list_mutex;
+ void *file_thread;
+ int upload_idx;
+} http2_file_stream_ctx_t;
+
+
+typedef struct {
+ char *send_buffer;
+ const char *upload_id;
+ uint32_t file_offset;
+ uint32_t part_len;
+} fs_send_ext_info_t;
+
+
+static http2_file_stream_ctx_t g_http2_fs_ctx = { 0 };
+static http2_stream_cb_t callback_func = { 0 };
+
+
+/* utils, get file sizef */
+static int http2_stream_get_file_size(const char *file_name)
+{
+ void *fp = NULL;
+ int size = 0;
+ if ((fp = HAL_Fopen(file_name, "r")) == NULL) {
+ h2_err("The file %s can not be opened.\n", file_name);
+ return -1;
+ }
+ HAL_Fseek(fp, 0L, HAL_SEEK_END);
+ size = HAL_Ftell(fp);
+ HAL_Fclose(fp);
+ return size;
+}
+
+/* utils, get file name */
+static const char *_http2_fs_get_filename(const char *file_path)
+{
+ const char *p_name = NULL;
+
+ if (file_path == NULL) {
+ return NULL;
+ }
+
+ p_name = file_path + strlen(file_path);
+
+ while (--p_name != file_path) {
+ if (*p_name == '/') {
+ p_name++;
+ break;
+ }
+ }
+
+ return p_name;
+}
+
+/* utils, read file data */
+static int http2_stream_get_file_data(const char *file_name, char *data, int len, int offset)
+{
+ void *fp = NULL;
+ int ret = 0;
+ if ((fp = HAL_Fopen(file_name, "r")) == NULL) {
+ h2_err("The file %s can not be opened.\n", file_name);
+ return -1;
+ }
+ ret = HAL_Fseek(fp, offset, HAL_SEEK_SET);
+ if (ret != 0) {
+ HAL_Fclose(fp);
+ h2_err("The file %s can not move offset.\n", file_name);
+ return -1;
+ }
+ ret = HAL_Fread(data, len, 1, fp);
+ HAL_Fclose(fp);
+ return len;
+}
+
+/* open http2 file upload channel */
+static int _http2_fs_open_channel(http2_file_stream_t *fs_node, stream_data_info_t *info)
+{
+ stream_handle_t *h2_handle = g_http2_fs_ctx.http2_handle;
+ header_ext_info_t ext_header;
+ fs_rsp_header_val_t *open_rsp = (fs_rsp_header_val_t *)info->user_data;
+ const char *filename = NULL;
+ int ret = UPLOAD_ERROR_COMMON;
+
+ /* header for normal upload */
+ http2_header header_filename[] = {
+ MAKE_HEADER_CS("x-file-name", ""),
+ };
+
+ /* header for override operation */
+ http2_header header_overwrite[] = {
+ MAKE_HEADER_CS("x-file-name", ""),
+ MAKE_HEADER_CS("x-file-overwrite", "1"),
+ };
+
+ /* header for continue operation */
+ http2_header header_uploadid[] = {
+ MAKE_HEADER("x-file-upload-id", ""),
+ };
+
+ filename = _http2_fs_get_filename(fs_node->file_path);
+ h2_info("filename = %s", filename);
+
+ header_filename[0].value = (char *)filename;
+ header_filename[0].valuelen = strlen(filename);
+ header_overwrite[0].value = (char *)filename;
+ header_overwrite[0].valuelen = strlen(filename);
+
+ /* setup http2 ext_header */
+ switch (fs_node->type) {
+ case FS_TYPE_NORMAL: {
+ ext_header.num = 1;
+ ext_header.nva = header_filename;
+
+ } break;
+ case FS_TYPE_OVERRIDE: {
+ ext_header.num = 2;
+ ext_header.nva = header_overwrite;
+
+ } break;
+ case FS_TYPE_CONTINUE: {
+ /* upload id must be exist */
+ header_uploadid[0].value = fs_node->upload_id;
+ header_uploadid[0].valuelen = strlen(fs_node->upload_id);
+ ext_header.num = 1;
+ ext_header.nva = header_uploadid;
+ } break;
+ default: break;
+ }
+
+ ret = IOT_HTTP2_Stream_Open(h2_handle, info, &ext_header);
+ if (ret < 0 || open_rsp->fs_offset == -1 || open_rsp->fs_upload_id[0] == '\0') {
+ h2_err("IOT_HTTP2_Stream_Open failed %d\n", ret);
+ return UPLOAD_STREAM_OPEN_FAILED;
+ }
+ h2_info("fs channel open succeed");
+ return SUCCESS_RETURN;
+}
+
+
+/* file part data send sync api */
+static int _http2_fs_part_send_sync(http2_file_stream_t *fs_node, stream_data_info_t *info, fs_send_ext_info_t *ext_info)
+{
+ stream_handle_t *h2_handle = g_http2_fs_ctx.http2_handle;
+ header_ext_info_t ext_header;
+ int res;
+ http2_header header_uploadid[] = {
+ MAKE_HEADER_CS("x-file-upload-id", ext_info->upload_id),
+ };
+
+ /* setup ext header */
+ ext_header.num = 1;
+ ext_header.nva = header_uploadid;
+
+ /* setup Stream_Send params */
+ info->stream = ext_info->send_buffer;
+ info->stream_len = ext_info->part_len;
+ info->send_len = 0;
+ info->packet_len = FS_UPLOAD_PACKET_LEN;
+
+ while (info->send_len < info->stream_len) {
+ if (!h2_handle->init_state) {
+ res = UPLOAD_ERROR_COMMON;
+ break;
+ }
+
+ res = http2_stream_get_file_data(fs_node->file_path, ext_info->send_buffer, FS_UPLOAD_PACKET_LEN, (info->send_len + ext_info->file_offset)); /* offset used */
+ if (res <= 0) {
+ res = UPLOAD_FILE_READ_FAILED;
+ break;
+ }
+ info->packet_len = res;
+
+ /* adjust the packet len */
+ if (info->stream_len - info->send_len < info->packet_len) {
+ info->packet_len = info->stream_len - info->send_len;
+ }
+
+ res = IOT_HTTP2_Stream_Send(h2_handle, info, &ext_header);
+ if (res < 0) {
+ res = UPLOAD_STREAM_SEND_FAILED;
+ break;
+ }
+ h2_debug("send len = %d\n", info->send_len);
+
+ if (fs_node->if_stop) {
+ res = UPLOAD_STOP_BY_IOCTL;
+ break;
+ }
+
+ res = SUCCESS_RETURN;
+ }
+
+ return res;
+}
+
+void *_http2_fs_node_handle(http2_file_stream_t *fs_node)
+{
+ stream_handle_t *h2_handle = g_http2_fs_ctx.http2_handle;
+ int filesize = 0;
+ int upload_len = 0;
+ fs_rsp_header_val_t rsp_data;
+ fs_send_ext_info_t send_ext_info;
+ stream_data_info_t channel_info;
+ uint32_t part_len = 0;
+ int res = FAIL_RETURN;
+
+ /* params check */
+ if (h2_handle == NULL) {
+ /* TODO: handle */
+ return NULL;
+ }
+
+ /* get fileszie */
+ filesize = http2_stream_get_file_size(fs_node->file_path);
+ if (filesize <= 0) {
+ if (fs_node->end_cb) {
+ fs_node->end_cb(fs_node->file_path, UPLOAD_FILE_NOT_EXIST, fs_node->user_data);
+ }
+
+ return NULL;
+ }
+ h2_info("filesize = %d", filesize);
+
+ /* open http2 file upload channel */
+ memset(&rsp_data, 0, sizeof(fs_rsp_header_val_t));
+ memset(&channel_info, 0, sizeof(stream_data_info_t));
+ channel_info.identify = g_http2_fs_ctx.service_id;
+ channel_info.user_data = (void *)&rsp_data;
+
+ res = _http2_fs_open_channel(fs_node, &channel_info);
+ if (res < SUCCESS_RETURN) {
+ if (fs_node->end_cb) {
+ fs_node->end_cb(fs_node->file_path, res, fs_node->user_data);
+ }
+
+ return NULL;
+ }
+
+ h2_info("upload_id = %s", rsp_data.fs_upload_id);
+ h2_info("upload_offset = %d", rsp_data.fs_offset);
+ if (fs_node->opened_cb) {
+ fs_node->opened_cb(fs_node->file_path, rsp_data.fs_upload_id, fs_node->user_data);
+ }
+
+ if (fs_node->spec_len && (fs_node->spec_len + rsp_data.fs_offset < filesize)) {
+ upload_len = fs_node->spec_len + rsp_data.fs_offset;
+ }
+ else {
+ upload_len = filesize;
+ }
+
+ /* setup send part len */
+ if ((fs_node->part_len < (1024 * 100)) || (fs_node->part_len > (1024 * 1024 * 100))) {
+ part_len = FS_UPLOAD_PART_LEN;
+ }
+ else {
+ part_len = fs_node->part_len;
+ }
+
+ /* send http2 file upload data */
+ send_ext_info.upload_id = rsp_data.fs_upload_id;
+ send_ext_info.file_offset = rsp_data.fs_offset;
+ send_ext_info.send_buffer = HTTP2_STREAM_MALLOC(FS_UPLOAD_PACKET_LEN);
+ if (send_ext_info.send_buffer == NULL) {
+ if (fs_node->end_cb) {
+ fs_node->end_cb(fs_node->file_path, UPLOAD_MALLOC_FAILED, fs_node->user_data);
+ }
+
+ return NULL;
+ }
+
+ do {
+ /* setup the part len */
+ send_ext_info.part_len = ((upload_len - send_ext_info.file_offset) < part_len)?
+ (upload_len - send_ext_info.file_offset): part_len;
+
+ res = _http2_fs_part_send_sync(fs_node, &channel_info, &send_ext_info);
+ if (res < SUCCESS_RETURN) {
+ h2_err("fs send return %d", res);
+ break;
+ }
+
+ send_ext_info.file_offset += send_ext_info.part_len;
+ h2_info("file offset = %d now", send_ext_info.file_offset);
+ } while (send_ext_info.file_offset < upload_len);
+
+ if (res < 0) {
+ if (fs_node->end_cb) {
+ fs_node->end_cb(fs_node->file_path, res, fs_node->user_data);
+ }
+
+ HTTP2_STREAM_FREE(channel_info.channel_id);
+ HTTP2_STREAM_FREE(send_ext_info.send_buffer);
+ return NULL;
+ }
+
+ /* close http2 file upload channel */
+ IOT_HTTP2_FS_Close(h2_handle, &channel_info, NULL);
+
+ if (fs_node->end_cb) {
+ fs_node->end_cb(fs_node->file_path, UPLOAD_SUCCESS, fs_node->user_data);
+ }
+
+ HTTP2_STREAM_FREE(send_ext_info.send_buffer);
+ return NULL;
+}
+
+static void *http_upload_file_func(void *fs_data)
+{
+ http2_file_stream_ctx_t *fs_ctx = (http2_file_stream_ctx_t *)fs_data;
+ http2_file_stream_t *node = NULL;
+ if (fs_ctx == NULL) {
+ return NULL;
+ }
+
+ while (fs_ctx->http2_handle->init_state) {
+ HAL_MutexLock(fs_ctx->list_mutex);
+ if (!list_empty((list_head_t *)&g_http2_fs_ctx.file_list)) {
+ node = list_first_entry(&fs_ctx->file_list, http2_file_stream_t, list);
+ HAL_MutexUnlock(fs_ctx->list_mutex);
+
+ /* execute upload routine */
+ _http2_fs_node_handle((void *)node);
+
+ /* delete the completed node */
+ HAL_MutexLock(fs_ctx->list_mutex);
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node);
+ HAL_MutexUnlock(fs_ctx->list_mutex);
+ }
+ else {
+ HAL_MutexUnlock(fs_ctx->list_mutex);
+ h2_debug("file list is empty, file upload thread exit\n");
+ g_http2_fs_ctx.file_thread = NULL;
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static void _http2_fs_list_insert(http2_file_stream_ctx_t *fs_ctx, http2_file_stream_t *node)
+{
+ INIT_LIST_HEAD((list_head_t *)&node->list);
+ HAL_MutexLock(fs_ctx->list_mutex);
+ list_add_tail((list_head_t *)&node->list, (list_head_t *)&fs_ctx->file_list);
+ HAL_MutexUnlock(fs_ctx->list_mutex);
+}
+
+typedef enum {
+ HTTP2_IOCTL_STOP_UPLOAD,
+ HTTP2_IOCTL_COMMAND_NUM,
+} http2_file_upload_ioctl_command_t;
+
+static int _http2_fs_list_search_by_idx(int idx, http2_file_stream_t **search_node)
+{
+ http2_file_stream_t *node = NULL;
+
+ HAL_MutexLock(g_http2_fs_ctx.list_mutex);
+
+ list_for_each_entry(node, &g_http2_fs_ctx.file_list, list, http2_file_stream_t) {
+ if (idx == node->idx) {
+ *search_node = node;
+ HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
+ *search_node = NULL;
+ return FAIL_RETURN;
+}
+
+int IOT_HTTP2_Ioctl(int upload_idx, int command, void *data)
+{
+ http2_file_stream_t *node = NULL;
+
+ if (g_http2_fs_ctx.http2_handle == NULL) {
+ return UPLOAD_ERROR_COMMON;
+ }
+
+ _http2_fs_list_search_by_idx(upload_idx, &node);
+ if (node == NULL) {
+ return UPLOAD_ERROR_COMMON;
+ }
+
+ switch (command) {
+ case HTTP2_IOCTL_STOP_UPLOAD: {
+ if (g_http2_fs_ctx.http2_handle) {
+ HAL_MutexLock(g_http2_fs_ctx.list_mutex);
+ node->if_stop = 1;
+ HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
+ return SUCCESS_RETURN;
+ }
+ else {
+ return UPLOAD_ERROR_COMMON;
+ }
+ } break;
+ default: {
+ return UPLOAD_ERROR_COMMON;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+void *IOT_HTTP2_UploadFile_Connect(http2_upload_conn_info_t *conn_info, http2_status_cb_t *cb)
+{
+ void *handle;
+
+ memset(&callback_func, 0, sizeof(http2_stream_cb_t));
+
+ if (cb != NULL) {
+ callback_func.on_reconnect_cb = cb->on_reconnect_cb;
+ callback_func.on_disconnect_cb = cb->on_disconnect_cb;
+ }
+
+ handle = IOT_HTTP2_Connect((device_conn_info_t *)conn_info, &callback_func);
+ if (handle == NULL) {
+ return handle;
+ }
+
+ /* TODO */
+ g_http2_fs_ctx.list_mutex = HAL_MutexCreate();
+ if (g_http2_fs_ctx.list_mutex == NULL) {
+ h2_err("fs mutex create error\n");
+ IOT_HTTP2_UploadFile_Disconnect(handle);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD((list_head_t *)&(g_http2_fs_ctx.file_list));
+ g_http2_fs_ctx.http2_handle = handle;
+ g_http2_fs_ctx.service_id = HTTP2_FS_SERVICE_ID;
+
+ return handle;
+}
+
+int IOT_HTTP2_UploadFile_Request(void *http2_handle, http2_upload_params_t *params, http2_upload_result_cb_t *cb, void *user_data)
+{
+ int ret;
+ http2_file_stream_t *file_node = NULL;
+
+ if (http2_handle == NULL || params == NULL || cb == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (params->file_path == NULL) {
+ return UPLOAD_FILE_PATH_IS_NULL;
+ }
+
+ if ( (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_RESUME) && params->upload_id == NULL) {
+ return UPLOAD_ID_IS_NULL;
+ }
+
+ if ( (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN) && params->upload_len == 0) {
+ return UPLOAD_LEN_IS_ZERO;
+ }
+
+ file_node = (http2_file_stream_t *)HTTP2_STREAM_MALLOC(sizeof(http2_file_stream_t));
+ if (file_node == NULL) {
+ return UPLOAD_MALLOC_FAILED;
+ }
+
+ memset(file_node, 0, sizeof(http2_file_stream_t));
+ file_node->file_path = params->file_path;
+ file_node->part_len = params->part_len;
+ file_node->opened_cb = cb->upload_id_received_cb;
+ file_node->end_cb = cb->upload_completed_cb;
+ file_node->user_data = user_data;
+ file_node->type = FS_TYPE_NORMAL;
+ file_node->idx = g_http2_fs_ctx.upload_idx++;
+
+ if (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN) {
+ file_node->spec_len = params->upload_len;
+ }
+ if (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_OVERWRITE) {
+ file_node->type = FS_TYPE_OVERRIDE;
+ }
+ else if (params->opt_bit_map & UPLOAD_FILE_OPT_BIT_RESUME) {
+ file_node->type = FS_TYPE_CONTINUE;
+ memcpy(file_node->upload_id, params->upload_id, sizeof(file_node->upload_id));
+ }
+
+ /* inset http2_fs node */
+ _http2_fs_list_insert(&g_http2_fs_ctx, file_node);
+
+ if (g_http2_fs_ctx.file_thread == NULL) {
+ hal_os_thread_param_t thread_parms = {0};
+ thread_parms.stack_size = 6144;
+ thread_parms.name = "file_upload";
+ ret = HAL_ThreadCreate(&g_http2_fs_ctx.file_thread, http_upload_file_func, (void *)&g_http2_fs_ctx, &thread_parms, NULL);
+ if (ret != 0) {
+ h2_err("file upload thread create error\n");
+ return -1;
+ }
+ HAL_ThreadDetach(g_http2_fs_ctx.file_thread);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int IOT_HTTP2_UploadFile_Disconnect(void *handle)
+{
+ int res = FAIL_RETURN;
+
+ res = IOT_HTTP2_Disconnect(handle);
+
+ if (g_http2_fs_ctx.list_mutex == NULL) {
+ memset(&g_http2_fs_ctx, 0, sizeof(g_http2_fs_ctx));
+ }
+ else {
+ http2_file_stream_t *node, *next;
+ HAL_MutexLock(g_http2_fs_ctx.list_mutex);
+ list_for_each_entry_safe(node, next, &g_http2_fs_ctx.file_list, list, http2_file_stream_t) {
+ list_del((list_head_t *)&node->list);
+ HTTP2_STREAM_FREE(node);
+ break;
+ }
+ HAL_MutexUnlock(g_http2_fs_ctx.list_mutex);
+
+ HAL_MutexDestroy(g_http2_fs_ctx.list_mutex);
+ memset(&g_http2_fs_ctx, 0, sizeof(g_http2_fs_ctx));
+ }
+
+ return res;
+}
+
+#endif /* #ifdef FS_ENABLED */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_upload_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_upload_api.h
new file mode 100644
index 00000000..af554448
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_upload_api.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _HTTP2_UPLOAD_API_H_
+#define _HTTP2_UPLOAD_API_H_
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* bit define of file override option */
+#define UPLOAD_FILE_OPT_BIT_OVERWRITE (0x00000001)
+#define UPLOAD_FILE_OPT_BIT_RESUME (0x00000002)
+#define UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN (0x00000004)
+
+/* http2 connect information */
+typedef struct {
+ char *product_key;
+ char *device_name;
+ char *device_secret;
+ char *url;
+ int port;
+} http2_upload_conn_info_t;
+
+/* file upload option define */
+typedef struct {
+ const char *file_path; /* file path, filename must be ASCII string and strlen < 2014 */
+ uint32_t part_len; /* maximum content len of one http2 request, must be in range of 100KB ~ 100MB */
+ const char *upload_id; /* a specific id used to indicate one upload session, only required when UPLOAD_FILE_OPT_BIT_RESUME option set */
+ uint32_t upload_len; /* used to indicate the upload length, only required when UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN option set */
+ uint32_t opt_bit_map; /* option bit map, support UPLOAD_FILE_OPT_BIT_OVERWRITE, UPLOAD_FILE_OPT_BIT_RESUME and UPLOAD_FILE_OPT_BIT_SPECIFIC_LEN */
+} http2_upload_params_t;
+
+/* error code for file upload */
+typedef enum {
+ UPLOAD_STOP_BY_IOCTL = -14,
+ UPLOAD_HTTP2_HANDLE_NULL = -13,
+ UPLOAD_LEN_IS_ZERO = -12,
+ UPLOAD_FILE_PATH_IS_NULL = -11,
+ UPLOAD_ID_IS_NULL = -10,
+ UPLOAD_FILE_NOT_EXIST = -9,
+ UPLOAD_FILE_READ_FAILED = -8,
+ UPLOAD_STREAM_OPEN_FAILED = -7,
+ UPLOAD_STREAM_SEND_FAILED = -6,
+ UPLOAD_MALLOC_FAILED = -5,
+ UPLOAD_NULL_POINT = -2,
+ UPLOAD_ERROR_COMMON = -1,
+ UPLOAD_SUCCESS = 0,
+} http2_file_upload_result_t;
+
+/* gerneral callback function, this callback will be invoke when http2 disconnected */
+typedef void (*http2_disconnect_cb_t)(void);
+
+/* gerneral callback function, this callback will be invoke when http2 reconnected */
+typedef void (*http2_reconnect_cb_t)(void);
+
+/* callback function type define, this callback will be invoke when upload completed */
+typedef void (*http2_upload_completed_cb_t)(const char *file_path, int result, void *user_data);
+
+/* callback funciton type define, this callback will be invoke when upload_id received */
+typedef void (*http2_upload_id_received_cb_t)(const char *file_path, const char *upload_id, void *user_data);
+
+/* http2 connect status callback define */
+typedef struct {
+ http2_disconnect_cb_t on_disconnect_cb;
+ http2_reconnect_cb_t on_reconnect_cb;
+} http2_status_cb_t;
+
+/* http2 upload result callback define */
+typedef struct {
+ http2_upload_id_received_cb_t upload_id_received_cb;
+ http2_upload_completed_cb_t upload_completed_cb;
+} http2_upload_result_cb_t;
+
+/* http2 uploadfile connect api, http2 handle returned */
+DLL_IOT_API void *IOT_HTTP2_UploadFile_Connect(http2_upload_conn_info_t *conn_info, http2_status_cb_t *cb);
+
+/* http2 uploadfile start api */
+DLL_IOT_API int IOT_HTTP2_UploadFile_Request(void *http2_handle, http2_upload_params_t *params, http2_upload_result_cb_t *cb, void *user_data);
+
+/* http2 uploadfile disconnect api */
+DLL_IOT_API int IOT_HTTP2_UploadFile_Disconnect(void *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef _HTTP2_UPLOAD_API_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_wrapper.h
new file mode 100644
index 00000000..454401b2
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/http2_wrapper.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __HTTP2_WRAPPER_H__
+#define __HTTP2_WRAPPER_H__
+
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+
+extern void HAL_Printf(const char *fmt, ...);
+extern void HAL_SleepMs(uint32_t ms);
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+extern void *HAL_MutexCreate(void);
+extern void HAL_MutexDestroy(void *mutex);
+extern void HAL_MutexLock(void *mutex);
+extern void HAL_MutexUnlock(void *mutex);
+
+extern void *HAL_SemaphoreCreate(void);
+extern void HAL_SemaphoreDestroy(void *sem);
+extern void HAL_SemaphorePost(void *sem);
+extern int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
+
+extern int HAL_ThreadCreate(
+ void **thread_handle,
+ void *(*work_routine)(void *),
+ void *arg,
+ hal_os_thread_param_t *hal_os_thread_param,
+ int *stack_used);
+extern void HAL_ThreadDetach(void *thread_handle);
+extern void HAL_ThreadDelete(void *thread_handle);
+
+#ifdef FS_ENABLED
+typedef enum {
+ HAL_SEEK_SET,
+ HAL_SEEK_CUR,
+ HAL_SEEK_END
+} hal_fs_seek_type_t;
+
+extern void *HAL_Fopen(const char *path, const char *mode);
+extern uint32_t HAL_Fread(void *buff, uint32_t size, uint32_t count, void *stream);
+extern uint32_t HAL_Fwrite(const void *ptr, uint32_t size, uint32_t count, void *stream);
+extern int HAL_Fseek(void *stream, long offset, int framewhere);
+extern int HAL_Fclose(void *stream);
+extern long HAL_Ftell(void *stream);
+#endif /* #ifdef FS_ENABLED */
+
+#endif /* #ifndef __HTTP2_WRAPPER_H__ */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/iotx_http2.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/iotx_http2.c
new file mode 100644
index 00000000..e3fdef3b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/http2/iotx_http2.c
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+#include
+
+#include "nghttp2.h"
+#include "nghttp2_session.h"
+#include "infra_httpc.h"
+#include "http2_internal.h"
+#include "http2_wrapper.h"
+
+
+#define MAX_HTTP2_HOST_LEN (128)
+#define NGHTTP2_DBG h2_info
+
+typedef enum {
+ PING_IDLE,
+ PING_SENDING,
+ PING_SENT,
+ PING_RECVED,
+} http2_ping_state_t;
+
+
+enum { IO_NONE, WANT_READ, WANT_WRITE };
+
+typedef struct _http2_request_struct_ {
+ /* Stream ID for this request. */
+ int32_t stream_id;
+} http2_request;
+
+
+extern const char *iotx_ca_get(void);
+extern int httpclient_connect(httpclient_t *client);
+static int http2_nv_copy_nghttp2_nv(nghttp2_nv *nva, int start, http2_header *nva_copy, int end);
+/*static int http2_parse_host(char *url, char *host, size_t maxHostLen);*/
+
+static http2_ping_state_t ping_state = PING_IDLE;
+
+int g_recv_timeout = 10;
+
+int set_http2_recv_timeout(int timeout)
+{
+ g_recv_timeout = timeout;
+ return 1;
+}
+
+static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
+ size_t length, int flags, void *user_data)
+{
+ http2_connection_t *connection;
+ httpclient_t *client;
+ int rv;
+
+ connection = (http2_connection_t *)user_data;
+ if (connection == NULL) {
+ return 0;
+ }
+
+ NGHTTP2_DBG("send_callback data len %d, session->remote_window_size=%d!\r\n", (int)length,
+ session->remote_window_size);
+ if (session->remote_window_size < length * 2) {
+ HAL_SleepMs(50);
+ NGHTTP2_DBG("wait a munite ....");
+ }
+ /*if(length < 50)
+ LITE_hexdump("data:", data, length);*/
+ client = (httpclient_t *)connection->network;
+ rv = client->net.write(&client->net, (char *)data, length, 5000);
+ NGHTTP2_DBG("send_callback data ends len = %d!\r\n", rv);
+ if (rv < 0) {
+ rv = NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return rv;
+}
+
+
+/**
+* @brief The implementation of nghttp2_recv_callback type. Here we read |data| from the network
+* and write them in |buf|. The capacity of |buf| is |length| bytes. Returns the number of
+* bytes stored in |buf|. See the documentation of nghttp2_recv_callback for the details.
+* To set this callback to :type:`nghttp2_session_callbacks`, use
+* `nghttp2_session_callbacks_set_on_frame_send_callback()`.
+* @param[in] session: nghttp2 session.
+* @param[in] buf: receive data buffer.
+* @param[in] length: data length.
+* @param[in] flags: no using.
+* @param[in] user_data: user data.
+* @return Received data length.
+ */
+static ssize_t recv_callback(nghttp2_session *session, uint8_t *buf,
+ size_t length, int flags, void *user_data)
+{
+ http2_connection_t *connection;
+ int rv;
+ httpclient_t *client;
+
+ connection = (http2_connection_t *)user_data;
+ if (connection == NULL) {
+ return 0;
+ }
+
+ client = (httpclient_t *)connection->network;
+
+ rv = client->net.read(&client->net, (char *)buf, length, g_recv_timeout);
+ /* NGHTTP2_DBG("recv_callback len= %d\r\n", rv); */
+ if (rv < 0) {
+ rv = NGHTTP2_ERR_CALLBACK_FAILURE;
+ } else if (rv == 0) {
+ rv = 0;
+ }
+ return rv;
+}
+/**
+* @brief Callback function invoked after the frame |frame| is sent.
+* To set this callback to :type:`nghttp2_session_callbacks`, use
+* `nghttp2_session_callbacks_set_on_frame_send_callback()`.
+* @param[in] session: nghttp2 session.
+* @param[in] frame: nghttp2 frame.
+* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
+* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
+* @return The implementation of this function must return 0 if it succeeds.
+* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
+* and `nghttp2_session_mem_send()` functions immediately return :enum:
+* `NGHTTP2_ERR_CALLBACK_FAILURE`.
+*/
+static int on_frame_send_callback(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data)
+{
+ size_t i;
+
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+ if (connection == NULL) {
+ return 0;
+ }
+
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS: {
+ const nghttp2_nv *nva = frame->headers.nva;
+ NGHTTP2_DBG("[INFO] C ---------> S (HEADERS) stream_id [%d]\n", frame->hd.stream_id);
+ for (i = 0; i < frame->headers.nvlen; ++i) {
+ NGHTTP2_DBG("> %s: %s\n", nva[i].name, nva[i].value);
+ }
+ (void)nva;
+ } break;
+ case NGHTTP2_RST_STREAM: {
+ NGHTTP2_DBG("[INFO] C ---------> S (RST_STREAM)\n");
+ } break;
+ case NGHTTP2_GOAWAY: {
+ NGHTTP2_DBG("[INFO] C ---------> S (GOAWAY) code = %d\n",frame->goaway.error_code);
+ } break;
+ case NGHTTP2_PING: {
+ NGHTTP2_DBG("[INFO] C ---------> S (PING)\n");
+ ping_state = PING_SENDING;
+ } break;
+ default: break;
+ }
+
+ if (connection->cbs && connection->cbs->on_user_frame_send_cb) {
+ connection->cbs->on_user_frame_send_cb(frame->hd.stream_id, frame->hd.type, frame->hd.flags);
+ }
+ return 0;
+}
+
+
+/**
+* @brief Callback function invoked by `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` when a frame is received.
+* If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``member of their data structure are always
+* ``NULL`` and 0 respectively. The header name/value pairs are emitted via:type:`nghttp2_on_header_callback`
+* To set this callback to :type:`nghttp2_session_callbacks`, use`nghttp2_session_callbacks_set_on_frame_send_callback()`.
+* For HEADERS, PUSH_PROMISE and DATA frames, this callback may be called after stream is closed (see:type:
+* `nghttp2_on_stream_close_callback`). The application should check that stream is still alive using its own stream
+* management or :func:`nghttp2_session_get_stream_user_data()`.
+* Only HEADERS and DATA frame can signal the end of incoming data. If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM``
+* is nonzero, the|frame| is the last frame from the remote peer in this stream.
+* This callback won't be called for CONTINUATION frames.
+* HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame.
+* @param[in] session: nghttp2 session.
+* @param[in] frame: nghttp2 frame.
+* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
+* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
+* @return The implementation of this function must return 0 if it succeeds.
+* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
+* and `nghttp2_session_mem_send()` functions immediately return :enum:
+* `NGHTTP2_ERR_CALLBACK_FAILURE`.
+*/
+static int on_frame_recv_callback(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data)
+{
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+ http2_request *req;
+ NGHTTP2_DBG("on_frame_recv_callback, type = %d\n", frame->hd.type);
+ NGHTTP2_DBG("on_frame_recv_callback, stream_id = %d\n", frame->hd.stream_id);
+
+ if (connection == NULL) {
+ return 0;
+ }
+
+ req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
+ if (req == NULL) {
+ NGHTTP2_DBG("stream user data is not exist\n");
+ }
+
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS: {
+ if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
+
+ }
+ } break;
+ case NGHTTP2_RST_STREAM: {
+ connection->status = 0;
+ NGHTTP2_DBG("[INFO] C <--------- S (RST_STREAM)\n");
+ } break;
+ case NGHTTP2_GOAWAY: {
+ connection->status = 0;
+ NGHTTP2_DBG("[INFO] C <--------- S (GOAWAY) code = %d\n",frame->goaway.error_code);
+ } break;
+ case NGHTTP2_DATA: {
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ NGHTTP2_DBG("end stream flag\r\n");
+ }
+ } break;
+ case NGHTTP2_PING: {
+ NGHTTP2_DBG("[INFO] C <--------- S (PING)\n");
+ ping_state = PING_RECVED;
+ } break;
+ }
+
+ if (connection->cbs && connection->cbs->on_user_frame_recv_cb) {
+ connection->cbs->on_user_frame_recv_cb(frame->hd.stream_id, frame->hd.type, frame->hd.flags);
+ }
+ return 0;
+}
+
+/**
+* @brief Callback function invoked when the stream |stream_id| is closed.
+* We use this function to know if the response is fully received. Since we just fetch 1 resource in this program, after
+* the response is received, we submit GOAWAY and close the session.
+* @param[in] session: nghttp2 session.
+* @param[in] stream_id: stream id.
+* @param[in] error_code: The reason of closure.
+* Usually one of :enum:`nghttp2_error_code`, but that is not guaranteed. The stream_user_data, which was specified in
+* `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still available in this function.
+* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
+* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
+* @return The implementation of this function must return 0 if it succeeds.
+* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
+* and `nghttp2_session_mem_send()` functions immediately return :enum:
+* `NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+static int on_h2_stream_close_callback(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code,
+ void *user_data)
+{
+ http2_request *req;
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+
+ if (connection == NULL) {
+ return 0;
+ }
+ req = nghttp2_session_get_stream_user_data(session, stream_id);
+ if (req) {
+ int rv;
+ rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
+
+ if (rv != 0) {
+ NGHTTP2_DBG("stream close nghttp2_session_terminate_session\r\n");
+ }
+ }
+ if (connection->cbs && connection->cbs->on_user_stream_close_cb) {
+ connection->cbs->on_user_stream_close_cb(stream_id, error_code);
+ }
+ return 0;
+}
+
+
+/**
+* @brief Callback function invoked when a chunk of data in DATA frame is received.
+* The implementation of nghttp2_on_data_chunk_recv_callback type. We use this function to print the received response body.
+* @param[in] session: nghttp2 session.
+* @param[in] flags: no using.
+* @param[in] stream_id: the stream ID this DATA frame belongs to.
+* @param[in] data: receive data.
+* @param[in] len: data length.
+* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
+* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
+* @return The implementation of this function must return 0 if it succeeds.
+* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
+* and `nghttp2_session_mem_send()` functions immediately return :enum:
+* `NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+static int on_data_chunk_recv_callback(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ const uint8_t *data, size_t len,
+ void *user_data)
+{
+ http2_request *req;
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+
+ if (connection == NULL) {
+ return 0;
+ }
+
+ req = nghttp2_session_get_stream_user_data(session, stream_id);
+ if (req) {
+ NGHTTP2_DBG("stream user data is not exist\n");
+ }
+ NGHTTP2_DBG("[INFO] C <----------- S (DATA chunk) stream_id [%d] :: %lu bytes\n", stream_id, (unsigned long int)len);
+
+ if (connection->cbs && connection->cbs->on_user_chunk_recv_cb) {
+ connection->cbs->on_user_chunk_recv_cb(stream_id, data, len, flags);
+ }
+
+ nghttp2_session_consume_connection(session, len);
+ nghttp2_session_consume(session, stream_id, len);
+ nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, len);
+ nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, stream_id, len);
+ nghttp2_session_send(session);
+
+ return 0;
+}
+
+
+/**
+* @brief Callback function invoked when a header name/value pair is received.
+* The implementation of nghttp2_on_data_chunk_recv_callback type. We use this function to print the received response body.
+* @param[in] session: nghttp2 session.
+* @param[in] frame: nghttp2 frame.
+* @param[in] name: header name.
+* @param[in] namelen: length of header name.
+* @param[in] value: header value.
+* @param[in] valuelen: length of header value.
+* @param[in] flags: no using.
+* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
+* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
+* @return The implementation of this function must return 0 if it succeeds.
+* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
+* and `nghttp2_session_mem_send()` functions immediately return :enum:
+* `NGHTTP2_ERR_CALLBACK_FAILURE`.
+*/
+
+
+static int on_header_callback(nghttp2_session *session,
+ const nghttp2_frame *frame, const uint8_t *name,
+ size_t namelen, const uint8_t *value,
+ size_t valuelen, uint8_t flags,
+ void *user_data)
+{
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+ if (connection == NULL) {
+ return 0;
+ }
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS:
+
+ if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+ /* Print response headers for the initiated request. */
+ NGHTTP2_DBG("< %s: %s\n", name, value);
+
+ if (connection->cbs && connection->cbs->on_user_header_cb) {
+ connection->cbs->on_user_header_cb(frame->hd.stream_id, (int)frame->headers.cat, name, namelen, value, valuelen, flags);
+ }
+ break;
+ }
+
+ }
+ return 0;
+}
+
+/**
+* @brief Called when nghttp2 library gets started to receive header block.
+* @param[in] session: nghttp2 session.
+* @param[in] frame: nghttp2 frame.
+* @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to
+* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`
+* @return The implementation of this function must return 0 if it succeeds.
+* If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()`
+* and `nghttp2_session_mem_send()` functions immediately return :enum:
+* `NGHTTP2_ERR_CALLBACK_FAILURE`.
+*/
+static int on_begin_headers_callback(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data)
+{
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS:
+ if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
+ NGHTTP2_DBG("[INFO] C <--------- S (HEADERS) stream_id [%d]\n", (int)frame->hd.stream_id);
+ }
+ break;
+ }
+ return 0;
+}
+
+
+/**
+* @brief Setup callback functions.
+* nghttp2 API offers many callback functions, but most of them are optional. The send_callback is always required.
+* Since we use nghttp2_session_recv(), the recv_callback is also required.
+* @param[in|out] callbacks: nghttp2 callbacks.
+* @return None.
+ */
+static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
+{
+ nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
+
+ nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
+
+ nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
+ on_frame_send_callback);
+
+ nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
+ on_frame_recv_callback);
+
+ nghttp2_session_callbacks_set_on_stream_close_callback(
+ callbacks, on_h2_stream_close_callback);
+
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ callbacks, on_data_chunk_recv_callback);
+
+ nghttp2_session_callbacks_set_on_header_callback(callbacks,
+ on_header_callback);
+
+ nghttp2_session_callbacks_set_on_begin_headers_callback(
+ callbacks, on_begin_headers_callback);
+
+}
+
+
+static ssize_t data_read_callback(nghttp2_session *session, int32_t stream_id,
+ uint8_t *buf, size_t length,
+ uint32_t *data_flags,
+ nghttp2_data_source *source,
+ void *user_data)
+{
+ int len = 0;
+ http2_connection_t *connection = (http2_connection_t *)user_data;
+ if (connection == NULL) {
+ return 0;
+ }
+
+ if (source->ptr == NULL) {
+ return 0;
+ }
+ if (connection != NULL && connection->flag != NGHTTP2_FLAG_END_STREAM) {
+ *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
+ connection->flag = NGHTTP2_FLAG_NONE;
+ }
+ *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+
+ /*len = strlen((char *)source->ptr);*/
+ len = source->len;
+
+ if (length < len) {
+ len = length;
+ }
+ memcpy(buf, source->ptr, len);
+ return len;
+}
+
+
+static int http2_nv_copy_nghttp2_nv(nghttp2_nv *nva, int start, http2_header *nva_copy, int end)
+{
+ int i, j;
+ for (i = start, j = 0; j < end; i++, j++) {
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+ nva[i].name = (uint8_t *)nva_copy[j].name;
+ nva[i].value = (uint8_t *)nva_copy[j].value;
+ nva[i].namelen = nva_copy[j].namelen;
+ nva[i].valuelen = nva_copy[j].valuelen;
+ }
+ return i;
+}
+
+
+/**
+* @brief Connect the SSL client.
+* @param[in] pclient: http client.
+* @param[in] url. destination url.
+* @param[in] port. destination port.
+* @param[in] ssl_config: custome config.
+* @return The result. 0 is ok.
+*/
+static int http2_client_conn(httpclient_t *pclient, char *url, int port)
+{
+ int ret = 0;
+ /*char host[MAX_HTTP2_HOST_LEN] = { 0 };*/
+
+ /*http2_parse_host(url, host, sizeof(host));*/
+ if (0 == pclient->net.handle) {
+ /* Establish connection if no. */
+ extern const char *iotx_ca_crt;
+
+ ret = iotx_net_init(&pclient->net, url, port, iotx_ca_crt);
+
+ if (0 != ret) {
+ return ret;
+ }
+ ret = httpclient_connect(pclient);
+ if (0 != ret) {
+ h2_err("http2client_connect is error, ret = %d", ret);
+ httpclient_close(pclient);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+int iotx_http2_client_send(http2_connection_t *conn, http2_data *h2_data)
+{
+ int send_flag = 0;
+ int rv = 0;
+ nghttp2_data_provider data_prd;
+ nghttp2_nv *nva = NULL;
+ int nva_size = 0;
+ http2_header *header = h2_data->header;
+ int header_count = h2_data->header_count;
+ char *data = h2_data->data;
+ int len = h2_data->len;
+ int stream_id = h2_data->stream_id;
+ int flags = h2_data->flag;
+
+ if (conn == NULL) {
+ return -1;
+ }
+
+ if (header != NULL && header_count != 0) {
+ nva = (nghttp2_nv *)HTTP2_STREAM_MALLOC(sizeof(nghttp2_nv) * header_count);
+ if (nva == NULL) {
+ return -1;
+ }
+ nva_size = http2_nv_copy_nghttp2_nv(nva, nva_size, header, header_count);
+ }
+ /*upload to server*/
+ if (data != NULL && len != 0) {
+ data_prd.source.ptr = data;
+ data_prd.source.len = len;
+ data_prd.read_callback = data_read_callback;
+ if (nva_size != 0) {
+ rv = nghttp2_submit_request(conn->session, NULL, nva, nva_size, &data_prd, NULL);
+ h2_data->stream_id = rv;
+ } else {
+ rv = nghttp2_submit_data(conn->session, flags, stream_id, &data_prd);
+ }
+ } else {
+ rv = nghttp2_submit_request(conn->session, NULL, nva, nva_size, NULL, NULL);
+ h2_data->stream_id = rv;
+ }
+ HTTP2_STREAM_FREE(nva);
+
+ if (rv < 0) {
+ return rv;
+ }
+
+ send_flag = nghttp2_session_want_write(conn->session);
+ if (send_flag) {
+ rv = nghttp2_session_send(conn->session);
+ NGHTTP2_DBG("nghttp2_session_send %d\r\n", rv);
+ }
+
+ return rv;
+}
+
+int iotx_http2_client_recv(http2_connection_t *conn, char *data, int data_len, int *len, int timeout)
+{
+ int rv = 0;
+ int read_flag = 0;
+
+ if (conn == NULL) {
+ return -1;
+ }
+
+ set_http2_recv_timeout(timeout);
+ read_flag = nghttp2_session_want_read(conn->session);
+ if (read_flag) {
+ rv = nghttp2_session_recv(conn->session);
+ NGHTTP2_DBG("nghttp2_client_recv %d\r\n", rv);
+ if (rv < 0) {
+ read_flag = 0;
+ }
+ }
+ return rv;
+}
+
+/**
+* @brief the http2 client connect.
+* @param[in] pclient: http client.
+* @return http2 client connection handler.
+*/
+http2_connection_t *iotx_http2_client_connect(void *pclient, char *url, int port)
+{
+ http2_connection_t *connection;
+ nghttp2_session_callbacks *callbacks;
+ int rv;
+ int ret = 0;
+
+ connection = HTTP2_STREAM_MALLOC(sizeof(http2_connection_t));
+ if (connection == NULL) {
+ return NULL;
+ }
+ memset(connection, 0, sizeof(http2_connection_t));
+
+ if (0 != (ret = http2_client_conn((httpclient_t *)pclient, url, port))) {
+ NGHTTP2_DBG("https_client_conn failed %d\r\n", ret);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+ connection->network = pclient;
+
+ rv = nghttp2_session_callbacks_new(&callbacks);
+ if (rv != 0) {
+ NGHTTP2_DBG("nghttp2_session_callbacks_new1 %d", rv);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+
+ setup_nghttp2_callbacks(callbacks);
+ rv = nghttp2_session_client_new((nghttp2_session **)&connection->session, callbacks, connection);
+ if (rv != 0) {
+ NGHTTP2_DBG("nghttp2_session_client_new3 %d", rv);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+ nghttp2_session_callbacks_del(callbacks);
+
+ nghttp2_submit_settings(connection->session, NGHTTP2_FLAG_NONE, NULL, 0);
+#if 0
+
+ parse_uri(&uri, url);
+ request_init(&req, &uri);
+ /* Submit the HTTP request to the outbound queue. */
+ submit_request(connection, &req);
+#endif
+
+ rv = nghttp2_session_send(connection->session);
+ /*request_free(&req);*/
+ if (rv < 0) {
+ NGHTTP2_DBG("nghttp2_session_send fail %d", rv);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+ connection->status = 1;
+ return connection;
+}
+
+/**
+* @brief the http2 client connect.
+* @param[in] pclient: http client.
+* @return http2 client connection handler.
+*/
+http2_connection_t *iotx_http2_client_connect_with_cb(void *pclient, char *url, int port, http2_user_cb_t *cb)
+{
+ http2_connection_t *connection;
+ nghttp2_session_callbacks *callbacks;
+ int rv;
+ int ret = 0;
+
+ connection = HTTP2_STREAM_MALLOC(sizeof(http2_connection_t));
+ if (connection == NULL) {
+ return NULL;
+ }
+ memset(connection, 0, sizeof(http2_connection_t));
+
+ if (0 != (ret = http2_client_conn((httpclient_t *)pclient, url, port))) {
+ NGHTTP2_DBG("https_client_conn failed %d\r\n", ret);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+ connection->network = pclient;
+
+ rv = nghttp2_session_callbacks_new(&callbacks);
+ if (rv != 0) {
+ NGHTTP2_DBG("nghttp2_session_callbacks_new1 %d", rv);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+
+ connection->cbs = cb;
+ setup_nghttp2_callbacks(callbacks);
+
+ rv = nghttp2_session_client_new((nghttp2_session **)&connection->session, callbacks, connection);
+ if (rv != 0) {
+ NGHTTP2_DBG("nghttp2_session_client_new3 %d", rv);
+ nghttp2_session_callbacks_del(callbacks);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+ nghttp2_session_callbacks_del(callbacks);
+
+ nghttp2_submit_settings(connection->session, NGHTTP2_FLAG_NONE, NULL, 0);
+#if 0
+
+ parse_uri(&uri, url);
+ request_init(&req, &uri);
+ /* Submit the HTTP request to the outbound queue. */
+ submit_request(connection, &req);
+#endif
+
+ rv = nghttp2_session_send(connection->session);
+ /*request_free(&req);*/
+ if (rv < 0) {
+ nghttp2_session_del(connection->session);
+ NGHTTP2_DBG("nghttp2_session_send fail %d", rv);
+ HTTP2_STREAM_FREE(connection);
+ return NULL;
+ }
+ connection->status = 1;
+ return connection;
+}
+
+int iotx_http2_client_disconnect(http2_connection_t *conn)
+{
+ /* Resource cleanup */
+ if (conn == NULL) {
+ return -1;
+ }
+ httpclient_close((httpclient_t *)conn->network);
+ nghttp2_session_del(conn->session);
+ HTTP2_STREAM_FREE(conn);
+ return 0;
+}
+
+int iotx_http2_client_send_ping(http2_connection_t *conn)
+{
+ int rv = 0;
+ int send_flag;
+
+ ping_state = PING_IDLE;
+
+ if (conn == NULL) {
+ return -1;
+ }
+ rv = nghttp2_submit_ping(conn->session, NGHTTP2_FLAG_NONE, NULL);
+ if (rv < 0) {
+ return rv;
+ }
+ send_flag = nghttp2_session_want_write(conn->session);
+ if (send_flag) {
+ rv = nghttp2_session_send(conn->session);
+ NGHTTP2_DBG("nghttp2_session_send %d\r\n", rv);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+
+ ping_state = PING_SENDING;
+ return 0;
+}
+
+int iotx_http2_client_recv_ping(void)
+{
+ if (ping_state == PING_RECVED || ping_state == PING_IDLE) {
+ NGHTTP2_DBG("ping recv secceed\r\n");
+ return 0;
+ }
+ else {
+ NGHTTP2_DBG("ping recv timeout");
+ return -1;
+ }
+}
+
+int iotx_http2_get_available_window_size(http2_connection_t *conn)
+{
+ int windows_size = 0;
+
+ if (conn == NULL) {
+ return -1;
+ }
+
+ windows_size = nghttp2_session_get_remote_window_size(conn->session);
+ return windows_size;
+}
+
+
+int iotx_http2_update_window_size(http2_connection_t *conn)
+{
+ int rv;
+
+ if (conn == NULL) {
+ return -1;
+ }
+
+ rv = nghttp2_session_recv(conn->session);
+ if (rv < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Performs the network I/O.
+ */
+int iotx_http2_exec_io(http2_connection_t *connection)
+{
+ if (connection == NULL) {
+ return -1;
+ }
+
+ if (nghttp2_session_want_read(connection->session) /*||
+ nghttp2_session_want_write(connection->session)*/) {
+
+ int rv;
+ rv = nghttp2_session_recv(connection->session);
+ if (rv < 0) {
+ NGHTTP2_DBG("nghttp2_session_recv error");
+ return -1;
+ }
+ /* rv = nghttp2_session_send(connection->session); */
+ /* if (rv < 0) { */
+ /* NGHTTP2_DBG("nghttp2_session_send error"); */
+ /* return -1; */
+ /* } */
+ }
+ return 0;
+}
+
+int iotx_http2_reset_stream(http2_connection_t *connection, int32_t stream_id)
+{
+ int rv = 0;
+ if(connection == NULL){
+ return -1;
+ }
+ if(!nghttp2_session_get_stream_local_close(connection->session,stream_id)) {
+ rv = nghttp2_submit_rst_stream(connection->session,0, stream_id, NGHTTP2_NO_ERROR);
+ }
+ if (rv < 0) {
+ return rv;
+ }
+
+ rv = nghttp2_session_want_write(connection->session);
+ if (rv) {
+ rv = nghttp2_session_send(connection->session);
+ NGHTTP2_DBG("nghttp2_session_send %d\r\n", rv);
+ }
+ return rv;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_cjson.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_cjson.c
new file mode 100644
index 00000000..b2260ca4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_cjson.c
@@ -0,0 +1,1897 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_CJSON
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "infra_cjson.h"
+#include "infra_types.h"
+
+typedef struct {
+ const unsigned char *content;
+ int length;
+ int offset;
+ int depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Predeclare these prototypes. */
+static int parse_value(lite_cjson_t *const item, parse_buffer *const input_buffer);
+static int parse_string(lite_cjson_t *const item, parse_buffer *const input_buffer);
+static int parse_array(lite_cjson_t *const item, parse_buffer *const input_buffer);
+static int parse_object(lite_cjson_t *const item, parse_buffer *const input_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL)) {
+ return NULL;
+ }
+
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
+ buffer->offset++;
+ }
+
+ if (buffer->offset == buffer->length) {
+ buffer->offset--;
+ }
+
+ return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer *const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
+ return NULL;
+ }
+
+ if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
+ buffer->offset += 3;
+ }
+
+ return buffer;
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static int parse_number(lite_cjson_t *const item, parse_buffer *const input_buffer)
+{
+ double number = 0;
+ unsigned char *after_end = NULL;
+ unsigned char number_c_string[64];
+ unsigned char decimal_point = '.';
+ int i = 0;
+
+ if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
+ return -1;
+ }
+
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
+ * of the current locale (for strtod)
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
+ switch (buffer_at_offset(input_buffer)[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case 'e':
+ case 'E':
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
+ break;
+ case '.':
+ number_c_string[i] = decimal_point;
+ break;
+
+ default:
+ goto loop_end;
+ }
+ }
+loop_end:
+ number_c_string[i] = '\0';
+ number = strtod((const char *)number_c_string, (char **)&after_end);
+ if (number_c_string == after_end) {
+ return -1;
+ }
+
+ item->type = cJSON_Number;
+ item->value = (char *)buffer_at_offset(input_buffer);
+ item->value_length = (int)(after_end - number_c_string);
+ item->value_double = number;
+
+ /* use saturation in case of overflow */
+ if (number >= INT_MAX) {
+ item->value_int = INT_MAX;
+ } else if (number <= INT_MIN) {
+ item->value_int = INT_MIN;
+ } else {
+ item->value_int = (int)number;
+ }
+
+ input_buffer->offset += (int)(after_end - number_c_string);
+ return 0;
+}
+
+/* Build an array from input text. */
+static int parse_array(lite_cjson_t *const item, parse_buffer *const input_buffer)
+{
+ lite_cjson_t current_item;
+ int start_pos = input_buffer->offset;
+ item->size = 0;
+
+ if (input_buffer->depth >= LITE_CJSON_NESTING_LIMIT) {
+ return -1; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (buffer_at_offset(input_buffer)[0] != '[') {
+ /* not an array */
+ goto fail;
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
+ /* empty array */
+ goto success;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0)) {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ memset(¤t_item, 0, sizeof(lite_cjson_t));
+
+ /* parse next value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (parse_value(¤t_item, input_buffer) != 0) {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* printf("current item index: %d, type: %d, length: %d, value: %.*s\n", */
+ /* item->size+1, current_item.type, current_item.value_length, current_item.value_length, current_item.value); */
+
+ item->size++;
+ } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
+ goto fail; /* expected end of array */
+ }
+
+success:
+ input_buffer->depth--;
+
+ item->type = cJSON_Array;
+ item->value = (char *)(input_buffer->content + start_pos);
+ item->value_length = input_buffer->offset - start_pos + 1;
+
+ input_buffer->offset++;
+
+ return 0;
+
+fail:
+
+ return -1;
+}
+
+/* Build an object from the text. */
+static int parse_object(lite_cjson_t *const item, parse_buffer *const input_buffer)
+{
+ lite_cjson_t current_item_key;
+ lite_cjson_t current_item_value;
+ int start_pos = input_buffer->offset;
+ item->size = 0;
+
+ if (input_buffer->depth >= LITE_CJSON_NESTING_LIMIT) {
+ return -1; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
+ goto fail; /* not an object */
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
+ goto success; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0)) {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ memset(¤t_item_key, 0, sizeof(lite_cjson_t));
+ memset(¤t_item_value, 0, sizeof(lite_cjson_t));
+
+ /* parse the name of the child */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (parse_string(¤t_item_key, input_buffer) != 0) {
+ goto fail; /* faile to parse name */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
+ goto fail; /* invalid object */
+ }
+
+ /* parse the value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (parse_value(¤t_item_value, input_buffer) != 0) {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* printf("Current Object [Index: %d], [Key Length: %d, Key Value: %.*s], [Value Length: %d, Value: %.*s]\n", */
+ /* item->size+1,current_item_key.value_length,current_item_key.value_length,current_item_key.value, */
+ /* current_item_value.value_length,current_item_value.value_length,current_item_value.value); */
+
+ item->size++;
+ } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
+ goto fail; /* expected end of object */
+ }
+
+success:
+ input_buffer->depth--;
+
+ item->type = cJSON_Object;
+ item->value = (char *)(input_buffer->content + start_pos);
+ item->value_length = input_buffer->offset - start_pos + 1;
+
+ input_buffer->offset++;
+
+ return 0;
+
+fail:
+
+ return -1;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static int parse_string(lite_cjson_t *const item, parse_buffer *const input_buffer)
+{
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+ /* unsigned char *output_pointer = NULL; */
+ /* unsigned char *output = NULL; */
+
+ /* not a string */
+ if (buffer_at_offset(input_buffer)[0] != '\"') {
+ /* printf("not a string"); */
+ goto fail;
+ }
+
+ {
+ /* calculate approximate size of the output (overestimate) */
+ /* int allocation_length = 0; */
+ int skipped_bytes = 0;
+ while (((int)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
+ /* is escape sequence */
+ if (input_end[0] == '\\') {
+ if ((int)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
+ /* prevent buffer overflow when last input character is a backslash */
+ goto fail;
+ }
+ skipped_bytes++;
+ input_end++;
+ }
+ input_end++;
+ }
+ if (((int)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
+ /* printf("end error\n"); */
+ goto fail; /* string ended unexpectedly */
+ }
+#if 0
+ /* This is at most how much we need for the output */
+ allocation_length = (int)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+ output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+ if (output == NULL) {
+ goto fail; /* allocation failure */
+ }
+#endif
+ }
+
+#if 0
+ output_pointer = output;
+ /* loop through the string literal */
+ while (input_pointer < input_end) {
+ if (*input_pointer != '\\') {
+ *output_pointer++ = *input_pointer++;
+ }
+ /* escape sequence */
+ else {
+ unsigned char sequence_length = 2;
+ if ((input_end - input_pointer) < 1) {
+ goto fail;
+ }
+
+ switch (input_pointer[1]) {
+ case 'b':
+ *output_pointer++ = '\b';
+ break;
+ case 'f':
+ *output_pointer++ = '\f';
+ break;
+ case 'n':
+ *output_pointer++ = '\n';
+ break;
+ case 'r':
+ *output_pointer++ = '\r';
+ break;
+ case 't':
+ *output_pointer++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *output_pointer++ = input_pointer[1];
+ break;
+
+ /* UTF-16 literal */
+ case 'u':
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+ if (sequence_length == 0) {
+ /* failed to convert UTF16-literal to UTF-8 */
+ goto fail;
+ }
+ break;
+
+ default:
+ goto fail;
+ }
+ input_pointer += sequence_length;
+ }
+ }
+
+ /* zero terminate the output */
+ *output_pointer = '\0';
+#endif
+
+ item->type = cJSON_String;
+ item->value = (char *)input_pointer;
+ item->value_length = input_end - input_pointer;
+
+ input_buffer->offset = (int)(input_end - input_buffer->content);
+ input_buffer->offset++;
+
+ return 0;
+
+fail:
+#if 0
+ if (output != NULL) {
+ input_buffer->hooks.deallocate(output);
+ }
+#endif
+ if (input_pointer != NULL) {
+ input_buffer->offset = (int)(input_pointer - input_buffer->content);
+ }
+
+ return -1;
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static int parse_value(lite_cjson_t *const lite, parse_buffer *const input_buffer)
+{
+ if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
+ return -1; /* no input */
+ }
+
+ /* parse the different types of values */
+ /* null */
+ if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
+ lite->type = cJSON_NULL;
+ lite->value = (char *)buffer_at_offset(input_buffer);
+ lite->value_length = 4;
+
+ input_buffer->offset += 4;
+ return 0;
+ }
+ /* false */
+ if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
+ lite->type = cJSON_False;
+ lite->value = (char *)buffer_at_offset(input_buffer);
+ lite->value_length = 5;
+
+ input_buffer->offset += 5;
+ return 0;
+ }
+ /* true */
+ if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
+ lite->type = cJSON_True;
+ lite->value = (char *)buffer_at_offset(input_buffer);
+ lite->value_length = 4;
+
+ input_buffer->offset += 4;
+ return 0;
+ }
+ /* string */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
+ /* printf("parse string\n"); */
+ return parse_string(lite, input_buffer);
+ }
+
+ /* number */
+ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-')
+ || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
+ /* printf("parse number\n"); */
+ return parse_number(lite, input_buffer);
+ }
+
+ /* array */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
+ /* printf("parse array\n"); */
+ return parse_array(lite, input_buffer);
+ }
+
+ /* object */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
+ return parse_object(lite, input_buffer);
+ }
+
+ return -1;
+}
+
+int lite_cjson_parse(const char *src, int src_len, lite_cjson_t *lite)
+{
+ parse_buffer buffer;
+
+ if (!lite || !src || !lite || src_len <= 0) {
+ return -1;
+ }
+
+ memset(&buffer, 0, sizeof(parse_buffer));
+ buffer.content = (const unsigned char *)src;
+ buffer.length = src_len;
+ buffer.offset = 0;
+
+ if (parse_value(lite, buffer_skip_whitespace(skip_utf8_bom(&buffer))) != 0) {
+ lite->type = cJSON_Invalid;
+ lite->value = NULL;
+ lite->value_length = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+#if 0
+int lite_cjson_is_false(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_False;
+}
+
+int lite_cjson_is_true(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_True;
+}
+
+int lite_cjson_is_null(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_NULL;
+}
+#endif
+
+int lite_cjson_is_number(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_Number;
+}
+
+int lite_cjson_is_string(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_String;
+}
+
+int lite_cjson_is_array(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_Array;
+}
+
+int lite_cjson_is_object(lite_cjson_t *lite)
+{
+ if (!lite) {
+ return -1;
+ }
+
+ return (lite->type & 0xFF) == cJSON_Object;
+}
+
+int lite_cjson_array_item(lite_cjson_t *lite, int index, lite_cjson_t *lite_item)
+{
+ parse_buffer buffer;
+ parse_buffer *p_buffer = &buffer;
+ lite_cjson_t current_item;
+ int iter_index = 0;
+
+ if (!lite || lite->type != cJSON_Array || !lite->value ||
+ index < 0 || index >= lite->size || !lite_item) {
+ return -1;
+ }
+
+ memset(&buffer, 0, sizeof(parse_buffer));
+ buffer.content = (const unsigned char *)lite->value;
+ buffer.length = lite->value_length;
+ buffer.offset = 0;
+
+ /* int start_pos = p_buffer->offset; */
+
+ if (buffer_at_offset(p_buffer)[0] != '[') {
+ /* not an array */
+ return -1;
+ }
+
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (can_access_at_index(p_buffer, 0) && (buffer_at_offset(p_buffer)[0] == ']')) {
+ /* empty array */
+ return -1;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(p_buffer, 0)) {
+ p_buffer->offset--;
+ return -1;
+ }
+
+ /* step back to character in front of the first element */
+ p_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ memset(¤t_item, 0, sizeof(lite_cjson_t));
+
+ /* parse next value */
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (parse_value(¤t_item, p_buffer) != 0) {
+ return -1; /* failed to parse value */
+ }
+ buffer_skip_whitespace(p_buffer);
+
+ /* printf("current item index: %d, type: %d, length: %d, value: %.*s\n", */
+ /* iter_index+1, current_item.type, current_item.value_length, current_item.value_length, current_item.value); */
+
+ if (iter_index == index) {
+ memcpy(lite_item, ¤t_item, sizeof(lite_cjson_t));
+ return 0;
+ }
+
+ iter_index++;
+ } while (can_access_at_index(p_buffer, 0) && (buffer_at_offset(p_buffer)[0] == ','));
+
+ return -1;
+}
+
+static int _lite_cjson_object_item(lite_cjson_t *lite, const char *key, int key_len,
+ lite_cjson_t *lite_item)
+{
+ parse_buffer buffer;
+ parse_buffer *p_buffer = &buffer;
+ lite_cjson_t current_item_key;
+ lite_cjson_t current_item_value;
+ int index = 0;
+
+ if (!lite || lite->type != cJSON_Object || !lite->value || lite->size == 0 || !key || key_len <= 0 || !lite_item) {
+ return -1;
+ };
+
+ memset(&buffer, 0, sizeof(parse_buffer));
+ buffer.content = (const unsigned char *)lite->value;
+ buffer.length = lite->value_length;
+ buffer.offset = 0;
+
+ /* int start_pos = p_buffer->offset; */
+
+ if (cannot_access_at_index(p_buffer, 0) || (buffer_at_offset(p_buffer)[0] != '{')) {
+ return -1; /* not an object */
+ }
+
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (can_access_at_index(p_buffer, 0) && (buffer_at_offset(p_buffer)[0] == '}')) {
+ return -1; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(p_buffer, 0)) {
+ p_buffer->offset--;
+ return -1;
+ }
+
+ /* step back to character in front of the first element */
+ p_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ memset(¤t_item_key, 0, sizeof(lite_cjson_t));
+ memset(¤t_item_value, 0, sizeof(lite_cjson_t));
+
+ /* parse the name of the child */
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (parse_string(¤t_item_key, p_buffer) != 0) {
+ return -1; /* faile to parse name */
+ }
+ buffer_skip_whitespace(p_buffer);
+
+ if (cannot_access_at_index(p_buffer, 0) || (buffer_at_offset(p_buffer)[0] != ':')) {
+ return -1; /* invalid object */
+ }
+
+ /* parse the value */
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (parse_value(¤t_item_value, p_buffer) != 0) {
+ return -1; /* failed to parse value */
+ }
+ buffer_skip_whitespace(p_buffer);
+
+ /* printf("Current Object [Index: %d], [Key Length: %d, Key Value: %.*s], [Value Length: %d, Value: %.*s]\n", */
+ /* index + 1, current_item_key.value_length,current_item_key.value_length,current_item_key.value, */
+ /* current_item_value.value_length,current_item_value.value_length,current_item_value.value); */
+ index++;
+
+ /* printf("key: %s, ken_len: %d\n",key,key_len); */
+ if ((current_item_key.value_length == key_len) &&
+ memcmp(current_item_key.value, key, key_len) == 0) {
+ memcpy(lite_item, ¤t_item_value, sizeof(lite_cjson_t));
+ return 0;
+ }
+ } while (can_access_at_index(p_buffer, 0) && (buffer_at_offset(p_buffer)[0] == ','));
+
+ return -1;
+}
+
+static int _lite_cjson_key_array_index(const char *key, int key_len,
+ int *partial_key_len, int *array_key_len, int *array_index)
+{
+ char *bracket_pre = NULL;
+ char *bracket_suf = NULL;
+ int index = 0;
+ int deep = 0;
+ char array_index_str[10] = {0};
+
+ if (!key || !partial_key_len || !array_key_len || !array_index) {
+ return -1;
+ }
+
+ for (index = 0; index < key_len; index++) {
+ switch (key[index]) {
+ case '[': {
+ if (deep != 0) {
+ return -1;
+ }
+ deep++;
+ if (!bracket_pre) {
+ bracket_pre = (char *)&key[index];
+ }
+ }
+ break;
+ case ']': {
+ if (deep != 1) {
+ return -1;
+ }
+ deep--;
+ if (key[index - 1] == '[') {
+ return -1;
+ }
+ if (!bracket_suf) {
+ bracket_suf = (char *)&key[index];
+ }
+ }
+ break;
+ default:
+ break;
+
+ }
+ }
+
+ if (bracket_pre && bracket_suf && ((bracket_suf - key + 1) == key_len)) {
+ *partial_key_len = bracket_pre - key;
+ *array_key_len = bracket_suf - key + 1;
+
+ /* Get Index */
+ memcpy(array_index_str, bracket_pre + 1, bracket_suf - bracket_pre - 1);
+ *array_index = atoi(array_index_str);
+ return 0;
+ }
+
+ return -1;
+}
+
+int lite_cjson_object_item(lite_cjson_t *lite, const char *key, int key_len,
+ lite_cjson_t *lite_item)
+{
+ int res = 0;
+ char *delim = NULL;
+ lite_cjson_t lite_prev;
+ lite_cjson_t lite_next;
+ lite_cjson_t lite_iter;
+ char *key_iter = (char *)key;
+ int key_iter_len = 0;
+ int partial_key_len = 0;
+ int array_key_len = 0;
+ int array_index = 0;
+
+ if (!lite || lite->type != cJSON_Object || !lite->value || lite->size == 0 || !key || key_len <= 0 || !lite_item) {
+ return -1;
+ };
+
+ memcpy(&lite_iter, lite, sizeof(lite_cjson_t));
+ memset(&lite_prev, 0, sizeof(lite_cjson_t));
+
+ do {
+ if ((delim = strchr(key_iter, '.')) != NULL) {
+ /* printf("delim exist,delim : %s\n",delim); */
+ memset(&lite_next, 0, sizeof(lite_cjson_t));
+ partial_key_len = array_key_len = array_index = 0;
+ key_iter_len = (int)(delim - key_iter);
+ } else {
+ key_iter_len = key_len - (key_iter - key);
+ /* printf("key: %s, last key: %s, key len: %d, last key len: %d\n",key, key_iter, key_len, key_iter_len); */
+ }
+
+ if (_lite_cjson_key_array_index(key_iter, key_iter_len,
+ &partial_key_len, &array_key_len, &array_index) == 0) {
+
+ /* printf("partial_key_len: %d, array_key_len: %d, array_index: %d\n", partial_key_len, array_key_len, array_index); */
+
+ res = _lite_cjson_object_item(&lite_iter, key_iter, partial_key_len, &lite_prev);
+ if (res || lite_prev.type != cJSON_Array) {
+ return -1;
+ }
+ /* printf("current array: %.*s\n",lite_prev.value_length,lite_prev.value); */
+
+ res = lite_cjson_array_item(&lite_prev, array_index, &lite_next);
+ if (res) {
+ return -1;
+ }
+ /* printf("current array item: %.*s\n",lite_next.value_length,lite_next.value); */
+
+ memcpy(&lite_iter, &lite_next, sizeof(lite_cjson_t));
+ key_iter += array_key_len + 1;
+ /* printf("key_iter: %s\n",key_iter); */
+ } else {
+ res = _lite_cjson_object_item(&lite_iter, key_iter, key_iter_len, &lite_prev);
+ if (res) {
+ return -1;
+ }
+ /* printf("current object: %.*s\n",lite_prev.value_length,lite_prev.value); */
+
+ memcpy(&lite_iter, &lite_prev, sizeof(lite_cjson_t));
+ key_iter = delim + 1;
+ }
+ } while (delim);
+
+ /* printf("final lite cjson value: %.*s\n",lite_iter.value_length,lite_iter.value); */
+ memcpy(lite_item, &lite_iter, sizeof(lite_cjson_t));
+
+ return 0;
+}
+
+int lite_cjson_object_item_by_index(lite_cjson_t *lite, int index, lite_cjson_t *lite_item_key,
+ lite_cjson_t *lite_item_value)
+{
+ parse_buffer buffer;
+ parse_buffer *p_buffer = &buffer;
+ lite_cjson_t current_item_key;
+ lite_cjson_t current_item_value;
+ /* int start_pos = p_buffer->offset; */
+ int item_index = 0;
+
+ if (!lite || lite->type != cJSON_Object || !lite->value || lite->size == 0 || index < 0 || index >= lite->size) {
+ return -1;
+ };
+
+ memset(&buffer, 0, sizeof(parse_buffer));
+ buffer.content = (const unsigned char *)lite->value;
+ buffer.length = lite->value_length;
+ buffer.offset = 0;
+
+ if (cannot_access_at_index(p_buffer, 0) || (buffer_at_offset(p_buffer)[0] != '{')) {
+ return -1; /* not an object */
+ }
+
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (can_access_at_index(p_buffer, 0) && (buffer_at_offset(p_buffer)[0] == '}')) {
+ return -1; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(p_buffer, 0)) {
+ p_buffer->offset--;
+ return -1;
+ }
+
+ /* step back to character in front of the first element */
+ p_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ memset(¤t_item_key, 0, sizeof(lite_cjson_t));
+ memset(¤t_item_value, 0, sizeof(lite_cjson_t));
+
+ /* parse the name of the child */
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (parse_string(¤t_item_key, p_buffer) != 0) {
+ return -1; /* faile to parse name */
+ }
+ buffer_skip_whitespace(p_buffer);
+
+ if (cannot_access_at_index(p_buffer, 0) || (buffer_at_offset(p_buffer)[0] != ':')) {
+ return -1; /* invalid object */
+ }
+
+ /* parse the value */
+ p_buffer->offset++;
+ buffer_skip_whitespace(p_buffer);
+ if (parse_value(¤t_item_value, p_buffer) != 0) {
+ return -1; /* failed to parse value */
+ }
+ buffer_skip_whitespace(p_buffer);
+
+ /* printf("Current Object [Index: %d], [Key Length: %d, Key Value: %.*s], [Value Length: %d, Value: %.*s]\n", */
+ /* index + 1, current_item_key.value_length,current_item_key.value_length,current_item_key.value, */
+ /* current_item_value.value_length,current_item_value.value_length,current_item_value.value); */
+
+ /* printf("index:%d, key: %.*s, value: %.*s\n",index, */
+ /* current_item_key.value_length,current_item_key.value, */
+ /* current_item_value.value_length,current_item_value.value); */
+
+ if (item_index == index) {
+ if (lite_item_key) {
+ memcpy(lite_item_key, ¤t_item_key, sizeof(lite_cjson_t));
+ }
+ if (lite_item_value) {
+ memcpy(lite_item_value, ¤t_item_value, sizeof(lite_cjson_t));
+ }
+ return 0;
+ }
+
+ item_index++;
+ } while (can_access_at_index(p_buffer, 0) && (buffer_at_offset(p_buffer)[0] == ','));
+
+ return -1;
+}
+
+/*** cjson create, add and print ***/
+#if defined(DEVICE_MODEL_GATEWAY) || defined(ALCS_ENABLED) || defined(DEPRECATED_LINKKIT)
+#define true ((cJSON_bool)1)
+#define false ((cJSON_bool)0)
+#define cjson_min(a, b) ((a < b) ? a : b)
+
+typedef struct internal_hooks {
+ void *(*allocate)(uint32_t size);
+ void (*deallocate)(void *pointer);
+ void *(*reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+typedef struct {
+ unsigned char *buffer;
+ size_t length;
+ size_t offset;
+ size_t depth; /* current nesting depth (for formatted printing) */
+ cJSON_bool noalloc;
+ cJSON_bool format; /* is this print a formatted print */
+ internal_hooks hooks;
+} printbuffer;
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+static void *internal_malloc(uint32_t size)
+{
+ return HAL_Malloc(size);
+}
+
+static void internal_free(void *ptr)
+{
+ HAL_Free(ptr);
+}
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, NULL };
+static cJSON_bool print_value(const lite_cjson_item_t *const item, printbuffer *const output_buffer);
+
+void lite_cjson_init_hooks(lite_cjson_hooks *hooks)
+{
+ if (hooks == NULL || hooks->malloc_fn == NULL || hooks->free_fn == NULL) {
+ return;
+ }
+
+ global_hooks.allocate = hooks->malloc_fn;
+ global_hooks.deallocate = hooks->free_fn;
+}
+
+static unsigned char *ensure(printbuffer *const p, size_t needed)
+{
+ unsigned char *newbuffer = NULL;
+ size_t newsize = 0;
+
+ if ((p == NULL) || (p->buffer == NULL)) {
+ return NULL;
+ }
+
+ if ((p->length > 0) && (p->offset >= p->length)) {
+ /* make sure that offset is valid */
+ return NULL;
+ }
+
+ if (needed > INT_MAX) {
+ /* sizes bigger than INT_MAX are currently not supported */
+ return NULL;
+ }
+
+ needed += p->offset + 1;
+ if (needed <= p->length) {
+ return p->buffer + p->offset;
+ }
+
+ if (p->noalloc) {
+ return NULL;
+ }
+
+ /* calculate new buffer size */
+ if (needed > (INT_MAX / 2)) {
+ /* overflow of int, use INT_MAX if possible */
+ if (needed <= INT_MAX) {
+ newsize = INT_MAX;
+ } else {
+ return NULL;
+ }
+ } else {
+ newsize = needed * 2;
+ }
+
+ if (p->hooks.reallocate != NULL) {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize);
+ if (newbuffer == NULL) {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ } else {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char *)p->hooks.allocate(newsize);
+ if (!newbuffer) {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ if (newbuffer) {
+ memcpy(newbuffer, p->buffer, p->offset + 1);
+ }
+ p->hooks.deallocate(p->buffer);
+ }
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+ struct lconv *lconv = localeconv();
+ return (unsigned char) lconv->decimal_point[0];
+#else
+ return '.';
+#endif
+}
+
+static int remove_zero(unsigned char buffer[26], int length)
+{
+ int idx = 0, found = 0;
+
+ for (idx = 0; idx < 26; idx++) {
+ if (buffer[idx] == '.') {
+ found = 1;
+ continue;
+ }
+ if (buffer[idx] == '\0') {
+ break;
+ }
+ }
+
+ if (found == 0) {
+ return length;
+ }
+
+ for (; idx > 0; idx--) {
+ if (buffer[idx - 1] == '0') {
+ buffer[idx - 1] = '\0';
+ length--;
+ } else {
+ if (buffer[idx - 1] == '.') {
+ buffer[idx - 1] = '\0';
+ length--;
+ }
+ break;
+ }
+ }
+
+ return length;
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const lite_cjson_item_t *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ double d = item->valuedouble;
+ int length = 0;
+ size_t i = 0;
+ unsigned char number_buffer[26]; /* temporary buffer to print the number into */
+ unsigned char decimal_point = get_decimal_point();
+ float test_float;
+ double test;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* This checks for NaN and Infinity */
+ if ((d * 0) != 0) {
+ length = sprintf((char *)number_buffer, "null");
+ } else {
+ /* Try float data type */
+ length = sprintf((char *)number_buffer, "%f", d);
+
+ if ((sscanf((char *)number_buffer, "%f", &test_float) != 1) || ((double)test_float != d)) {
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+ length = sprintf((char *)number_buffer, "%1.15g", d);
+
+ /* Check whether the original double can be recovered */
+ if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || ((double)test != d)) {
+ /* If not, print with 17 decimal places of precision */
+ length = sprintf((char *)number_buffer, "%1.17g", d);
+ }
+ } else {
+ length = remove_zero(number_buffer, length);
+ }
+ }
+
+ /* sprintf failed or buffer overrun occured */
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
+ return false;
+ }
+
+ /* reserve appropriate space in the output */
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ /* copy the printed number to the output and replace locale
+ * dependent decimal point with '.' */
+ for (i = 0; i < ((size_t)length); i++) {
+ if (number_buffer[i] == decimal_point) {
+ output_pointer[i] = '.';
+ continue;
+ }
+
+ output_pointer[i] = number_buffer[i];
+ }
+ output_pointer[i] = '\0';
+
+ output_buffer->offset += (size_t)length;
+
+ return true;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer)
+{
+ const unsigned char *input_pointer = NULL;
+ unsigned char *output = NULL;
+ unsigned char *output_pointer = NULL;
+ size_t output_length = 0;
+ /* numbers of additional characters needed for escaping */
+ size_t escape_characters = 0;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* empty string */
+ if (input == NULL) {
+ output = ensure(output_buffer, sizeof("\"\""));
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "\"\"");
+
+ return true;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (input_pointer = input; *input_pointer; input_pointer++) {
+ switch (*input_pointer) {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ /* one character escape sequence */
+ escape_characters++;
+ break;
+ default:
+ if (*input_pointer < 32) {
+ /* UTF-16 escape sequence uXXXX */
+ escape_characters += 5;
+ }
+ break;
+ }
+ }
+ output_length = (size_t)(input_pointer - input) + escape_characters;
+
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
+ if (output == NULL) {
+ return false;
+ }
+
+ /* no characters have to be escaped */
+ if (escape_characters == 0) {
+ output[0] = '\"';
+ memcpy(output + 1, input, output_length);
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+ }
+
+ output[0] = '\"';
+ output_pointer = output + 1;
+ /* copy the string */
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
+ /* normal character, copy */
+ *output_pointer = *input_pointer;
+ } else {
+ /* character needs to be escaped */
+ *output_pointer++ = '\\';
+ switch (*input_pointer) {
+ case '\\':
+ *output_pointer = '\\';
+ break;
+ case '\"':
+ *output_pointer = '\"';
+ break;
+ case '\b':
+ *output_pointer = 'b';
+ break;
+ case '\f':
+ *output_pointer = 'f';
+ break;
+ case '\n':
+ *output_pointer = 'n';
+ break;
+ case '\r':
+ *output_pointer = 'r';
+ break;
+ case '\t':
+ *output_pointer = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf((char *)output_pointer, "u%04x", *input_pointer);
+ output_pointer += 4;
+ break;
+ }
+ }
+ }
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const lite_cjson_item_t *const item, printbuffer *const p)
+{
+ return print_string_ptr((unsigned char *)item->valuestring, p);
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer *const buffer)
+{
+ const unsigned char *buffer_pointer = NULL;
+ if ((buffer == NULL) || (buffer->buffer == NULL)) {
+ return;
+ }
+ buffer_pointer = buffer->buffer + buffer->offset;
+
+ buffer->offset += strlen((const char *)buffer_pointer);
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const lite_cjson_item_t *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ lite_cjson_item_t *current_element = item->child;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* Compose the output array. */
+ /* opening square bracket */
+ output_pointer = ensure(output_buffer, 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ *output_pointer = '[';
+ output_buffer->offset++;
+ output_buffer->depth++;
+
+ while (current_element != NULL) {
+ if (!print_value(current_element, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+ if (current_element->next) {
+ length = (size_t)(output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ',';
+ if (output_buffer->format) {
+ *output_pointer++ = ' ';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+ }
+ current_element = current_element->next;
+ }
+
+ output_pointer = ensure(output_buffer, 2);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ']';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const lite_cjson_item_t *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ lite_cjson_item_t *current_item = item->child;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* Compose the output: */
+ length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ *output_pointer++ = '{';
+ output_buffer->depth++;
+ if (output_buffer->format) {
+ *output_pointer++ = '\n';
+ }
+ output_buffer->offset += length;
+
+ while (current_item) {
+ if (output_buffer->format) {
+ size_t i;
+ output_pointer = ensure(output_buffer, output_buffer->depth);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ for (i = 0; i < output_buffer->depth; i++) {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += output_buffer->depth;
+ }
+
+ /* print key */
+ if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ length = (size_t)(output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ':';
+ if (output_buffer->format) {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += length;
+
+ /* print value */
+ if (!print_value(current_item, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ /* print comma if not last */
+ length = (size_t)((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ if (current_item->next) {
+ *output_pointer++ = ',';
+ }
+
+ if (output_buffer->format) {
+ *output_pointer++ = '\n';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+
+ current_item = current_item->next;
+ }
+
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ if (output_buffer->format) {
+ size_t i;
+ for (i = 0; i < (output_buffer->depth - 1); i++) {
+ *output_pointer++ = '\t';
+ }
+ }
+ *output_pointer++ = '}';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const lite_cjson_item_t *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output = NULL;
+
+ if ((item == NULL) || (output_buffer == NULL)) {
+ return false;
+ }
+
+ switch ((item->type) & 0xFF) {
+ case cJSON_NULL:
+ output = ensure(output_buffer, 5);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "null");
+ return true;
+
+ case cJSON_False:
+ output = ensure(output_buffer, 6);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "false");
+ return true;
+
+ case cJSON_True:
+ output = ensure(output_buffer, 5);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "true");
+ return true;
+
+ case cJSON_Number:
+ return print_number(item, output_buffer);
+
+ case cJSON_Raw: {
+ size_t raw_length = 0;
+ if (item->valuestring == NULL) {
+ return false;
+ }
+
+ raw_length = strlen(item->valuestring) + sizeof("");
+ output = ensure(output_buffer, raw_length);
+ if (output == NULL) {
+ return false;
+ }
+ memcpy(output, item->valuestring, raw_length);
+ return true;
+ }
+
+ case cJSON_String:
+ return print_string(item, output_buffer);
+
+ case cJSON_Array:
+ return print_array(item, output_buffer);
+
+ case cJSON_Object:
+ return print_object(item, output_buffer);
+
+ default:
+ return false;
+ }
+}
+
+static unsigned char *print(const lite_cjson_item_t *const item, cJSON_bool format, const internal_hooks *const hooks)
+{
+ static const size_t default_buffer_size = 256;
+ printbuffer buffer[1];
+ unsigned char *printed = NULL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* create buffer */
+ buffer->buffer = (unsigned char *) hooks->allocate(default_buffer_size);
+ buffer->length = default_buffer_size;
+ buffer->format = format;
+ buffer->hooks = *hooks;
+ if (buffer->buffer == NULL) {
+ goto fail;
+ }
+
+ /* print the value */
+ if (!print_value(item, buffer)) {
+ goto fail;
+ }
+ update_offset(buffer);
+
+ /* check if reallocate is available */
+ if (hooks->reallocate != NULL) {
+ printed = (unsigned char *) hooks->reallocate(buffer->buffer, buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ buffer->buffer = NULL;
+ } else { /* otherwise copy the JSON over to a new buffer */
+ printed = (unsigned char *) hooks->allocate(buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+ printed[buffer->offset] = '\0'; /* just to be sure */
+
+ /* free the buffer */
+ hooks->deallocate(buffer->buffer);
+ }
+
+ return printed;
+
+fail:
+ if (buffer->buffer != NULL) {
+ hooks->deallocate(buffer->buffer);
+ }
+
+ return NULL;
+}
+
+char *lite_cjson_print(lite_cjson_item_t *item)
+{
+ return (char *)print(item, true, &global_hooks);
+}
+
+char *lite_cjson_print_unformatted(lite_cjson_item_t *item)
+{
+ return (char *)print(item, false, &global_hooks);
+}
+
+/* Delete a cJSON structure. */
+void lite_cjson_delete(lite_cjson_item_t *item)
+{
+ lite_cjson_item_t *next = NULL;
+ while (item != NULL) {
+ next = item->next;
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
+ lite_cjson_delete(item->child);
+ }
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
+ global_hooks.deallocate(item->valuestring);
+ }
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
+ global_hooks.deallocate(item->string);
+ }
+ global_hooks.deallocate(item);
+ item = next;
+ }
+}
+
+static void suffix_object(lite_cjson_item_t *prev, lite_cjson_item_t *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+static cJSON_bool add_item_to_array(lite_cjson_item_t *array, lite_cjson_item_t *item)
+{
+ lite_cjson_item_t *child = NULL;
+
+ if ((item == NULL) || (array == NULL)) {
+ return false;
+ }
+
+ child = array->child;
+
+ if (child == NULL) {
+ /* list is empty, start new one */
+ array->child = item;
+ } else {
+ /* append to the end */
+ while (child->next) {
+ child = child->next;
+ }
+ suffix_object(child, item);
+ }
+
+ return true;
+}
+
+void lite_cjson_add_item_to_array(lite_cjson_item_t *array, lite_cjson_item_t *item)
+{
+ add_item_to_array(array, item);
+}
+
+static void *cast_away_const(const void *string)
+{
+ return (void *)string;
+}
+
+static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks)
+{
+ size_t length = 0;
+ unsigned char *copy = NULL;
+
+ if (string == NULL) {
+ return NULL;
+ }
+
+ length = strlen((const char *)string) + sizeof("");
+ copy = (unsigned char *)hooks->allocate(length);
+ if (copy == NULL) {
+ return NULL;
+ }
+ memcpy(copy, string, length);
+
+ return copy;
+}
+
+static cJSON_bool add_item_to_object(lite_cjson_item_t *const object, const char *const string,
+ lite_cjson_item_t *const item, const internal_hooks *const hooks, const cJSON_bool constant_key)
+{
+ char *new_key = NULL;
+ int new_type = cJSON_Invalid;
+
+ if ((object == NULL) || (string == NULL) || (item == NULL)) {
+ return false;
+ }
+
+ if (constant_key) {
+ new_key = (char *)cast_away_const(string);
+ new_type = item->type | cJSON_StringIsConst;
+ } else {
+ new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks);
+ if (new_key == NULL) {
+ return false;
+ }
+
+ new_type = item->type & ~cJSON_StringIsConst;
+ }
+
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
+ hooks->deallocate(item->string);
+ }
+
+ item->string = new_key;
+ item->type = new_type;
+
+ return add_item_to_array(object, item);
+}
+
+void lite_cjson_add_item_to_object(lite_cjson_item_t *object, const char *string, lite_cjson_item_t *item)
+{
+ add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+static lite_cjson_item_t *cJSON_New_Item(const internal_hooks *const hooks)
+{
+ lite_cjson_item_t *node = (lite_cjson_item_t *)hooks->allocate(sizeof(lite_cjson_item_t));
+ if (node) {
+ memset(node, '\0', sizeof(lite_cjson_item_t));
+ }
+
+ return node;
+}
+
+lite_cjson_item_t *lite_cjson_create_null(void)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_true(void)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_false(void)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_bool(cJSON_bool b)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = b ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_number(double num)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+
+ /* use saturation in case of overflow */
+ if (num >= INT_MAX) {
+ item->valueint = INT_MAX;
+ } else if (num <= INT_MIN) {
+ item->valueint = INT_MIN;
+ } else {
+ item->valueint = (int)num;
+ }
+ }
+
+ return item;
+}
+lite_cjson_item_t *lite_cjson_create_string(const char *string)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_String;
+ item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
+ if (!item->valuestring) {
+ lite_cjson_delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_array(void)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Array;
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_object(void)
+{
+ lite_cjson_item_t *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+lite_cjson_item_t *lite_cjson_create_intArray(const int *numbers, int count)
+{
+ size_t i = 0;
+ lite_cjson_item_t *n = NULL;
+ lite_cjson_item_t *p = NULL;
+ lite_cjson_item_t *a = NULL;
+
+ if ((count < 0) || (numbers == NULL)) {
+ return NULL;
+ }
+
+ a = lite_cjson_create_array();
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = lite_cjson_create_number(numbers[i]);
+ if (!n) {
+ lite_cjson_delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+lite_cjson_item_t *lite_cjson_create_floatArray(const float *numbers, int count)
+{
+ size_t i = 0;
+ lite_cjson_item_t *n = NULL;
+ lite_cjson_item_t *p = NULL;
+ lite_cjson_item_t *a = NULL;
+
+ if ((count < 0) || (numbers == NULL)) {
+ return NULL;
+ }
+
+ a = lite_cjson_create_array();
+
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = lite_cjson_create_number((double)numbers[i]);
+ if (!n) {
+ lite_cjson_delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+lite_cjson_item_t *lite_cjson_create_doubleArray(const double *numbers, int count)
+{
+ size_t i = 0;
+ lite_cjson_item_t *n = NULL;
+ lite_cjson_item_t *p = NULL;
+ lite_cjson_item_t *a = NULL;
+
+ if ((count < 0) || (numbers == NULL)) {
+ return NULL;
+ }
+
+ a = lite_cjson_create_array();
+
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = lite_cjson_create_number(numbers[i]);
+ if (!n) {
+ lite_cjson_delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+lite_cjson_item_t *lite_cjson_create_stringArray(const char **strings, int count)
+{
+ size_t i = 0;
+ lite_cjson_item_t *n = NULL;
+ lite_cjson_item_t *p = NULL;
+ lite_cjson_item_t *a = NULL;
+
+ if ((count < 0) || (strings == NULL)) {
+ return NULL;
+ }
+
+ a = lite_cjson_create_array();
+
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = lite_cjson_create_string(strings[i]);
+ if (!n) {
+ lite_cjson_delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+#endif
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_cjson.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_cjson.h
new file mode 100644
index 00000000..77c14b55
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_cjson.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _INFRA_CJSON_H_
+#define _INFRA_CJSON_H_
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False (1 << 0)
+#define cJSON_True (1 << 1)
+#define cJSON_NULL (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw (1 << 7) /* raw json */
+
+#ifndef LITE_CJSON_NESTING_LIMIT
+ #define LITE_CJSON_NESTING_LIMIT 1000
+#endif
+
+/* The cJSON structure: */
+typedef struct lite_cjson_st {
+ /* The type of the item, as above. */
+ int type;
+
+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
+ char *value;
+ int value_length;
+
+ /* The item's size, if type == cJSON_Array and type == cJSON_Object */
+ int size;
+
+ double value_double;
+ int value_int;
+} lite_cjson_t;
+
+int lite_cjson_parse(const char *src, int src_len, lite_cjson_t *lite);
+
+int lite_cjson_is_false(lite_cjson_t *lite);
+int lite_cjson_is_true(lite_cjson_t *lite);
+int lite_cjson_is_null(lite_cjson_t *lite);
+int lite_cjson_is_number(lite_cjson_t *lite);
+int lite_cjson_is_string(lite_cjson_t *lite);
+int lite_cjson_is_array(lite_cjson_t *lite);
+int lite_cjson_is_object(lite_cjson_t *lite);
+
+int lite_cjson_array_item(lite_cjson_t *lite, int index, lite_cjson_t *lite_item);
+int lite_cjson_object_item(
+ lite_cjson_t *lite,
+ const char *key,
+ int key_len,
+ lite_cjson_t *lite_item);
+int lite_cjson_object_item_by_index(
+ lite_cjson_t *lite,
+ int index,
+ lite_cjson_t *lite_item_key,
+ lite_cjson_t *lite_item_value);
+
+
+/*** lite_cjson create, add and print ***/
+typedef int cJSON_bool;
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct lite_cjson_item_t {
+ struct lite_cjson_item_t *next,
+ *prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct lite_cjson_item_t
+ *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+
+ int type; /* The type of the item, as above. */
+
+ char *valuestring; /* The item's string, if type==cJSON_String */
+ int valueint; /* The item's number, if type==cJSON_Number */
+ double valuedouble; /* The item's number, if type==cJSON_Number */
+
+ char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+} lite_cjson_item_t;
+
+typedef struct {
+ void *(*malloc_fn)(unsigned int sz);
+ void(*free_fn)(void *ptr);
+} lite_cjson_hooks;
+
+void lite_cjson_init_hooks(lite_cjson_hooks *hooks);
+
+/* Render a lite_cjson_item_t entity to text for transfer/storage. Free the char* when finished. */
+char *lite_cjson_print(lite_cjson_item_t *item);
+char *lite_cjson_print_unformatted(lite_cjson_item_t *item);
+
+/* Delete a lite_cjson_item_t entity and all subentities. */
+void lite_cjson_delete(lite_cjson_item_t *item);
+
+/* Append item to specific object */
+void lite_cjson_add_item_to_array(lite_cjson_item_t *array, lite_cjson_item_t *item);
+void lite_cjson_add_item_to_object(lite_cjson_item_t *object, const char *string, lite_cjson_item_t *item);
+
+/* These calls create a lite_cjson_item_t item of the appropriate type. */
+lite_cjson_item_t *lite_cjson_create_null(void);
+lite_cjson_item_t *lite_cjson_create_true(void);
+lite_cjson_item_t *lite_cjson_create_false(void);
+lite_cjson_item_t *lite_cjson_create_bool(int b);
+lite_cjson_item_t *lite_cjson_create_number(double num);
+lite_cjson_item_t *lite_cjson_create_string(const char *string);
+lite_cjson_item_t *lite_cjson_create_array(void);
+lite_cjson_item_t *lite_cjson_create_object(void);
+
+/* These utilities create an Array of count items. */
+lite_cjson_item_t *lite_cjson_create_intArray(const int *numbers, int count);
+lite_cjson_item_t *lite_cjson_create_floatArray(const float *numbers, int count);
+lite_cjson_item_t *lite_cjson_create_doubleArray(const double *numbers, int count);
+lite_cjson_item_t *lite_cjson_create_stringArray(const char **strings, int count);
+
+/* Macros for creating things quickly. */
+#define lite_cjson_add_null_to_object(object,name) lite_cjson_add_item_to_object(object, name, lite_cjson_create_null())
+#define lite_cjson_add_true_to_object(object,name) lite_cjson_add_item_to_object(object, name, lite_cjson_create_true())
+#define lite_cjson_add_false_to_object(object,name) lite_cjson_add_item_to_object(object, name, lite_cjson_create_false())
+#define lite_cjson_add_bool_to_object(object,name,b) lite_cjson_add_item_to_object(object, name, lite_cjson_create_bool(b))
+#define lite_cjson_add_number_to_object(object,name,n) lite_cjson_add_item_to_object(object, name, lite_cjson_create_number(n))
+#define lite_cjson_add_string_to_object(object,name,s) lite_cjson_add_item_to_object(object, name, lite_cjson_create_string(s))
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_compat.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_compat.c
new file mode 100644
index 00000000..a83ed728
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_compat.c
@@ -0,0 +1,279 @@
+#include "infra_config.h"
+
+#ifdef INFRA_COMPAT
+#include
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_compat.h"
+
+#if !defined(INFRA_LOG)
+void IOT_SetLogLevel(IOT_LogLevel level) {}
+#endif
+
+#ifdef MQTT_COMM_ENABLED
+#include "dev_sign_api.h"
+#include "mqtt_api.h"
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define sdk_err(...) log_err("infra_compat", __VA_ARGS__)
+ #define sdk_info(...) log_info("infra_compat", __VA_ARGS__)
+#else
+ #define sdk_err(...)
+ #define sdk_info(...)
+#endif
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+static sdk_impl_ctx_t g_sdk_impl_ctx = {0};
+/* global variable for mqtt construction */
+static iotx_conn_info_t g_iotx_conn_info = {0};
+static char g_empty_string[1] = "";
+
+int IOT_SetupConnInfo(const char *product_key,
+ const char *device_name,
+ const char *device_secret,
+ void **info_ptr)
+{
+ if (product_key == NULL || device_name == NULL || device_secret == NULL ||
+ strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
+ strlen(device_name) > IOTX_DEVICE_NAME_LEN ||
+ strlen(device_secret) > IOTX_DEVICE_SECRET_LEN) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (info_ptr) {
+ memset(&g_iotx_conn_info, 0, sizeof(iotx_conn_info_t));
+ g_iotx_conn_info.host_name = g_empty_string;
+ g_iotx_conn_info.client_id = g_empty_string;
+ g_iotx_conn_info.username = g_empty_string;
+ g_iotx_conn_info.password = g_empty_string;
+ g_iotx_conn_info.pub_key = g_empty_string;
+
+ *info_ptr = &g_iotx_conn_info;
+ }
+ return SUCCESS_RETURN;
+}
+#endif /* #ifdef MQTT_COMM_ENABLED */
+
+#if defined(DEVICE_MODEL_CLASSIC) && defined(DEVICE_MODEL_ENABLED)
+ #include "iotx_dm.h"
+#endif
+
+int IOT_Ioctl(int option, void *data)
+{
+ int res = SUCCESS_RETURN;
+ sdk_impl_ctx_t *ctx = NULL;
+
+ ctx = &g_sdk_impl_ctx;
+
+ if (option < 0 || data == NULL) {
+ return FAIL_RETURN;
+ }
+
+ switch (option) {
+ case IOTX_IOCTL_SET_REGION: {
+ ctx->domain_type = *(int *)data;
+ /* iotx_guider_set_region(*(int *)data); */
+
+ res = SUCCESS_RETURN;
+ }
+ break;
+ case IOTX_IOCTL_GET_REGION: {
+ *(int *)data = ctx->domain_type;
+
+ res = SUCCESS_RETURN;
+ }
+ break;
+ case IOTX_IOCTL_SET_MQTT_DOMAIN: {
+ ctx->domain_type = IOTX_CLOUD_REGION_CUSTOM;
+
+ if (ctx->cloud_custom_domain) {
+ HAL_Free(ctx->cloud_custom_domain);
+ ctx->cloud_custom_domain = NULL;
+ g_infra_mqtt_domain[IOTX_CLOUD_REGION_CUSTOM] = NULL;
+ }
+ ctx->cloud_custom_domain = HAL_Malloc(strlen((char *)data) + 1);
+ if (ctx->cloud_custom_domain == NULL) {
+ return FAIL_RETURN;
+ }
+ memset(ctx->cloud_custom_domain, 0, strlen((char *)data) + 1);
+ memcpy(ctx->cloud_custom_domain, data, strlen((char *)data));
+ g_infra_mqtt_domain[IOTX_CLOUD_REGION_CUSTOM] = (const char *)ctx->cloud_custom_domain;
+ res = SUCCESS_RETURN;
+ }
+ break;
+ case IOTX_IOCTL_SET_HTTP_DOMAIN: {
+ ctx->domain_type = IOTX_HTTP_REGION_CUSTOM;
+
+ if (ctx->http_custom_domain) {
+ HAL_Free(ctx->http_custom_domain);
+ ctx->http_custom_domain = NULL;
+ g_infra_http_domain[IOTX_CLOUD_REGION_CUSTOM] = NULL;
+ }
+ ctx->http_custom_domain = HAL_Malloc(strlen((char *)data) + 1);
+ if (ctx->http_custom_domain == NULL) {
+ return FAIL_RETURN;
+ }
+ memset(ctx->http_custom_domain, 0, strlen((char *)data) + 1);
+ memcpy(ctx->http_custom_domain, data, strlen((char *)data));
+ g_infra_http_domain[IOTX_CLOUD_REGION_CUSTOM] = (const char *)ctx->http_custom_domain;
+ res = SUCCESS_RETURN;
+ }
+ break;
+ case IOTX_IOCTL_SET_DYNAMIC_REGISTER: {
+ ctx->dynamic_register = *(int *)data;
+
+ res = SUCCESS_RETURN;
+ }
+ break;
+ case IOTX_IOCTL_GET_DYNAMIC_REGISTER: {
+ *(int *)data = ctx->dynamic_register;
+
+ res = SUCCESS_RETURN;
+ }
+ break;
+#if defined(DEVICE_MODEL_CLASSIC) && defined(DEVICE_MODEL_ENABLED) && !defined(DEPRECATED_LINKKIT)
+#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
+ case IOTX_IOCTL_RECV_EVENT_REPLY:
+ case IOTX_IOCTL_RECV_PROP_REPLY: {
+ res = iotx_dm_set_opt(IMPL_LINKKIT_IOCTL_SWITCH_EVENT_POST_REPLY, data);
+ }
+ break;
+ case IOTX_IOCTL_SEND_PROP_SET_REPLY : {
+ res = iotx_dm_set_opt(IMPL_LINKKIT_IOCTL_SWITCH_PROPERTY_SET_REPLY, data);
+ }
+ break;
+#endif
+ case IOTX_IOCTL_SET_SUBDEV_SIGN: {
+ /* todo */
+ }
+ break;
+ case IOTX_IOCTL_GET_SUBDEV_LOGIN: {
+ /* todo */
+ }
+ break;
+#if defined(DEVICE_MODEL_CLASSIC) && defined(DEVICE_MODEL_GATEWAY)
+#ifdef DEVICE_MODEL_SUBDEV_OTA
+ case IOTX_IOCTL_SET_OTA_DEV_ID: {
+ int devid = *(int *)(data);
+ res = iotx_dm_ota_switch_device(devid);
+ }
+ break;
+#endif
+#endif
+#else
+ case IOTX_IOCTL_RECV_EVENT_REPLY:
+ case IOTX_IOCTL_RECV_PROP_REPLY:
+ case IOTX_IOCTL_SEND_PROP_SET_REPLY:
+ case IOTX_IOCTL_GET_SUBDEV_LOGIN: {
+ res = SUCCESS_RETURN;
+ }
+ break;
+#endif
+ default: {
+ res = FAIL_RETURN;
+ }
+ break;
+ }
+
+ return res;
+}
+
+void IOT_DumpMemoryStats(IOT_LogLevel level)
+{
+#ifdef INFRA_MEM_STATS
+ int lvl = (int)level;
+
+ if (lvl > LOG_DEBUG_LEVEL) {
+ lvl = LOG_DEBUG_LEVEL;
+ HAL_Printf("Invalid input level, using default: %d => %d", level, lvl);
+ }
+
+ LITE_dump_malloc_free_stats(lvl);
+#endif
+}
+
+static void *g_event_monitor = NULL;
+
+int iotx_event_regist_cb(void (*monitor_cb)(int event))
+{
+ g_event_monitor = (void *)monitor_cb;
+ return 0;
+}
+
+int iotx_event_post(int event)
+{
+ if (g_event_monitor == NULL) {
+ return -1;
+ }
+ ((void (*)(int))g_event_monitor)(event);
+ return 0;
+}
+
+typedef struct {
+ int eventid;
+ void *callback;
+} impl_event_map_t;
+
+static impl_event_map_t g_impl_event_map[] = {
+ {ITE_AWSS_STATUS, NULL},
+ {ITE_CONNECT_SUCC, NULL},
+ {ITE_CONNECT_FAIL, NULL},
+ {ITE_DISCONNECTED, NULL},
+ {ITE_REDIRECT, NULL},
+ {ITE_RAWDATA_ARRIVED, NULL},
+ {ITE_SERVICE_REQUEST, NULL},
+ {ITE_PROPERTY_SET, NULL},
+ {ITE_PROPERTY_GET, NULL},
+#ifdef DEVICE_MODEL_SHADOW
+ {ITE_PROPERTY_DESIRED_GET_REPLY, NULL},
+#endif
+ {ITE_REPORT_REPLY, NULL},
+ {ITE_TRIGGER_EVENT_REPLY, NULL},
+ {ITE_TIMESTAMP_REPLY, NULL},
+ {ITE_TOPOLIST_REPLY, NULL},
+ {ITE_PERMIT_JOIN, NULL},
+ {ITE_INITIALIZE_COMPLETED, NULL},
+ {ITE_FOTA, NULL},
+ {ITE_COTA, NULL},
+ {ITE_MQTT_CONNECT_SUCC, NULL}
+};
+
+void *iotx_event_callback(int evt)
+{
+ if (evt < 0 || evt >= sizeof(g_impl_event_map) / sizeof(impl_event_map_t)) {
+ return NULL;
+ }
+ return g_impl_event_map[evt].callback;
+}
+
+DEFINE_EVENT_CALLBACK(ITE_AWSS_STATUS, int (*callback)(int))
+DEFINE_EVENT_CALLBACK(ITE_CONNECT_SUCC, int (*callback)(void))
+DEFINE_EVENT_CALLBACK(ITE_CONNECT_FAIL, int (*callback)(void))
+DEFINE_EVENT_CALLBACK(ITE_DISCONNECTED, int (*callback)(void))
+DEFINE_EVENT_CALLBACK(ITE_REDIRECT, int (*callback)(void))
+DEFINE_EVENT_CALLBACK(ITE_RAWDATA_ARRIVED, int (*callback)(const int, const unsigned char *, const int))
+DEFINE_EVENT_CALLBACK(ITE_SERVICE_REQUEST, int (*callback)(const int, const char *, const int, const char *,
+ const int, char **, int *))
+DEFINE_EVENT_CALLBACK(ITE_PROPERTY_SET, int (*callback)(const int, const char *, const int))
+#ifdef DEVICE_MODEL_SHADOW
+ DEFINE_EVENT_CALLBACK(ITE_PROPERTY_DESIRED_GET_REPLY, int (*callback)(const char *, const int))
+#endif
+DEFINE_EVENT_CALLBACK(ITE_PROPERTY_GET, int (*callback)(const int, const char *, const int, char **, int *))
+DEFINE_EVENT_CALLBACK(ITE_REPORT_REPLY, int (*callback)(const int, const int, const int, const char *,
+ const int))
+DEFINE_EVENT_CALLBACK(ITE_TRIGGER_EVENT_REPLY, int (*callback)(const int, const int, const int, const char *,
+ const int, const char *, const int))
+DEFINE_EVENT_CALLBACK(ITE_TIMESTAMP_REPLY, int (*callback)(const char *))
+DEFINE_EVENT_CALLBACK(ITE_TOPOLIST_REPLY, int (*callback)(const int, const int, const int, const char *,
+ const int))
+DEFINE_EVENT_CALLBACK(ITE_PERMIT_JOIN, int (*callback)(const char *, int))
+DEFINE_EVENT_CALLBACK(ITE_INITIALIZE_COMPLETED, int (*callback)(const int))
+DEFINE_EVENT_CALLBACK(ITE_FOTA, int (*callback)(const int, const char *))
+DEFINE_EVENT_CALLBACK(ITE_COTA, int (*callback)(const int, const char *, int, const char *,
+ const char *, const char *, const char *))
+DEFINE_EVENT_CALLBACK(ITE_MQTT_CONNECT_SUCC, int (*callback)(void))
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_compat.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_compat.h
new file mode 100644
index 00000000..acba415f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_compat.h
@@ -0,0 +1,290 @@
+#ifndef _INFRA_COMPAT_H_
+#define _INFRA_COMPAT_H_
+
+#include "infra_defs.h"
+#include "infra_list.h"
+
+#undef being_deprecated
+#define being_deprecated
+
+typedef enum _IOT_LogLevel {
+ IOT_LOG_NONE = 0,
+ IOT_LOG_CRIT,
+ IOT_LOG_ERROR,
+ IOT_LOG_WARNING,
+ IOT_LOG_INFO,
+ IOT_LOG_DEBUG,
+} IOT_LogLevel;
+
+DLL_IOT_API void IOT_SetLogLevel(IOT_LogLevel level);
+DLL_IOT_API void IOT_DumpMemoryStats(IOT_LogLevel level);
+
+/**
+ * @brief event list used for iotx_regist_event_monitor_cb
+ */
+enum iotx_event_t {
+ IOTX_AWSS_START = 0x1000, /* AWSS start without enbale, just supports device discover */
+ IOTX_AWSS_ENABLE, /* AWSS enable */
+ IOTX_AWSS_LOCK_CHAN, /* AWSS lock channel(Got AWSS sync packet) */
+ IOTX_AWSS_CS_ERR, /* AWSS AWSS checksum is error */
+ IOTX_AWSS_PASSWD_ERR, /* AWSS decrypt passwd error */
+ IOTX_AWSS_GOT_SSID_PASSWD, /* AWSS parse ssid and passwd successfully */
+ IOTX_AWSS_CONNECT_ADHA, /* AWSS try to connnect adha (device discover, router solution) */
+ IOTX_AWSS_CONNECT_ADHA_FAIL, /* AWSS fails to connect adha */
+ IOTX_AWSS_CONNECT_AHA, /* AWSS try to connect aha (AP solution) */
+ IOTX_AWSS_CONNECT_AHA_FAIL, /* AWSS fails to connect aha */
+ IOTX_AWSS_SETUP_NOTIFY, /* AWSS sends out device setup information (AP and router solution) */
+ IOTX_AWSS_CONNECT_ROUTER, /* AWSS try to connect destination router */
+ IOTX_AWSS_CONNECT_ROUTER_FAIL, /* AWSS fails to connect destination router. */
+ IOTX_AWSS_GOT_IP, /* AWSS connects destination successfully and got ip address */
+ IOTX_AWSS_SUC_NOTIFY, /* AWSS sends out success notify (AWSS sucess) */
+ IOTX_AWSS_BIND_NOTIFY, /* AWSS sends out bind notify information to support bind between user and device */
+ IOTX_AWSS_ENABLE_TIMEOUT, /* AWSS enable timeout(user needs to call awss_config_press again to enable awss) */
+ IOTX_CONN_CLOUD = 0x2000, /* Device try to connect cloud */
+ IOTX_CONN_CLOUD_FAIL, /* Device fails to connect cloud, refer to net_sockets.h for error code */
+ IOTX_CONN_CLOUD_SUC, /* Device connects cloud successfully */
+ IOTX_RESET = 0x3000, /* Linkkit reset success (just got reset response from cloud without any other operation) */
+};
+
+/**
+ * @brief register callback to monitor all event from system.
+ *
+ * @param callback, when some event occurs, the system will trigger callback to user.
+ * refer to enum iotx_event_t for event list supported.
+ *
+ * @return 0 when success, -1 when fail.
+ * @note: user should make sure that callback is not block and runs to complete fast.
+ */
+int iotx_event_regist_cb(void (*monitor_cb)(int event));
+
+/**
+ * @brief post event to trigger callback resitered by iotx_event_regist_cb
+ *
+ * @param event, event id, refer to iotx_event_t
+ *
+ * @return 0 when success, -1 when fail.
+ */
+int iotx_event_post(int event);
+
+#ifndef BUILD_AOS
+
+#ifndef VERSION_NUM_SIZE
+ #define VERSION_NUM_SIZE 4
+#endif
+
+#ifndef RANDOM_NUM_SIZE
+ #define RANDOM_NUM_SIZE 4
+#endif
+
+#ifndef MAC_ADDRESS_SIZE
+ #define MAC_ADDRESS_SIZE 8
+#endif
+
+#ifndef CHIP_CODE_SIZE
+ #define CHIP_CODE_SIZE 4
+#endif
+
+#define AOS_ACTIVE_INFO_LEN (81)
+unsigned int aos_get_version_info(unsigned char version_num[VERSION_NUM_SIZE],
+ unsigned char random_num[RANDOM_NUM_SIZE],
+ unsigned char mac_address[MAC_ADDRESS_SIZE],
+ unsigned char chip_code[CHIP_CODE_SIZE],
+ unsigned char *output_buffer,
+ unsigned int output_buffer_size);
+#endif
+
+typedef enum {
+ ITE_AWSS_STATUS,
+ ITE_CONNECT_SUCC,
+ ITE_CONNECT_FAIL,
+ ITE_DISCONNECTED,
+ ITE_REDIRECT,
+ ITE_RAWDATA_ARRIVED,
+ ITE_SERVICE_REQUEST,
+ ITE_PROPERTY_SET,
+ ITE_PROPERTY_GET,
+#ifdef DEVICE_MODEL_SHADOW
+ ITE_PROPERTY_DESIRED_GET_REPLY,
+#endif
+ ITE_REPORT_REPLY,
+ ITE_TRIGGER_EVENT_REPLY,
+ ITE_TIMESTAMP_REPLY,
+ ITE_TOPOLIST_REPLY,
+ ITE_PERMIT_JOIN,
+ ITE_INITIALIZE_COMPLETED,
+ ITE_FOTA,
+ ITE_COTA,
+ ITE_MQTT_CONNECT_SUCC
+} iotx_ioctl_event_t;
+
+#define IOT_RegisterCallback(evt, cb) iotx_register_for_##evt(cb);
+#define DECLARE_EVENT_CALLBACK(evt, cb) DLL_IOT_API int iotx_register_for_##evt(cb);
+#define DEFINE_EVENT_CALLBACK(evt, cb) DLL_IOT_API int iotx_register_for_##evt(cb) { \
+ if (evt < 0 || evt >= sizeof(g_impl_event_map)/sizeof(impl_event_map_t)) {return -1;} \
+ g_impl_event_map[evt].callback = (void *)callback;return 0;}
+
+DECLARE_EVENT_CALLBACK(ITE_AWSS_STATUS, int (*cb)(int))
+DECLARE_EVENT_CALLBACK(ITE_CONNECT_SUCC, int (*cb)(void))
+DECLARE_EVENT_CALLBACK(ITE_CONNECT_FAIL, int (*cb)(void))
+DECLARE_EVENT_CALLBACK(ITE_DISCONNECTED, int (*cb)(void))
+DECLARE_EVENT_CALLBACK(ITE_REDIRECT, int (*cb)(void))
+DECLARE_EVENT_CALLBACK(ITE_RAWDATA_ARRIVED, int (*cb)(const int, const unsigned char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_SERVICE_REQUEST, int (*cb)(const int, const char *, const int, const char *, const int,
+ char **, int *))
+DECLARE_EVENT_CALLBACK(ITE_PROPERTY_SET, int (*cb)(const int, const char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_PROPERTY_DESIRED_GET_REPLY, int (*cb)(const char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_PROPERTY_GET, int (*cb)(const int, const char *, const int, char **, int *))
+DECLARE_EVENT_CALLBACK(ITE_REPORT_REPLY, int (*cb)(const int, const int, const int, const char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_TRIGGER_EVENT_REPLY, int (*cb)(const int, const int, const int, const char *, const int,
+ const char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_TIMESTAMP_REPLY, int (*cb)(const char *))
+DECLARE_EVENT_CALLBACK(ITE_TOPOLIST_REPLY, int (*cb)(const int, const int, const int, const char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_PERMIT_JOIN, int (*cb)(const char *, const int))
+DECLARE_EVENT_CALLBACK(ITE_INITIALIZE_COMPLETED, int (*cb)(const int))
+DECLARE_EVENT_CALLBACK(ITE_FOTA, int (*cb)(const int, const char *))
+DECLARE_EVENT_CALLBACK(ITE_COTA, int (*cb)(const int, const char *, int, const char *, const char *,
+ const char *, const char *))
+DECLARE_EVENT_CALLBACK(ITE_MQTT_CONNECT_SUCC, int (*cb)(void))
+
+void *iotx_event_callback(int evt);
+
+#ifndef offset_of
+ #define offset_of aos_offsetof
+#endif
+#ifndef container_of
+ #define container_of aos_container_of
+#endif
+
+#define ALIYUN_LIST_HEAD AOS_DLIST_HEAD
+#define LIST_HEAD_INIT AOS_DLIST_INIT
+#define INIT_LIST_HEAD INIT_AOS_DLIST_HEAD
+#define ALIYUN_LIST_INIT AOS_DLIST_INIT
+
+#define list_head dlist_s
+#define list_head_t dlist_t
+
+#define list_add dlist_add
+#define list_add_tail dlist_add_tail
+#define list_del dlist_del
+#define list_empty dlist_empty
+#define list_entry_number dlist_entry_number
+#define list_first_entry dlist_first_entry
+#define list_for_each dlist_for_each
+#define list_for_each_entry_reverse dlist_for_each_entry_reverse
+#define list_for_each_safe dlist_for_each_safe
+#define list_init dlist_init
+
+#define list_for_each_entry(pos, head, member, type) \
+ dlist_for_each_entry(head, pos, type, member)
+
+#define list_for_each_entry_safe(pos, n, head, member, type) \
+ for (pos = list_entry((head)->next, type, member), \
+ n = list_entry(pos->member.next, type, member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, type, member))
+
+#define list_next_entry(pos, member, type) \
+ list_entry((pos)->member.next, type, member)
+
+static inline void list_del_init(struct list_head *entry)
+{
+ list_del(entry);
+ INIT_LIST_HEAD(entry);
+}
+
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+typedef struct {
+ uint16_t port;
+ uint8_t init;
+ char *host_name;
+ char *client_id;
+ char *username;
+ char *password;
+ const char *pub_key;
+} iotx_conn_info_t, *iotx_conn_info_pt;
+
+int IOT_SetupConnInfo(const char *product_key,
+ const char *device_name,
+ const char *device_secret,
+ void **info_ptr);
+
+typedef struct {
+ int domain_type;
+ int dynamic_register;
+ char *cloud_custom_domain;
+ char *http_custom_domain;
+} sdk_impl_ctx_t;
+
+typedef enum {
+ IOTX_IOCTL_SET_REGION, /* value(int*): iotx_cloud_region_types_t */
+ IOTX_IOCTL_GET_REGION, /* value(int*) */
+ IOTX_IOCTL_SET_MQTT_DOMAIN, /* value(const char*): point to mqtt domain string */
+ IOTX_IOCTL_SET_HTTP_DOMAIN, /* value(const char*): point to http domain string */
+ IOTX_IOCTL_SET_DYNAMIC_REGISTER, /* value(int*): 0 - Disable Dynamic Register, 1 - Enable Dynamic Register */
+ IOTX_IOCTL_GET_DYNAMIC_REGISTER, /* value(int*) */
+ IOTX_IOCTL_RECV_PROP_REPLY, /* value(int*): 0 - Disable property post reply by cloud; 1 - Enable property post reply by cloud */
+ IOTX_IOCTL_RECV_EVENT_REPLY, /* value(int*): 0 - Disable event post reply by cloud; 1 - Enable event post reply by cloud */
+ IOTX_IOCTL_SEND_PROP_SET_REPLY, /* value(int*): 0 - Disable send post set reply by devid; 1 - Enable property set reply by devid */
+ IOTX_IOCTL_SET_SUBDEV_SIGN, /* value(const char*): only for slave device, set signature of subdevice */
+ IOTX_IOCTL_GET_SUBDEV_LOGIN, /* value(int*): 0 - SubDev is logout; 1 - SubDev is login */
+ IOTX_IOCTL_SET_OTA_DEV_ID /* value(int*): select the device to do OTA according to devid */
+} iotx_ioctl_option_t;
+
+typedef enum {
+ IMPL_LINKKIT_IOCTL_SWITCH_PROPERTY_POST_REPLY, /* only for master device, choose whether you need receive property post reply message */
+ IMPL_LINKKIT_IOCTL_SWITCH_EVENT_POST_REPLY, /* only for master device, choose whether you need receive event post reply message */
+ IMPL_LINKKIT_IOCTL_SWITCH_PROPERTY_SET_REPLY, /* only for master device, choose whether you need send property set reply message */
+ IMPL_LINKKIT_IOCTL_MAX
+} impl_linkkit_ioctl_cmd_t;
+
+/**
+ * @brief Setup Demain type, should be called before MQTT connection.
+ *
+ * @param [in] option: see iotx_ioctl_option_t.
+ *
+ * @return None.
+ * @see None.
+ */
+int IOT_Ioctl(int option, void *data);
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+#endif
+
+/* compatible for V2.3.0 */
+#define IOTX_CLOUD_DOMAIN_SH IOTX_CLOUD_REGION_SHANGHAI
+#define IOTX_CLOUD_DOMAIN_SG IOTX_CLOUD_REGION_SINGAPORE
+#define IOTX_CLOUD_DOMAIN_JP IOTX_CLOUD_REGION_JAPAN
+#define IOTX_CLOUD_DOMAIN_US IOTX_CLOUD_REGION_USA_WEST
+#define IOTX_CLOUD_DOMAIN_GER IOTX_CLOUD_REGION_GERMANY
+#define IOTX_IOCTL_SET_DOMAIN IOTX_IOCTL_SET_REGION
+#define IOTX_IOCTL_GET_DOMAIN IOTX_IOCTL_GET_REGION
+
+#define IOT_OpenLog(arg)
+#define IOT_CloseLog() IOT_SetLogLevel(IOT_LOG_NONE)
+#define IOT_LOG_EMERG IOT_LOG_NONE
+
+#define IOT_Linkkit_Post IOT_Linkkit_Report
+/* compatible for V2.3.0 end */
+
+typedef enum {
+ HAL_AES_ENCRYPTION = 0,
+ HAL_AES_DECRYPTION = 1,
+} AES_DIR_t;
+
+typedef void *p_HAL_Aes128_t;
+
+#define NETWORK_ADDR_LEN (16)
+
+typedef struct _network_addr_t {
+ unsigned char
+ addr[NETWORK_ADDR_LEN];
+ unsigned short port;
+} NetworkAddr;
+
+#endif /* _INFRA_COMPAT_H_ */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_config.h
new file mode 100644
index 00000000..8e57a8eb
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_config.h
@@ -0,0 +1,84 @@
+#ifndef _INFRA_CONFIG_H_
+#define _INFRA_CONFIG_H_
+
+#include "sdkconfig.h"
+
+#define PLATFORM_HAS_STDINT
+#define PLATFORM_HAS_DYNMEM
+#define PLATFORM_HAS_OS
+#define INFRA_STRING
+#define INFRA_NET
+#define INFRA_LIST
+//#define INFRA_LOG_NETWORK_PAYLOAD
+#define INFRA_LOG
+//#define INFRA_LOG_ALL_MUTED
+//#define INFRA_LOG_MUTE_FLW
+//#define INFRA_LOG_MUTE_DBG
+//#define INFRA_LOG_MUTE_INF
+//#define INFRA_LOG_MUTE_WRN
+//#define INFRA_LOG_MUTE_ERR
+//#define INFRA_LOG_MUTE_CRT
+#define INFRA_TIMER
+#define INFRA_JSON_PARSER
+#define INFRA_CJSON
+#define INFRA_MD5
+#define INFRA_SHA1
+#define INFRA_SHA256
+#define INFRA_REPORT
+#define INFRA_HTTPC
+#define INFRA_COMPAT
+#define INFRA_CLASSIC
+#define DEV_SIGN
+#define MQTT_COMM_ENABLED
+#define MQTT_DEFAULT_IMPL
+#if CONFIG_MQTT_DIRECT
+#define MQTT_DIRECT
+#else
+#define MQTT_PRE_AUTH
+#define INFRA_PREAUTH
+#endif
+#define DEVICE_MODEL_CLASSIC
+//#define LOG_REPORT_TO_CLOUD
+#define DEVICE_MODEL_ENABLED
+#if CONFIG_DEVICE_MODEL_GATEWAY
+#define DEVICE_MODEL_GATEWAY
+#endif
+#if CONFIG_DEVICE_ALCS_ENABLE
+#define ALCS_ENABLED
+#endif
+#if CONFIG_DYNAMIC_REGISTER
+#define DYNAMIC_REGISTER
+#endif
+#define DEVICE_MODEL_SUBDEV_OTA
+#define DEVICE_MODEL_SHADOW
+#define HAL_KV
+#define SUPPORT_TLS
+#if defined(SUPPORT_TLS) && CONFIG_SUPPORT_TCP
+#define SUPPORT_TCP
+#endif
+#define HAL_CRYPTO
+#define HAL_UDP
+//#define COAP_DTLS_SUPPORT
+#define OTA_ENABLED
+//#define COAP_COMM_ENABLED
+#define COAP_PACKET
+#define COAP_CLIENT
+#define COAP_SERVER
+#define DEV_RESET
+#define HTTP_COMM_ENABLED
+#define HTTP2_COMM_ENABLED
+#define FS_ENABLED
+#define AWSS_SUPPORT_APLIST
+#define AWSS_SUPPORT_ADHA
+#define AWSS_FRAMEWORKS
+#define WIFI_PROVISION_ENABLED
+#define AWSS_SUPPORT_SMARTCONFIG_WPS
+#define AWSS_SUPPORT_SMARTCONFIG
+#define AWSS_SUPPORT_ZEROCONFIG
+#define AWSS_SUPPORT_AHA
+#define AWSS_SUPPORT_DEV_AP
+#define DEV_BIND_ENABLED
+#ifdef CONFIG_SUPPORT_SECURITY_OTA
+#define SUPPORT_SECURITY_OTA
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_defs.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_defs.c
new file mode 100644
index 00000000..45d97ca0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_defs.c
@@ -0,0 +1,23 @@
+
+#include "infra_config.h"
+#include "infra_types.h"
+#include "infra_defs.h"
+
+const char * g_infra_mqtt_domain[IOTX_MQTT_DOMAIN_NUMBER] = {
+ "iot-as-mqtt.cn-shanghai.aliyuncs.com", /* Shanghai */
+ "iot-as-mqtt.ap-southeast-1.aliyuncs.com", /* Singapore */
+ "iot-as-mqtt.ap-northeast-1.aliyuncs.com", /* Japan */
+ "iot-as-mqtt.us-west-1.aliyuncs.com", /* America */
+ "iot-as-mqtt.eu-central-1.aliyuncs.com", /* Germany */
+ NULL, /* Custom */
+};
+
+const char *g_infra_http_domain[IOTX_HTTP_DOMAIN_NUMBER] = {
+ "iot-auth.cn-shanghai.aliyuncs.com", /* Shanghai */
+ "iot-auth.ap-southeast-1.aliyuncs.com", /* Singapore */
+ "iot-auth.ap-northeast-1.aliyuncs.com", /* Japan */
+ "iot-auth.us-west-1.aliyuncs.com", /* America */
+ "iot-auth.eu-central-1.aliyuncs.com", /* Germany */
+ NULL, /* Custom */
+};
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_defs.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_defs.h
new file mode 100644
index 00000000..c5fa12f5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_defs.h
@@ -0,0 +1,356 @@
+#ifndef _INFRA_DEFS_H_
+#define _INFRA_DEFS_H_
+
+#include "infra_types.h"
+
+#ifdef _WIN32
+ #if !defined(CC_IS_MINGW32)
+ #ifdef DLL_HAL_EXPORTS
+ #define DLL_HAL_API __declspec(dllexport)
+ #else
+ #define DLL_HAL_API __declspec(dllimport)
+ #endif
+ #else
+ #define DLL_HAL_API
+ #endif
+#else
+ #define DLL_HAL_API
+#endif
+
+#ifdef _WIN32
+ #if !defined(CC_IS_MINGW32)
+ #ifdef DLL_IOT_EXPORTS
+ #define DLL_IOT_API __declspec(dllexport)
+ #else
+ #define DLL_IOT_API __declspec(dllimport)
+ #endif
+ #else
+ #define DLL_IOT_API
+ #endif
+#else
+ #define DLL_IOT_API
+#endif
+
+#define IOTX_SDK_VERSION "3.0.1"
+#define IOTX_ALINK_VERSION "20"
+#define IOTX_FIRMWARE_VERSION_LEN (32)
+#define IOTX_PRODUCT_KEY_LEN (20)
+#define IOTX_DEVICE_NAME_LEN (32)
+#define IOTX_DEVICE_SECRET_LEN (64)
+#define IOTX_DEVICE_ID_LEN (64)
+#define IOTX_PRODUCT_SECRET_LEN (64)
+#define IOTX_PARTNER_ID_LEN (64)
+#define IOTX_MODULE_ID_LEN (64)
+#define IOTX_NETWORK_IF_LEN (160)
+#define IOTX_FIRMWARE_VER_LEN (32)
+#define IOTX_URI_MAX_LEN (135)
+
+#ifndef _IN_
+ #define _IN_
+#endif
+
+#ifndef _OU_
+ #define _OU_
+#endif
+
+#ifndef _IN_OPT_
+ #define _IN_OPT_
+#endif
+
+#define NETWORK_ADDR_LEN (16)
+#define HAL_MAC_LEN (17 + 1) /* MAC地址的长度 */
+#define STR_SHORT_LEN (32)
+#ifndef ETH_ALEN
+#define ETH_ALEN (6)
+#endif
+#define HAL_MAX_SSID_LEN (32 + 1) /* ssid: 32 octets at most, include the NULL-terminated */
+#define HAL_MAX_PASSWD_LEN (64 + 1) /* password: 8-63 ascii */
+#define WLAN_CONNECTION_TIMEOUT_MS (30 * 1000)
+
+typedef enum IOT_RETURN_CODES {
+ ERROR_DEVICE_NOT_EXIST = -311,
+ ERROR_NET_TIMEOUT = -310,
+ ERROR_CERT_VERIFY_FAIL = -309,
+ ERROR_NET_SETOPT_TIMEOUT = -308,
+ ERROR_NET_SOCKET = -307,
+ ERROR_NET_CONNECT = -306,
+ ERROR_NET_BIND = -305,
+ ERROR_NET_LISTEN = -304,
+ ERROR_NET_RECV = -303,
+ ERROR_NET_SEND = -302,
+ ERROR_NET_CONN = -301,
+ ERROR_NET_UNKNOWN_HOST = -300,
+
+ MQTT_SUBHANDLE_LIST_LEN_TOO_SHORT = -47,
+ MQTT_OFFLINE_LIST_LEN_TOO_SHORT = -46,
+ MQTT_TOPIC_LEN_TOO_SHORT = -45,
+ MQTT_CONNECT_BLOCK = -44,
+ MQTT_SUB_INFO_NOT_FOUND_ERROR = -43,
+ MQTT_PUSH_TO_LIST_ERROR = -42,
+ MQTT_TOPIC_FORMAT_ERROR = -41,
+ NETWORK_RECONNECT_TIMED_OUT_ERROR = -40,/** Returned when the Network is disconnected and the reconnect attempt has timed out */
+ MQTT_CONNACK_UNKNOWN_ERROR = -39,/** Connect request failed with the server returning an unknown error */
+ MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -38,/** Connect request failed with the server returning an unacceptable protocol version error */
+ MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -37,/** Connect request failed with the server returning an identifier rejected error */
+ MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = -36,/** Connect request failed with the server returning an unavailable error */
+ MQTT_CONNACK_BAD_USERDATA_ERROR = -35,/** Connect request failed with the server returning a bad userdata error */
+ MQTT_CONNACK_NOT_AUTHORIZED_ERROR = -34,/** Connect request failed with the server failing to authenticate the request */
+ MQTT_CONNECT_ERROR = -33,
+ MQTT_CREATE_THREAD_ERROR = -32,
+ MQTT_PING_PACKET_ERROR = -31,
+ MQTT_CONNECT_PACKET_ERROR = -30,
+ MQTT_CONNECT_ACK_PACKET_ERROR = -29,
+ MQTT_NETWORK_CONNECT_ERROR = -28,
+ MQTT_STATE_ERROR = -27,
+ MQTT_SUBSCRIBE_PACKET_ERROR = -26,
+ MQTT_SUBSCRIBE_ACK_PACKET_ERROR = -25,
+ MQTT_SUBSCRIBE_ACK_FAILURE = -24,
+ MQTT_SUBSCRIBE_QOS_ERROR = -23,
+ MQTT_UNSUBSCRIBE_PACKET_ERROR = -22,
+ MQTT_PUBLISH_PACKET_ERROR = -21,
+ MQTT_PUBLISH_QOS_ERROR = -20,
+ MQTT_PUBLISH_ACK_PACKET_ERROR = -19,
+ MQTT_PUBLISH_COMP_PACKET_ERROR = -18,
+ MQTT_PUBLISH_REC_PACKET_ERROR = -17,
+ MQTT_PUBLISH_REL_PACKET_ERROR = -16,
+ MQTT_UNSUBSCRIBE_ACK_PACKET_ERROR = -15,
+ MQTT_NETWORK_ERROR = -14,
+ MQTT_PUBLISH_ACK_TYPE_ERROR = -13,
+
+ ERROR_SHADOW_NO_METHOD = -2008,
+ ERROR_SHADOW_UNDEF_TYPE = -2007,
+ ERROR_SHADOW_UPDATE_TIMEOUT = -2006,
+ ERROR_SHADOW_UPDATE_NACK = -2005, /**< Negative ACK */
+ ERROR_SHADOW_NO_ATTRIBUTE = -2004,
+ ERROR_SHADOW_ATTR_NO_EXIST = -2003, /**< NO such attribute */
+ ERROR_SHADOW_ATTR_EXIST = -2002, /**< attribute already exists */
+ ERROR_SHADOW_WAIT_LIST_OVERFLOW = -2001,
+ ERROR_SHADOW_INVALID_STATE = -2000,
+
+ ERROR_SUBDEV_NULL_VALUE = -1501, /**< Indicating NULL value*/
+ ERROR_SUBDEV_NOT_NULL_VALUE = -1500, /**< Indicating value not NULL*/
+ ERROR_SUBDEV_STRING_NULL_VALUE = -1499, /**< Indicating NULL value or empty string */
+ ERROR_SUBDEV_INVALID_GATEWAY_HANDLE = -1498, /**< Indicating gateway handle is null or invalid*/
+ ERROR_SUBDEV_SESSION_NOT_FOUND = -1497, /**< Cannot find device session*/
+ ERROR_SUBDEV_RRPC_CB_NOT_NULL = -1496, /**< RRPC callback function has been set,needn't to set again*/
+ ERROR_SUBDEV_REPLY_TYPE_NOT_DEF = -1495, /**< Reply type not defined*/
+ ERROR_SUBDEV_GET_JSON_VAL = -1494, /**< Get value from reply payload fail*/
+ ERROR_SUBDEV_DATA_LEN_OVERFLOW = -1493, /**< Length of 'data' value from reply palyoad is large than limit(1024)*/
+ ERROR_SUBDEV_MSG_LEN = -1492, /**< Indicating msg len is not correct*/
+ ERROR_SUBDEV_REPLY_PROC = -1491, /**< Error occur when process publish reply */
+ ERROR_SUBDEV_REPLY_TOPIC_NOT_MATCH = -1490, /**< Indicating that topic received is unknown*/
+ ERROR_SUBDEV_REPLY_VAL_CHECK = -1489, /**< Indicating that value get from reply checked fail with local*/
+ ERROR_SUBDEV_REGISTER_TYPE_NOT_DEF = -1488, /**< Register type not support*/
+ ERROR_SUBDEV_PACKET_SPLICE_FAIL = -1487, /**< Splice packet error*/
+ ERROR_SUBDEV_MQTT_PUBLISH_FAIL = -1486, /**< MQTT publish fail*/
+ ERROR_SUBDEV_REPLY_PARSE_FAIL = -1485, /**< Parse reply fail*/
+ ERROR_SUBDEV_CREATE_SESSION_FAIL = -1484, /**< Create session fail*/
+ ERROR_SUBDEV_INVALID_CLEAN_SESSION_TYPE = -1483, /**< Clean session not support*/
+ ERROR_SUBDEV_HAS_BEEN_LOGIN = -1482, /**< Device has been login*/
+ ERROR_SUBDEV_SUB_UNSUB_FAIL = -1481, /**< subscribe or unsubscribe fail*/
+ ERROR_SUBDEV_SESSION_STATE_FAIL = -1480, /**< Session state is error,may not login*/
+ ERROR_SUBDEV_MEMORY_NOT_ENOUGH = -1479, /**< Set memory too small*/
+
+ ERROR_REPLY_TIMEOUT = -6099, /**< recieve reply timeout*/
+ ERROR_DEVICE_NOT_FOUND = -6100, /**< device not found*/
+ ERROR_TOO_LARGE_PAGE_SIZE = -6101, /**< page size must less than 200*/
+ ERROR_DEVICE_COUNT_FAULT = -6102, /**< device count query service fault*/
+ ERROR_DEVICE_DETAIL_FAULT = -6103, /**< device detail query service fault*/
+ ERROR_TOO_LARGE_LIST_SIZE = -6104, /**< list size must less than 200*/
+ ERROR_LIST_SIZE_CANNOT_BE_ZERO = -6105, /**< list size must greater than 0*/
+ ERROR_TOO_LARGE_MAP_SIZE = -6106, /**< map size must less than 200*/
+ ERROR_MAP_SIZE_CANNOT_BE_ZERO = -6107, /**< map size must greater than 0*/
+ ERROR_DEVICE_STATUS_FAULT = -6108, /**< device status query service fault*/
+ ERROR_DEVICE_INFO_FAULT = -6109, /**< device info query service fault*/
+ ERROR_SET_THING_PROPERTIES_ERROR = -6150, /**< set thing properties error*/
+ ERROR_INVOKE_THING_SERVICE_ERROR = -6151, /**< invoke thing service error*/
+ ERROR_SCRIPT_REL_NOT_EXIST = -6200, /**< script relation not exist*/
+ ERROR_SCRIPT_CONVERT_DATA_IS_NULL = -6201, /**< script convert data is null*/
+ ERROR_DEVICE_PRODUCT_NOT_EXIST = -6202, /**< product not exist*/
+ ERROR_TOPIC_NOT_EXIST = -6203, /**< topic not exist*/
+ ERROR_DEVICE_IS_DISABLED = -6204, /**< device is disabled*/
+ ERROR_IOT_MESSAGE_ERROR = -6205, /**< iot message service error*/
+ ERROR_PRODUCT_PROPERTY_NOT_EXIST = -6206, /**< product property not exist*/
+ ERROR_DATA_FORMAT_ERROR = -6207, /**< device data format is error*/
+ ERROR_THING_STATUS_PROHIBITED = -6208, /**< thing status is prohibited*/
+ ERROR_THING_STATUS_NOT_ACTIVE = -6209, /**< thing status not active*/
+ /**
+ *
+ * -6250 ~ -6299
+ */
+ ERROR_PRODUCT_NOT_FOUND = -6250, /**< product not found*/
+ ERROR_DEVICE_EXISTS = -6251, /**< device has existed*/
+ ERROR_JUDGE_DEVICE_EXISTS_ERROR = -6252, /**< judge device exists error*/
+ ERROR_ADD_DEVICE_FAILED = -6253, /**< add device failed*/
+ ERROR_UPDATE_DEVICE_FAILED = -6254, /**< update device failed*/
+ ERROR_INSERT_DGR_FAILED = -6255, /**< insert device group relation failed*/
+ ERROR_SYN_DEVICE_FAILED = -6256, /**< device synchronization failed*/
+ ERROR_PRODUCT_DOMAIN_ILLEGAL = -6257, /**< product domain illegal*/
+ ERROR_TENANID_ILLEGAL = -6258, /**< tenantId illegal*/
+ ERROR_PRODUCT_REGION_ILLEGAL = -6259, /**< product region illegal*/
+ ERROR_PRODUCT_NETTYPE_ILLEGAL = -6260, /**< product nettype illegal*/
+ ERROR_INSERT_DEVICE_APPLY_DETAIL_FAILED = -6261, /**< insert device apply detail failed*/
+ ERROR_UPDATE_DEVICE_APPLY_STATUS_FAILED = -6262, /**< update device apply status failed*/
+ ERROR_DELERE_DGR_FAILED = -6263, /**< delete device group relation status*/
+ ERROR_DELETE_DEVICE_FAILED = -6264, /**< delete device failed*/
+ ERROR_QUERY_DEVICE_DETAIL_FAILED = -6265, /**< query device detail failed*/
+ ERROR_QUERY_DEVICE_COUNT_FAILED = -6266, /**< query device count failed*/
+ ERROR_QUERY_ACTIVE_DEVICE_COUNT_FAILED = -6267, /**< query active device count failed*/
+ ERROR_INSERT_AGR_FAILED = -6268, /**< insert apply group relation failed*/
+ ERROR_QUERY_DEVICE_APPLY_FAILED = -6269, /**< query device apply failed*/
+ ERROR_QUERY_PRODUCT_FAILED = -6270, /**< query product failed*/
+ ERROR_DEVICE_APPLY_NOT_FOUND = -6271, /**< device apply not found*/
+ ERROR_RELEASE_TRIAD_FAILED = -6272, /**< release triad failed*/
+ ERROR_UPDATE_DAD_STATUS_FAILED = -6273, /**< update device apply detail status failed*/
+ ERROR_REG_LORA_DEVICE_FAILED = -6274, /**< register lora device failed*/
+ ERROR_SYN_APPLY_DEVICE_FAILED = -6275, /**< device apply synchronization failed*/
+ ERROR_QUERY_DGR_FAILED = -6276, /**< query device group relation failed*/
+ ERROR_JUDGE_DGR_FAILED = -6277, /**< judge device group relation failed*/
+ ERROR_QUERY_AGR_FAILED = -6278, /**< query apply group relation failed*/
+ ERROR_JUDGE_AGR_FAILED = -6279, /**< judge apply group relation failed*/
+ ERROR_DEVICENAME_NOT_MEET_SPECS = -6280, /**< devicename not meet specs*/
+ ERROR_DELETE_APPLY_DEVICE_FAILED = -6281, /**< delete apply device failed*/
+ ERROR_GEN_DEVICEID_FAILED = -6282, /**< gennerate deviceId failed*/
+ ERROR_APPLY_ILLEGAL = -6283, /**< apply illegal*/
+ ERROR_LORA_DEVICE_METHOD_ERROR = -6284, /**< lora device cannot created by num*/
+ ERROR_APPLY_NOT_READY = -6285, /**< apply not ready*/
+
+
+ /**
+ * dsl
+ * -6300 ~ -6349
+ */
+ ERROR_DSL_PARSE_METHOD_NOT_EXIST = -6300, /**< dsl parse: method not exist*/
+ ERROR_DSL_PARSE_PARAMS_FORMAT_ERROR = -6301, /**< dsl parse: params format must be JSONObject/JSONArray*/
+ ERROR_DSL_PARSE_PARAMS_VALUE_EMPTY = -6302, /**< dsl parse: params value empty*/
+ ERROR_DSL_PARSE_PARAMS_NUMBER_ERROR = -6303, /**< dsl parse: params number error*/
+ ERROR_DSL_PARSE_PARAMS_NOT_EXIST = -6304, /**< dsl parse: params not exist*/
+ ERROR_DSL_PARSE_PARAMS_TYPE_ERROR = -6305, /**< dsl parse: params type error*/
+ ERROR_DSL_PARSE_INT_SPECS_ERROR = -6306, /**< dsl parse: int specs error*/
+ ERROR_DSL_PARSE_FLOAT_SPECS_ERROR = -6307, /**< dsl parse: float specs error*/
+ ERROR_DSL_PARSE_BOOL_SPECS_ERROR = -6308, /**< dsl parse: bool specs error*/
+ ERROR_DSL_PARSE_ENUM_SPECS_ERROR = -6309, /**< dsl parse: enum specs error*/
+ ERROR_DSL_PARSE_STRING_SPECS_ERROR = -6310, /**< dsl parse: string specs error*/
+ ERROR_DSL_PARSE_DATE_SPECS_ERROR = -6311, /**< dsl parse: date specs error*/
+ ERROR_DSL_PARSE_STRUCT_SPECS_ERROR = -6312, /**< dsl parse: struct specs error*/
+ ERROR_DSL_SERVICE_NOT_AVAILABLE = -6313, /**< dsl service not available*/
+ ERROR_DSL_PARSE_DATA_TYPE_PARSE_ERROR = -6314, /**< dsl parse: data type parse error*/
+ ERROR_DATA_NOT_SATISFY_DSL = -6315, /**< dsl parse: data not satisfy dsl*/
+ ERROR_DSL_PARSE_SPECS_NUMBER_FORMAT_ERROR = -6316, /**< dsl parse: specs number format error*/
+ ERROR_DSL_PARSE_TEMPLATE_ERROR = -6317, /**< dsl parse: template error*/
+ ERROR_DSL_EXCEPTION = -6318, /**< dsl exception*/
+ ERROR_DSL_PARSE_EVENT_CALL_TYPE_ERROR = -6319, /**< dsl parse: event call type error*/
+ ERROR_DSL_PARSE_NO_PROPERTY = -6320, /**< dsl parse: no property exist in product*/
+ ERROR_DSL_PARSE_IDENTIFIER_IS_NULL = -6321, /**< dsl parse: template property/params idetifier is null*/
+ ERROR_DSL_DEVICE_NOT_EXIST_IN_PRODUCT = -6321, /**< dsl: device not exist in product*/
+ ERROR_DSL_PARSE_DOUBLE_SPECS_ERROR = -6322, /**< dsl parse: double specs error*/
+
+ /**
+ *
+ * -6350 ~ -6399
+ */
+ ERROR_EVENT_PUT_ERROR = -6350, /**< thing event put error*/
+ ERROR_SERVICE_PUT_ERROR = -6351, /**< thing service put error*/
+ ERROR_DEVICE_GET_EVENT_FAULT = -6352, /**< thing event get error*/
+ ERROR_PRODUCT_KEY_ELEMENT_ALREADY_EXIST = -6353, /**< product key element already exist*/
+
+ /**
+ *
+ * -6400 ~ -6449
+ */
+ ERROR_TOPO_RELATION_COUNT_EXCEED = -6400, /**< topo relation count exceed*/
+ ERROR_TOPO_RELATION_NOT_EXIST = -6401, /**< topo relation not exist*/
+ ERROR_TOPO_RELATION_CANNOT_ADD_BYSELF = -6402, /**< topo relation cannot add by self*/
+
+ /**
+ * alink
+ * -6450 ~ -6469
+ */
+ ERROR_ALINK_METHOD_NOT_EXIST = -6450, /**< alink method not exist*/
+
+ /**
+ *
+ * -6550 ~ -6599
+ */
+ ERROR_DEVICE_GROUP_NOT_FOUND = -6550, /**< device group not found*/
+
+ /**
+ * @brief dev_sign
+ *
+ * -1100 ~ -1200
+ *
+ */
+ ERROR_DEV_SIGN_CUSTOM_DOMAIN_IS_NULL = -1105,
+ ERROR_DEV_SIGN_SOURCE_TOO_SHORT = -1104,
+ ERROR_DEV_SIGN_PASSWORD_TOO_SHORT = -1103,
+ ERROR_DEV_SIGN_USERNAME_TOO_SHORT = -1102,
+ ERROR_DEV_SIGN_CLIENT_ID_TOO_SHORT = -1101,
+ ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT = -1100,
+
+ ERROR_NO_MEM = -1016,
+ ERROR_CERTIFICATE_EXPIRED = -1015,
+ ERROR_MALLOC = -1014,
+ ERROR_NO_ENOUGH_MEM = -1013, /**< Writes more than size value. */
+
+ ERROR_NO_SUPPORT = -12,
+ ERROR_NO_PERSISTENCE = -11,
+ ERROR_HTTP_BREAK = -10,
+ ERROR_NULL_VALUE = -9,
+ ERROR_HTTP_CONN = -8, /**< Connection failed. */
+ ERROR_HTTP_PARSE = -7, /**< A URL parse error occurred. */
+ ERROR_HTTP_UNRESOLVED_DNS = -6, /**< Could not resolve the hostname. */
+ ERROR_HTTP_PRTCL = -5, /**< A protocol error occurred. */
+ ERROR_HTTP = -4, /**< An unknown error occurred. */
+ ERROR_HTTP_CLOSED = -3, /**< Connection was closed by a remote host. */
+ NULL_VALUE_ERROR = -2,
+
+ FAIL_RETURN = -1, /**< generic error. */
+ SUCCESS_RETURN = 0,
+
+
+ /* @value > 0, reserved for other usage */
+
+} iotx_err_t;
+
+typedef struct _iotx_dev_meta_info {
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1];
+ char product_secret[IOTX_PRODUCT_SECRET_LEN + 1];
+ char device_name[IOTX_DEVICE_NAME_LEN + 1];
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
+} iotx_dev_meta_info_t;
+
+typedef struct {
+ const char *region;
+ uint16_t port;
+} iotx_region_item_t;
+
+typedef enum {
+ IOTX_CLOUD_REGION_SHANGHAI, /* Shanghai */
+ IOTX_CLOUD_REGION_SINGAPORE, /* Singapore */
+ IOTX_CLOUD_REGION_JAPAN, /* Japan */
+ IOTX_CLOUD_REGION_USA_WEST, /* America */
+ IOTX_CLOUD_REGION_GERMANY, /* Germany */
+ IOTX_CLOUD_REGION_CUSTOM, /* Custom setting */
+ IOTX_CLOUD_DOMAIN_MAX /* Maximum number of domain */
+} iotx_mqtt_region_types_t;
+
+#define IOTX_MQTT_DOMAIN_NUMBER (6)
+extern const char *g_infra_mqtt_domain[IOTX_MQTT_DOMAIN_NUMBER];
+
+typedef enum {
+ IOTX_HTTP_REGION_SHANGHAI, /* Shanghai */
+ IOTX_HTTP_REGION_SINGAPORE, /* Singapore */
+ IOTX_HTTP_REGION_JAPAN, /* Japan */
+ IOTX_HTTP_REGION_AMERICA, /* America */
+ IOTX_HTTP_REGION_GERMANY, /* Germany */
+ IOTX_HTTP_REGION_CUSTOM, /* Custom setting */
+ IOTX_HTTP_REGION_MAX /* Maximum number of domain */
+} iotx_http_region_types_t;
+
+#define IOTX_HTTP_DOMAIN_NUMBER (6)
+extern const char *g_infra_http_domain[IOTX_HTTP_DOMAIN_NUMBER];
+
+#endif
+
+extern int iotx_facility_json_print(const char *str, int level, ...);
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_httpc.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_httpc.c
new file mode 100644
index 00000000..19e893ca
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_httpc.c
@@ -0,0 +1,587 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_HTTPC
+
+#include
+#include
+#include
+
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_httpc.h"
+#include "infra_net.h"
+#include "infra_timer.h"
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define httpc_err(...) log_err("httpc", __VA_ARGS__)
+ #define httpc_info(...) log_info("httpc", __VA_ARGS__)
+ #define httpc_debug(...) log_debug("httpc", __VA_ARGS__)
+#else
+ #define httpc_err(...)
+ #define httpc_info(...)
+ #define httpc_debug(...)
+#endif
+
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+void HAL_SleepMs(uint32_t ms);
+
+#define HTTPCLIENT_MIN(x,y) (((x)<(y))?(x):(y))
+#define HTTPCLIENT_MAX(x,y) (((x)>(y))?(x):(y))
+
+
+#define HTTPCLIENT_READ_BUF_SIZE (1024) /* read payload */
+#define HTTPCLIENT_RAED_HEAD_SIZE (32) /* read header */
+#define HTTPCLIENT_SEND_BUF_SIZE (1024) /* send */
+
+#define HTTPCLIENT_MAX_URL_LEN (256)
+
+#define HTTP_RETRIEVE_MORE_DATA (1) /**< More data needs to be retrieved. */
+
+#if defined(MBEDTLS_DEBUG_C)
+ #define DEBUG_LEVEL 2
+#endif
+#define HTTPCLIENT_CHUNK_SIZE (1024)
+
+static int _utils_parse_url(const char *url, char *host, char *path);
+static int _http_recv(httpclient_t *client, char *buf, int max_len, int *p_read_len,
+ uint32_t timeout);
+static int _http_get_response_body(httpclient_t *client, char *data, int len, uint32_t timeout,
+ httpclient_data_t *client_data);
+static int _http_parse_response_header(httpclient_t *client, char *data, int len, uint32_t timeout,
+ httpclient_data_t *client_data);
+
+static int _utils_parse_url(const char *url, char *host,
+ char *path)
+{
+ char *host_ptr = (char *) strstr(url, "://");
+ uint32_t host_len = 0;
+ uint32_t path_len;
+ /* char *port_ptr; */
+ char *path_ptr;
+ char *fragment_ptr;
+
+ if (host_ptr == NULL) {
+ return -1; /* URL is invalid */
+ }
+ host_ptr += 3;
+
+ path_ptr = strchr(host_ptr, '/');
+ if (NULL == path_ptr) {
+ return -2;
+ }
+
+ if (host_len == 0) {
+ host_len = path_ptr - host_ptr;
+ }
+
+ memcpy(host, host_ptr, host_len);
+ host[host_len] = '\0';
+ fragment_ptr = strchr(host_ptr, '#');
+ if (fragment_ptr != NULL) {
+ path_len = fragment_ptr - path_ptr;
+ } else {
+ path_len = strlen(path_ptr);
+ }
+
+ memcpy(path, path_ptr, path_len);
+ path[path_len] = '\0';
+
+ return SUCCESS_RETURN;
+}
+
+static int _utils_fill_tx_buffer(httpclient_t *client, char *send_buf, int *send_idx, char *buf,
+ uint32_t len) /* 0 on success, err code on failure */
+{
+ int ret;
+ int cp_len;
+ int idx = *send_idx;
+
+ if (len == 0) {
+ len = strlen(buf);
+ }
+ do {
+ if ((HTTPCLIENT_SEND_BUF_SIZE - idx) >= len) {
+ cp_len = len;
+ } else {
+ cp_len = HTTPCLIENT_SEND_BUF_SIZE - idx;
+ }
+
+ memcpy(send_buf + idx, buf, cp_len);
+ idx += cp_len;
+ len -= cp_len;
+
+ if (idx == HTTPCLIENT_SEND_BUF_SIZE) {
+ ret = client->net.write(&client->net, send_buf, HTTPCLIENT_SEND_BUF_SIZE, 5000);
+ if (ret) {
+ return (ret);
+ }
+ }
+ } while (len);
+
+ *send_idx = idx;
+ return SUCCESS_RETURN;
+}
+
+static int _http_send_header(httpclient_t *client, const char *host, const char *path, int method,
+ httpclient_data_t *client_data)
+{
+ int len;
+ char send_buf[HTTPCLIENT_SEND_BUF_SIZE] = { 0 };
+ char buf[HTTPCLIENT_SEND_BUF_SIZE] = { 0 };
+ char *meth = (method == HTTPCLIENT_GET) ? "GET" : (method == HTTPCLIENT_POST) ? "POST" :
+ (method == HTTPCLIENT_PUT) ? "PUT" : (method == HTTPCLIENT_DELETE) ? "DELETE" :
+ (method == HTTPCLIENT_HEAD) ? "HEAD" : "";
+ int ret;
+
+ /* Send request */
+ memset(send_buf, 0, HTTPCLIENT_SEND_BUF_SIZE);
+ len = 0; /* Reset send buffer */
+
+ HAL_Snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); /* Write request */
+
+ ret = _utils_fill_tx_buffer(client, send_buf, &len, buf, strlen(buf));
+ if (ret) {
+ /* httpc_err("Could not write request"); */
+ return ERROR_HTTP_CONN;
+ }
+
+ /* Add user header information */
+ if (client->header) {
+ _utils_fill_tx_buffer(client, send_buf, &len, (char *) client->header, strlen(client->header));
+ }
+
+ if (client_data->post_buf != NULL) {
+ HAL_Snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", client_data->post_buf_len);
+ _utils_fill_tx_buffer(client, send_buf, &len, buf, strlen(buf));
+
+ if (client_data->post_content_type != NULL) {
+ HAL_Snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", client_data->post_content_type);
+ _utils_fill_tx_buffer(client, send_buf, &len, buf, strlen(buf));
+ }
+ }
+
+ /* Close headers */
+ _utils_fill_tx_buffer(client, send_buf, &len, "\r\n", 0);
+
+#ifdef INFRA_LOG
+ log_multi_line(LOG_DEBUG_LEVEL, "REQUEST", "%s", send_buf, ">");
+#endif
+
+ /* ret = httpclient_tcp_send_all(client->net.handle, send_buf, len); */
+ ret = client->net.write(&client->net, send_buf, len, 5000);
+ if (ret <= 0) {
+ httpc_err("ret = client->net.write() = %d", ret);
+ return (ret == 0) ? ERROR_HTTP_CLOSED : ERROR_HTTP_CONN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int _http_send_userdata(httpclient_t *client, httpclient_data_t *client_data)
+{
+ int ret = 0;
+
+ if (client_data->post_buf && client_data->post_buf_len) {
+ /* ret = httpclient_tcp_send_all(client->handle, (char *)client_data->post_buf, client_data->post_buf_len); */
+ ret = client->net.write(&client->net, (char *)client_data->post_buf, client_data->post_buf_len, 5000);
+ httpc_debug("client_data->post_buf: %s, ret is %d", client_data->post_buf, ret);
+ if (ret <= 0) {
+ return (ret == 0) ? ERROR_HTTP_CLOSED : ERROR_HTTP_CONN; /* Connection was closed by server */
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+/* 0 on success, err code on failure */
+static int _http_recv(httpclient_t *client, char *buf, int max_len, int *p_read_len,
+ uint32_t timeout_ms)
+{
+ int ret = 0;
+ iotx_time_t timer;
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout_ms);
+
+ *p_read_len = 0;
+
+ ret = client->net.read(&client->net, buf, max_len, iotx_time_left(&timer));
+ /* httpc_debug("Recv: | %s", buf); */
+ httpc_info("ret of _http_recv is %d", ret);
+
+ if (ret > 0) {
+ *p_read_len = ret;
+ return 0;
+ } else if (ret == 0) {
+ /* timeout */
+ return FAIL_RETURN;
+ } else {
+ return ERROR_HTTP_CONN;
+ }
+}
+
+#define MIN_TIMEOUT (100)
+#define MAX_RETRY_COUNT (600)
+
+
+static int _utils_check_deadloop(int len, iotx_time_t *timer, int ret, unsigned int *dead_loop_count,
+ unsigned int *extend_count)
+{
+ /* if timeout reduce to zero, it will be translated into NULL for select function in TLS lib */
+ /* it would lead to indenfinite behavior, so we avoid it */
+ if (iotx_time_left(timer) < MIN_TIMEOUT) {
+ (*extend_count)++;
+ utils_time_countdown_ms(timer, MIN_TIMEOUT);
+ }
+
+ /* if it falls into deadloop before reconnected to internet, we just quit*/
+ if ((0 == len) && (0 == iotx_time_left(timer)) && (FAIL_RETURN == ret)) {
+ (*dead_loop_count)++;
+ if (*dead_loop_count > MAX_RETRY_COUNT) {
+ httpc_err("deadloop detected, exit");
+ return ERROR_HTTP_CONN;
+ }
+ } else {
+ *dead_loop_count = 0;
+ }
+
+ /*if the internet connection is fixed during the loop, the download stream might be disconnected. we have to quit */
+ if ((0 == len) && (*extend_count > 2 * MAX_RETRY_COUNT) && (FAIL_RETURN == ret)) {
+ httpc_err("extend timer for too many times, exit");
+ return ERROR_HTTP_CONN;
+ }
+ return SUCCESS_RETURN;
+}
+
+static int _utils_fill_rx_buf(int *recv_count, int len_to_write_to_respons_buf, httpclient_data_t *client_data,
+ char *data)
+{
+ int count = *recv_count;
+ if (count + len_to_write_to_respons_buf < client_data->response_buf_len - 1) {
+ memcpy(client_data->response_buf + count, data, len_to_write_to_respons_buf);
+ count += len_to_write_to_respons_buf;
+ client_data->response_buf[count] = '\0';
+ client_data->retrieve_len -= len_to_write_to_respons_buf;
+ *recv_count = count;
+ return SUCCESS_RETURN;
+ } else {
+ memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count);
+ client_data->response_buf[client_data->response_buf_len - 1] = '\0';
+ client_data->retrieve_len -= (client_data->response_buf_len - 1 - count);
+ return HTTP_RETRIEVE_MORE_DATA;
+ }
+}
+
+static int _http_get_response_body(httpclient_t *client, char *data, int data_len_actually_received,
+ uint32_t timeout_ms, httpclient_data_t *client_data)
+{
+ int written_response_buf_len = 0;
+ int len_to_write_to_respons_buf = 0;
+ iotx_time_t timer;
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout_ms);
+
+ /* Receive data */
+ /* httpc_debug("Current data: %s", data); */
+
+ client_data->is_more = IOT_TRUE;
+
+ /* the header is not received finished */
+ if (client_data->response_content_len == -1 && client_data->is_chunked == IOT_FALSE) {
+ /* can not enter this if */
+ /* TODO check the way to go into this branch */
+ httpc_err("header is not received yet");
+ return ERROR_HTTP_CONN;
+ }
+
+ while (1) {
+ unsigned int dead_loop_count = 0;
+ unsigned int extend_count = 0;
+ do {
+ int res;
+ /* move previous fetched data into response_buf */
+ len_to_write_to_respons_buf = HTTPCLIENT_MIN(data_len_actually_received, client_data->retrieve_len);
+ res = _utils_fill_rx_buf(&written_response_buf_len, len_to_write_to_respons_buf, client_data, data);
+ if (HTTP_RETRIEVE_MORE_DATA == res) {
+ return HTTP_RETRIEVE_MORE_DATA;
+ }
+
+ /* get data from internet and put into "data" buf temporary */
+ if (client_data->retrieve_len) {
+ int ret;
+ int max_len_to_receive = HTTPCLIENT_MIN(HTTPCLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - written_response_buf_len);
+ max_len_to_receive = HTTPCLIENT_MIN(max_len_to_receive, client_data->retrieve_len);
+
+ ret = _http_recv(client, data, max_len_to_receive, &data_len_actually_received, iotx_time_left(&timer));
+ if (ret == ERROR_HTTP_CONN) {
+ return ret;
+ }
+ httpc_debug("Total- remaind Payload: %d Bytes; currently Read: %d Bytes", client_data->retrieve_len, data_len_actually_received);
+
+ /* TODO add deadloop processing*/
+ ret = _utils_check_deadloop(data_len_actually_received, &timer, ret, &dead_loop_count,
+ &extend_count);
+ if (ERROR_HTTP_CONN == ret) {
+ return ret;
+ }
+ }
+ } while (client_data->retrieve_len);
+ client_data->is_more = IOT_FALSE;
+ break;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int _http_parse_response_header(httpclient_t *client, char *data, int len, uint32_t timeout_ms,
+ httpclient_data_t *client_data)
+{
+ int crlf_pos;
+ iotx_time_t timer;
+ char *tmp_ptr, *ptr_body_end;
+ int new_trf_len, ret;
+ char *crlf_ptr;
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout_ms);
+
+ client_data->response_content_len = -1;
+
+ /* http client response */
+ /* HTTP/1.1 200 OK(CRLF)
+
+ ...(CRLF)
+
+ (CRLF)
+
+ [] */
+ crlf_ptr = strstr(data, "\r\n");
+ if (crlf_ptr == NULL) {
+ httpc_err("\r\n not found");
+ return ERROR_HTTP_UNRESOLVED_DNS;
+ }
+
+ crlf_pos = crlf_ptr - data;
+ data[crlf_pos] = '\0';
+ client->response_code = atoi(data + 9);
+ httpc_debug("Reading headers: %s", data);
+ memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1); /* Be sure to move NULL-terminating char as well */
+ len -= (crlf_pos + 2); /* remove status_line length */
+ client_data->is_chunked = IOT_FALSE;
+
+ /*If not ending of response body*/
+ /* try to read more header again until find response head ending "\r\n\r\n" */
+ while (NULL == (ptr_body_end = strstr(data, "\r\n\r\n"))) {
+ /* try to read more header */
+ ret = _http_recv(client, data + len, HTTPCLIENT_RAED_HEAD_SIZE, &new_trf_len, iotx_time_left(&timer));
+ if (ret == ERROR_HTTP_CONN) {
+ return ret;
+ }
+ len += new_trf_len;
+ data[len] = '\0';
+ }
+
+ /* parse response_content_len */
+ if (NULL != (tmp_ptr = strstr(data, "Content-Length"))) {
+ client_data->response_content_len = atoi(tmp_ptr + strlen("Content-Length: "));
+ client_data->retrieve_len = client_data->response_content_len;
+ } else {
+ httpc_err("Could not parse header");
+ return ERROR_HTTP;
+ }
+
+ /* remove header length */
+ /* len is Had read body's length */
+ /* if client_data->response_content_len != 0, it is know response length */
+ /* the remain length is client_data->response_content_len - len */
+ len = len - (ptr_body_end + 4 - data);
+ memmove(data, ptr_body_end + 4, len + 1);
+ client_data->response_received_len += len;
+ return _http_get_response_body(client, data, len, iotx_time_left(&timer), client_data);
+}
+
+int httpclient_connect(httpclient_t *client)
+{
+ int retry_max = 3;
+ int retry_cnt = 1;
+ int retry_interval = 1000;
+ int rc = -1;
+
+ do {
+ client->net.handle = 0;
+ httpc_debug("calling TCP or TLS connect HAL for [%d/%d] iteration", retry_cnt, retry_max);
+
+ rc = client->net.connect(&client->net);
+ if (0 != rc) {
+ client->net.disconnect(&client->net);
+ httpc_err("TCP or TLS connect failed, rc = %d", rc);
+ HAL_SleepMs(retry_interval);
+ continue;
+ } else {
+ httpc_debug("rc = client->net.connect() = %d, success @ [%d/%d] iteration", rc, retry_cnt, retry_max);
+ break;
+ }
+ } while (++retry_cnt <= retry_max);
+
+ return SUCCESS_RETURN;
+}
+
+int _http_send_request(httpclient_t *client, const char *host, const char *path, HTTPCLIENT_REQUEST_TYPE method,
+ httpclient_data_t *client_data)
+{
+ int ret = ERROR_HTTP_CONN;
+
+ if (0 == client->net.handle) {
+ return -1;
+ }
+
+ ret = _http_send_header(client, host, path, method, client_data);
+ if (ret != 0) {
+ return -2;
+ }
+
+ if (method == HTTPCLIENT_POST || method == HTTPCLIENT_PUT) {
+ ret = _http_send_userdata(client, client_data);
+ if (ret < 0) {
+ ret = -3;
+ }
+ }
+
+ return ret;
+}
+
+int httpclient_recv_response(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data)
+{
+ int reclen = 0, ret = ERROR_HTTP_CONN;
+ char buf[HTTPCLIENT_READ_BUF_SIZE] = { 0 };
+ iotx_time_t timer;
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout_ms);
+
+ if (0 == client->net.handle) {
+ httpc_err("not connection have been established");
+ return ret;
+ }
+
+ if (client_data->is_more) {
+ client_data->response_buf[0] = '\0';
+ ret = _http_get_response_body(client, buf, reclen, iotx_time_left(&timer), client_data);
+ } else {
+ client_data->is_more = 1;
+ /* try to read header */
+ ret = _http_recv(client, buf, HTTPCLIENT_RAED_HEAD_SIZE, &reclen, iotx_time_left(&timer));
+ if (ret != 0) {
+ return ret;
+ }
+
+ buf[reclen] = '\0';
+
+ if (reclen) {
+#ifdef INFRA_LOG
+ log_multi_line(LOG_DEBUG_LEVEL, "RESPONSE", "%s", buf, "<");
+#endif
+ ret = _http_parse_response_header(client, buf, reclen, iotx_time_left(&timer), client_data);
+ }
+ }
+
+ return ret;
+}
+
+void httpclient_close(httpclient_t *client)
+{
+ if (client->net.handle > 0) {
+ client->net.disconnect(&client->net);
+ }
+ client->net.handle = 0;
+ httpc_info("client disconnected");
+}
+
+static int _http_send(httpclient_t *client, const char *url, int port, const char *ca_crt,
+ HTTPCLIENT_REQUEST_TYPE method, httpclient_data_t *client_data)
+{
+ int ret;
+ char host[HTTPCLIENT_MAX_URL_LEN] = { 0 };
+ char path[HTTPCLIENT_MAX_URL_LEN] = { 0 };
+
+ /* First we need to parse the url (http[s]://host[:port][/[path]]) */
+ ret = _utils_parse_url(url, host, path);
+ if (ret != SUCCESS_RETURN) {
+ httpc_err("_utils_parse_url fail returned %d", ret);
+ return ret;
+ }
+
+ if (0 == client->net.handle) {
+ /* Establish connection if no. */
+ #ifdef SUPPORT_TCP
+ ret = iotx_net_tcp_init(&client->net, host, port, ca_crt);
+ #else
+ ret = iotx_net_init(&client->net, host, port, ca_crt);
+ #endif
+ if (0 != ret) {
+ return ret;
+ }
+
+ ret = httpclient_connect(client);
+ if (0 != ret) {
+ httpclient_close(client);
+ return ret;
+ }
+
+ ret = _http_send_request(client, host, path, method, client_data);
+ if (0 != ret) {
+ httpc_err("_http_send_request is error, ret = %d", ret);
+ httpclient_close(client);
+ return ret;
+ }
+ }
+ return SUCCESS_RETURN;
+}
+
+int httpclient_common(httpclient_t *client, const char *url, int port, const char *ca_crt,
+ HTTPCLIENT_REQUEST_TYPE method, uint32_t timeout_ms, httpclient_data_t *client_data)
+{
+ iotx_time_t timer;
+ int ret = _http_send(client, url, port, ca_crt, method, client_data);
+ if (SUCCESS_RETURN != ret) {
+ return ret;
+ }
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout_ms);
+
+ if ((NULL != client_data->response_buf)
+ && (0 != client_data->response_buf_len)) {
+ ret = httpclient_recv_response(client, iotx_time_left(&timer), client_data);
+ if (ret < 0) {
+ httpc_err("httpclient_recv_response is error,ret = %d", ret);
+ httpclient_close(client);
+ return ret;
+ }
+ }
+
+ if (! client_data->is_more) {
+ /* Close the HTTP if no more data. */
+ httpc_info("close http channel");
+ httpclient_close(client);
+ }
+
+ ret = 0;
+ return ret;
+}
+
+int iotx_post(httpclient_t *client,
+ const char *url,
+ int port,
+ const char *ca_crt,
+ httpclient_data_t *client_data)
+{
+ return _http_send(client, url, port, ca_crt, HTTPCLIENT_POST, client_data);
+}
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_httpc.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_httpc.h
new file mode 100644
index 00000000..0148ede8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_httpc.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef _INFRA_HTTPC_H_
+#define _INFRA_HTTPC_H_
+
+#include "infra_net.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup HttpClient
+ * @{
+ * HttpClient API implements the client-side of HTTP/1.1. It provides base interfaces to execute an HTTP request on a given URL. It also supports HTTPS (HTTP over TLS) to provide secure communication.\n
+ * @section HttpClient_Usage_Chapter How to use this module
+ * In this release, MediaTek provides two types of APIs: high level APIs and low level APIs.\n
+ * - \b The \b high \b level \b APIs
+ * - Enables to execute a single HTTP request on a given URL.
+ * - Call #httpclient_get(), #httpclient_post(), #httpclient_put() or #httpclient_delete() to get, post, put or delete and HTTP request.\n
+ * - \b The \b low \b level \b APIs
+ * - Enables to execute more than one HTTP requests during a Keep-Alive connection. Keep-alive is the idea of using a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair.
+ * - Step1: Call #httpclient_connect() to connect to a remote server.
+ * - Step2: Call #httpclient_send_request() to send an HTTP request to the server.
+ * - Step3: Call #httpclient_recv_response() to receive an HTTP response from the server.
+ * - Step4: Repeat Steps 2 and 3 to execute more requests.
+ * - Step5: Call #httpclient_close() to close the connection.
+ * - Sample code: Please refer to the example under /project/mt7687_hdk/apps/http_client/http_client_keepalive folder.
+ */
+
+/** @defgroup httpclient_define Define
+ * @{
+ */
+/** @brief This macro defines the HTTP port. */
+#define HTTP_PORT 80
+
+/** @brief This macro defines the HTTPS port. */
+#define HTTPS_PORT 443
+/**
+ * @}
+ */
+
+/** @defgroup httpclient_enum Enum
+ * @{
+ */
+/** @brief This enumeration defines the HTTP request type. */
+typedef enum {
+ HTTPCLIENT_GET,
+ HTTPCLIENT_POST,
+ HTTPCLIENT_PUT,
+ HTTPCLIENT_DELETE,
+ HTTPCLIENT_HEAD
+} HTTPCLIENT_REQUEST_TYPE;
+
+
+/** @defgroup httpclient_struct Struct
+ * @{
+ */
+/** @brief This structure defines the httpclient_t structure. */
+typedef struct {
+ int remote_port; /**< HTTP or HTTPS port. */
+ utils_network_t net;
+ int response_code; /**< Response code. */
+ char *header; /**< Custom header. */
+ char *auth_user; /**< Username for basic authentication. */
+ char *auth_password; /**< Password for basic authentication. */
+} httpclient_t;
+
+/** @brief This structure defines the HTTP data structure. */
+typedef struct {
+ int is_more; /**< Indicates if more data needs to be retrieved. */
+ int is_chunked; /**< Response data is encoded in portions/chunks.*/
+ int retrieve_len; /**< Content length to be retrieved. */
+ int response_content_len; /**< Response content length. */
+ int response_received_len; /**< Response have received length. */
+ int post_buf_len; /**< Post data length. */
+ int response_buf_len; /**< Response buffer length. */
+ char *post_content_type; /**< Content type of the post data. */
+ char *post_buf; /**< User data to be posted. */
+ char *response_buf; /**< Buffer to store the response data. */
+} httpclient_data_t;
+
+int iotx_post(httpclient_t *client,
+ const char *url,
+ int port,
+ const char *ca_crt,
+ httpclient_data_t *client_data);
+
+int httpclient_recv_response(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data);
+
+int httpclient_common(httpclient_t *client, const char *url, int port, const char *ca_crt,
+ HTTPCLIENT_REQUEST_TYPE method, uint32_t timeout_ms, httpclient_data_t *client_data);
+
+void httpclient_close(httpclient_t *client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HTTPCLIENT_H__ */
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_json_parser.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_json_parser.c
new file mode 100644
index 00000000..f3481925
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_json_parser.c
@@ -0,0 +1,845 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_JSON_PARSER
+
+#include
+#include
+#include
+#include
+
+#include "infra_types.h"
+#include "infra_json_parser.h"
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+
+#ifdef INFRA_LOG
+#include "infra_log.h"
+#define jparser_debug(...) log_debug("jparser", __VA_ARGS__)
+#else
+#define jparser_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#define jparser_malloc(size) LITE_malloc(size, MEM_MAGIC, "jparser")
+#define jparser_free(ptr) LITE_free(ptr)
+#else
+#define jparser_malloc(size) HAL_Malloc(size)
+#define jparser_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+char *json_get_object(int type, char *str, char *str_end)
+{
+ char *pos = NULL;
+ char ch = (type == JOBJECT) ? '{' : '[';
+
+ if (!str || !str_end) {
+ return NULL;
+ }
+
+ while (str != NULL && *str != 0 && str < str_end) {
+ if (*str == ' ') {
+ str++;
+ continue;
+ }
+ pos = (*str == ch) ? str : NULL;
+ break;
+ }
+ return pos;
+}
+
+char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len,
+ char **val, int *val_len, int *val_type)
+{
+ char JsonMark[JTYPEMAX][2] = { { '\"', '\"' }, { '{', '}' }, { '[', ']' }, { '0', ' ' } };
+ int iMarkDepth = 0, iValueType = JNONE, iNameLen = 0, iValueLen = 0, iStringDepth = 0;
+ char *p_cName = 0, *p_cValue = 0, *p_cPos = str;
+
+ if (type == JOBJECT) {
+ /* Get Key */
+ p_cPos = strchr(p_cPos, '\"');
+ if (!p_cPos) {
+ goto do_exit;
+ }
+ p_cName = ++p_cPos;
+ p_cPos = strchr(p_cPos, '\"');
+ if (!p_cPos) {
+ goto do_exit;
+ }
+ iNameLen = p_cPos - p_cName;
+
+ /* Get Value */
+ p_cPos = strchr(p_cPos, ':');
+ }
+ while (p_cPos && *p_cPos && p_cPos < str_end) {
+ if (*p_cPos == '\"') {
+ iValueType = JSTRING;
+ p_cValue = ++p_cPos;
+ break;
+ } else if (*p_cPos == '{') {
+ iValueType = JOBJECT;
+ p_cValue = p_cPos++;
+ break;
+ } else if (*p_cPos == '[') {
+ iValueType = JARRAY;
+ p_cValue = p_cPos++;
+ break;
+ } else if ((*p_cPos == '-') || (*p_cPos >= '0' && *p_cPos <= '9')) {
+ iValueType = JNUMBER;
+ p_cValue = p_cPos++;
+ break;
+ } else if (*p_cPos == 't' || *p_cPos == 'T' || *p_cPos == 'f' || *p_cPos == 'F') {
+ iValueType = JBOOLEAN;
+ p_cValue = p_cPos;
+ break;
+ }
+ p_cPos++;
+ }
+
+ while (p_cPos && *p_cPos && p_cPos < str_end && iValueType > JNONE) {
+ if (iValueType == JBOOLEAN) {
+ int len = strlen(p_cValue);
+
+ if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4
+ && (!strncmp(p_cValue, "true", 4)
+ || !strncmp(p_cValue, "TRUE", 4))) {
+ iValueLen = 4;
+ p_cPos = p_cValue + iValueLen;
+ break;
+ } else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5
+ && (!strncmp(p_cValue, "false", 5)
+ || !strncmp(p_cValue, "FALSE", 5))) {
+ iValueLen = 5;
+ p_cPos = p_cValue + iValueLen;
+ break;
+ }
+ } else if (iValueType == JNUMBER) {
+ if ((*p_cPos < '0' || *p_cPos > '9') && (*p_cPos != '.') && (*p_cPos != '+') \
+ && (*p_cPos != '-') && ((*p_cPos != 'e')) && (*p_cPos != 'E')) {
+ iValueLen = p_cPos - p_cValue;
+ break;
+ }
+ } else if (iValueType == JSTRING) {
+ if (*p_cPos == '\"') {
+ iValueLen = p_cPos - p_cValue;
+ break;
+ }
+ } else if (*p_cPos == JsonMark[iValueType][1]) {
+ if (iStringDepth == 0) {
+ if (iMarkDepth == 0) {
+ iValueLen = p_cPos - p_cValue + 1;
+ p_cPos++;
+ break;
+ } else {
+ iMarkDepth--;
+ }
+ }
+ } else if (*p_cPos == JsonMark[iValueType][0]) {
+ if (iStringDepth == 0) {
+ iMarkDepth++;
+ }
+ } else if (*p_cPos == '\"') {
+ if (iStringDepth) {
+ iStringDepth = 0;
+ } else {
+ iStringDepth = 1;
+ }
+ }
+ p_cPos++;
+ }
+
+ if (type == JOBJECT) {
+ if ((p_cName + iNameLen) > str_end) {
+ goto do_exit;
+ }
+ *key = p_cName;
+ *key_len = iNameLen;
+ }
+ if ((p_cValue + iValueLen) > str_end) {
+ goto do_exit;
+ }
+
+ *val = p_cValue;
+ *val_len = iValueLen;
+ *val_type = iValueType;
+ if (iValueType == JSTRING) {
+ return p_cValue + iValueLen + 1;
+ } else {
+ return p_cValue + iValueLen;
+ }
+
+do_exit:
+ *val = NULL;
+ *val_len = 0;
+ *key = NULL;
+ *key_len = 0;
+ return NULL;
+}
+
+int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData)
+{
+ char *pos = 0, *key = 0, *val = 0;
+ int klen = 0, vlen = 0, vtype = 0;
+ int ret = JSON_RESULT_ERR;
+
+ if (p_cJsonStr == NULL || iStrLen == 0 || pfnCB == NULL) {
+ return ret;
+ }
+
+ json_object_for_each_kv(p_cJsonStr, iStrLen, pos, key, klen, val, vlen, vtype) {
+ if (key && klen && val && vlen) {
+ ret = JSON_RESULT_OK;
+ if (JSON_PARSE_FINISH == pfnCB(key, klen, val, vlen, vtype, p_CBData)) {
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
+ void *p_CBData)
+{
+ JSON_NV *p_stNameValue = (JSON_NV *)p_CBData;
+
+#ifdef JSON_DEBUG
+ int i;
+
+ if (p_cName) {
+ jparser_debug("Name:");
+ for (i = 0; i < iNameLen; i++) {
+ jparser_debug("%c", *(p_cName + i));
+ }
+ }
+
+ if (p_cValue) {
+ jparser_debug("Value:");
+ for (i = 0; i < iValueLen; i++) {
+ jparser_debug("%c", *(p_cValue + i));
+ }
+ }
+#endif
+
+ if ((iNameLen == p_stNameValue->nLen) && !strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) {
+ p_stNameValue->pV = p_cValue;
+ p_stNameValue->vLen = iValueLen;
+ p_stNameValue->vType = iValueType;
+ return JSON_PARSE_FINISH;
+ } else {
+ return JSON_PARSE_OK;
+ }
+}
+
+char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType)
+{
+ JSON_NV stNV;
+
+ memset(&stNV, 0, sizeof(stNV));
+ stNV.pN = p_cName;
+ stNV.nLen = strlen(p_cName);
+ if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
+ if (p_iValueLen) {
+ *p_iValueLen = stNV.vLen;
+ }
+ if (p_iValueType) {
+ *p_iValueType = stNV.vType;
+ }
+ }
+ return stNV.pV;
+}
+
+char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen,
+ int *p_iValueType)
+{
+ JSON_NV stNV;
+
+ memset(&stNV, 0, sizeof(stNV));
+ stNV.pN = p_cName;
+ stNV.nLen = p_cNameLen;
+ if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) {
+ if (p_iValueLen) {
+ *p_iValueLen = stNV.vLen;
+ }
+ if (p_iValueType) {
+ *p_iValueType = stNV.vType;
+ }
+ }
+ return stNV.pV;
+}
+
+char *LITE_json_value_of(char *key, char *src, ...)
+{
+ char *value = NULL;
+ char *ret = NULL;
+ char *delim = NULL;
+ char *key_iter;
+ char *key_next;
+ char *src_iter;
+
+ int key_len;
+ int value_len = -1;
+ int src_iter_len;
+
+ if (NULL == key || NULL == src) {
+ return NULL;
+ }
+
+#if WITH_MEM_STATS_PER_MODULE
+{
+ char *module_name = NULL;
+ int magic = 0;
+ va_list ap;
+ va_start(ap, src);
+ magic = va_arg(ap, int);
+ if (MEM_MAGIC == magic) {
+ module_name = va_arg(ap, char *);
+ }
+ va_end(ap);
+}
+#endif
+
+ src_iter = src;
+ src_iter_len = strlen(src_iter);
+ key_iter = key;
+
+ do {
+ if ((delim = strchr(key_iter, '.')) != NULL) {
+ key_len = delim - key_iter;
+ key_next = key_iter;
+
+ value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
+ if (value == NULL) {
+ return NULL;
+ }
+
+ src_iter = value;
+ src_iter_len = value_len;
+ key_iter = delim + 1;
+ }
+ } while (delim);
+
+ key_len = strlen(key_iter);
+ key_next = key_iter;
+ value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
+ if (NULL == value) {
+ return NULL;
+ }
+
+ ret = jparser_malloc((value_len + 1) * sizeof(char));
+
+ if (NULL == ret) {
+ return NULL;
+ }
+
+ HAL_Snprintf(ret, value_len + 1, "%s", value);
+ return ret;
+}
+
+#if WITH_JSON_KEYS_OF
+static list_head_t *_LITE_json_keys_of(char *src, int src_len, char *prefix, ...)
+{
+ static ALIYUN_LIST_HEAD(keylist);
+ char *module_name = NULL;
+ char *iter_pre = NULL;
+ char *pos = 0, *key = 0, *val = 0;
+ int klen = 0, vlen = 0, vtype = 0;
+ int magic = 0;
+ unsigned int mlen = 0;
+
+#if WITH_MEM_STATS_PER_MODULE
+ va_list ap;
+ va_start(ap, prefix);
+ magic = va_arg(ap, int);
+ if (MEM_MAGIC == magic) {
+ module_name = va_arg(ap, char *);
+ }
+ va_end(ap);
+#endif
+
+ if (!strcmp("", prefix)) {
+ INIT_LIST_HEAD(&keylist);
+ }
+
+ json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) {
+ if (key && klen && val && vlen) {
+
+ json_key_t *entry = NULL;
+
+ entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
+ if (NULL == entry) {
+ utils_err("jparser_malloc failed!");
+ return NULL;
+ }
+ memset(entry, 0, sizeof(json_key_t));
+
+ mlen = strlen(prefix) + klen + 1;
+ if (module_name) {
+ entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
+ } else {
+ entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
+ }
+ if (NULL == entry->key) {
+ jparser_free(entry);
+ return NULL;
+ }
+
+ list_add_tail(&entry->list, &keylist);
+
+ if (JOBJECT == vtype) {
+ mlen = strlen(prefix) + klen + 2;
+ if (module_name) {
+ iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key);
+ } else {
+ iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key);
+ }
+ if (NULL == iter_pre) {
+ return NULL;
+ }
+
+ _LITE_json_keys_of(val, vlen, iter_pre, magic, module_name);
+ jparser_free(iter_pre);
+ }
+ }
+ }
+
+ if (!strcmp("", prefix)) {
+ json_key_t *entry = NULL;
+
+ entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
+ if (NULL == entry) {
+ utils_err("jparser_malloc failed!");
+ return NULL;
+ }
+ memset(entry, 0, sizeof(json_key_t));
+ list_add_tail(&entry->list, &keylist);
+
+ return &keylist;
+ }
+
+ return NULL;
+}
+
+list_head_t *LITE_json_keys_of(char *src, char *prefix, ...)
+{
+ char *module_name = NULL;
+ int magic = 0;
+
+ if (!src || !prefix) {
+ return NULL;
+ }
+
+#if WITH_MEM_STATS_PER_MODULE
+
+ va_list ap;
+ va_start(ap, prefix);
+ magic = va_arg(ap, int);
+ if (MEM_MAGIC == magic) {
+ module_name = va_arg(ap, char *);
+ }
+ va_end(ap);
+#endif
+
+ return _LITE_json_keys_of(src, strlen(src), prefix, magic, module_name);
+
+}
+
+#if WITH_JSON_TOKEN_EXT
+static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, char *prefix, ...)
+{
+ static ALIYUN_LIST_HEAD(keylist);
+ char *module_name = NULL;
+ char *iter_pre = NULL;
+ char *pos = 0, *key = 0, *val = 0;
+ int klen = 0, vlen = 0, vtype = 0;
+ int magic = 0;
+ unsigned int count = 1;
+ unsigned int mlen = 0;
+
+ if (src == NULL || prefix == NULL) {
+ return NULL;
+ }
+
+#if WITH_MEM_STATS_PER_MODULE
+ va_list ap;
+ va_start(ap, prefix);
+ magic = va_arg(ap, int);
+ if (MEM_MAGIC == magic) {
+ module_name = va_arg(ap, char *);
+ }
+ va_end(ap);
+#endif
+
+ if (!strcmp("", prefix)) {
+ INIT_LIST_HEAD(&keylist);
+ }
+
+ if (JOBJECT == type) {
+ json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) {
+ if (key && klen && val && vlen) {
+
+ json_key_t *entry = NULL;
+
+ entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
+
+ if (NULL == entry) {
+ utils_err("jparser_malloc failed!");
+ return NULL;
+ }
+ memset(entry, 0, sizeof(json_key_t));
+
+ mlen = strlen(prefix) + klen + 1;
+ if (module_name) {
+ entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
+ } else {
+ entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
+ }
+
+ if (NULL == entry->key) {
+ jparser_free(entry);
+ return NULL;
+ }
+
+ list_add_tail(&entry->list, &keylist);
+
+ if (JOBJECT == vtype) {
+ mlen = strlen(prefix) + klen + 2;
+ if (module_name) {
+ iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key);
+ } else {
+ iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key);
+ }
+ if (NULL == iter_pre) {
+ return NULL;
+ }
+
+ _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
+ jparser_free(iter_pre);
+ } else if (JARRAY == vtype) {
+ mlen = strlen(prefix) + klen + 1;
+ if (module_name) {
+ iter_pre = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key);
+ } else {
+ iter_pre = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key);
+ }
+ if (NULL == iter_pre) {
+ return NULL;
+ }
+
+ _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
+ jparser_free(iter_pre);
+ }
+ }
+ }
+ } else if (JARRAY == type) {
+ json_array_for_each_entry(src, src_len, pos, val, vlen, vtype) {
+ if (val && vlen) {
+
+ json_key_t *entry = NULL;
+ unsigned int tmp = 0;
+ unsigned int arridxlen = 0;
+ entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
+ if (NULL == entry) {
+ utils_err("jparser_malloc failed!");
+ return NULL;
+ }
+ memset(entry, 0, sizeof(json_key_t));
+
+ tmp = count;
+ do {
+ tmp /= 10;
+ ++arridxlen;
+ } while (tmp);
+ mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen;
+ if (module_name) {
+ entry->key = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count);
+ } else {
+ entry->key = LITE_format_nstring(mlen, "%s[%d]", prefix, count);
+ }
+ if (NULL == entry->key) {
+ jparser_free(entry);
+ return NULL;
+ }
+
+ list_add_tail(&entry->list, &keylist);
+
+ if (JOBJECT == vtype) {
+ mlen = strlen("%s[%d].") + strlen(prefix) + arridxlen;
+ if (module_name) {
+ iter_pre = LITE_format_nstring(mlen, "%s[%d].", magic, module_name, prefix, count);
+ } else {
+ iter_pre = LITE_format_nstring(mlen, "%s[%d].", prefix, count);
+ }
+ if (NULL == iter_pre) {
+ return NULL;
+ }
+
+ _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
+ jparser_free(iter_pre);
+ } else if (JARRAY == vtype) {
+ mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen;
+ if (module_name) {
+ iter_pre = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count);
+ } else {
+ iter_pre = LITE_format_nstring(mlen, "%s[%d]", prefix, count);
+ }
+ if (NULL == iter_pre) {
+ return NULL;
+ }
+
+ _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name);
+ jparser_free(iter_pre);
+ }
+ ++count;
+ }
+ }
+ }
+
+ if (!strcmp("", prefix)) {
+ json_key_t *entry = NULL;
+
+ entry = jparser_malloc(sizeof(json_key_t), magic, module_name);
+ if (NULL == entry) {
+ utils_err("jparser_malloc failed!");
+ return NULL;
+ }
+ memset(entry, 0, sizeof(json_key_t));
+ list_add_tail(&entry->list, &keylist);
+
+ return &keylist;
+ }
+
+ return NULL;
+
+}
+
+int contain_arr(const char *src, int src_len, const char **arr_pre)
+{
+ int i = 0;
+ int ret = -1;
+ int deep = 0;
+ const char *pre = NULL;
+
+ if (NULL == src || NULL == arr_pre || src_len <= 0) {
+ return -1;
+ }
+
+ *arr_pre = NULL;
+ for (i = 0; i < src_len; ++i) {
+ switch (src[i]) {
+ case '[': {
+ if (deep != 0) {
+ return ret;
+ }
+ ++deep;
+ if (!pre) {
+ pre = &src[i];
+ }
+ }
+ break;
+ case ']': {
+ if (deep != 1) {
+ return ret;
+ }
+ --deep;
+ if ('[' == src[i - 1]) {
+ return ret;
+ }
+ }
+ break;
+ default: {
+ if ((pre != NULL) && (0 == deep)) {
+ return ret;
+ }
+ }
+ break;
+ }
+ }
+ if ((NULL != pre) && (pre < src + src_len) && (pre >= src)) {
+ *arr_pre = pre;
+ ret = 0;
+ }
+ return ret;
+}
+
+static char *_json_value_by_arrname(char *src, int src_len, const char *key, int key_len, int *val_len)
+{
+ char *pos = src;
+ char *entry = NULL;
+ const char *p = NULL;
+ const char *arr_pre = key;
+ const char *arr_suf = NULL;
+ int vtype;
+ int loop;
+ int loop_tmp = 0;
+ do {
+ loop = 0;
+
+ arr_pre = strchr(arr_pre, '[');
+ if (arr_pre && (arr_pre < key + key_len)) {
+ arr_suf = strchr(arr_pre, ']');
+ }
+ if (arr_pre && arr_suf && (arr_suf < key + key_len)) {
+ loop_tmp = 0;
+ for (p = arr_pre + 1; p < arr_suf; ++p) {
+ if (*p > '9' || *p < '0') {
+ return NULL;
+ }
+ loop_tmp *= 10;
+ loop_tmp += *p - '0';
+
+ }
+
+ pos = json_get_object(JARRAY, pos, src + src_len);
+ if (pos != 0 && *pos != 0) {
+ if (*pos == '[' && *(pos + 1) == ']') {
+ return NULL;
+ }
+ }
+
+ json_array_for_each_entry(src, src_len, pos, entry, *val_len, vtype) {
+ if (entry && *val_len) {
+ if (++loop >= loop_tmp) {
+ break;
+ }
+ }
+ }
+
+ if (loop != loop_tmp) {
+ return NULL;
+ }
+ src = entry;
+ arr_pre = arr_suf + 1;
+ }
+ } while (arr_pre && arr_suf && (arr_pre < key + key_len));
+ return entry;
+}
+
+void LITE_json_keys_release(list_head_t *keylist)
+{
+ json_key_t *pos, *tmp;
+
+ if (NULL == keylist) {
+ return;
+ }
+
+ list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) {
+ if (pos->key) {
+ jparser_free(pos->key);
+ }
+ list_del(&pos->list);
+ jparser_free(pos);
+ }
+}
+
+list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...)
+{
+ char *module_name = NULL;
+ int magic = 0;
+
+#if WITH_MEM_STATS_PER_MODULE
+
+ va_list ap;
+ va_start(ap, prefix);
+ magic = va_arg(ap, int);
+ if (MEM_MAGIC == magic) {
+ module_name = va_arg(ap, char *);
+ }
+ va_end(ap);
+#endif
+
+ if (!src || !prefix) {
+ return NULL;
+ }
+
+ return _LITE_json_keys_of_ext(JOBJECT, src, strlen(src), prefix, magic, module_name);
+}
+
+static char *_LITE_json_value_of_ext(char *key, char *src, int src_len, int *val_len)
+{
+ char *value = NULL;
+ char *delim = NULL;
+ char *key_iter;
+ char *key_next;
+ char *src_iter;
+ const char *arr_pre = NULL;
+
+ int value_len;
+ int key_len;
+ int obj_key_len = 0;
+ int key_type;
+ int src_iter_len;
+
+ src_iter = src;
+ src_iter_len = src_len;
+ key_iter = key;
+ value_len = src_iter_len;
+ do {
+ if ((delim = strchr(key_iter, '.')) != NULL) {
+ key_len = delim - key_iter;
+ key_type = JOBJECT;
+ key_next = key_iter;
+ if (0 == contain_arr(key_next, key_len, &arr_pre)) {
+ key_type = JARRAY;
+ obj_key_len = arr_pre - key_iter;
+ if (obj_key_len) {
+ value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0);
+ } else {
+ value = src_iter;
+ }
+ } else {
+ value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
+ }
+
+ if (NULL == value) {
+ return NULL;
+ }
+
+ if (key_type == JARRAY) {
+ if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) {
+ return NULL;
+ }
+ }
+ src_iter = value;
+ src_iter_len = value_len;
+ key_iter = delim + 1;
+
+ }
+ } while (delim);
+
+ key_len = strlen(key_iter);
+ key_next = key_iter;
+ key_type = JOBJECT;
+ if (0 == contain_arr(key_next, key_len, &arr_pre)) {
+ key_type = JARRAY;
+ obj_key_len = arr_pre - key_iter;
+ if (obj_key_len) {
+ value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0);
+ } else {
+ value = src_iter;
+ }
+ } else {
+ value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0);
+ }
+
+ if (NULL == value) {
+ return NULL;
+ }
+ if (key_type == JARRAY) {
+ if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) {
+ return NULL;
+ }
+ }
+ *val_len = value_len;
+ return value;
+}
+
+#endif /* #if WITH_JSON_TOKEN_EXT */
+#endif /* #if WITH_JSON_KEYS_OF */
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_json_parser.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_json_parser.h
new file mode 100644
index 00000000..4224964b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_json_parser.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef _INFRA_JSON_PARSER_H_
+#define _INFRA_JSON_PARSER_H_
+
+/* #include "iotx_utils_internal.h" */
+
+typedef struct JSON_NV {
+ int nLen;
+ int vLen;
+ int vType;
+ char *pN;
+ char *pV;
+} JSON_NV;
+
+/**
+The descriptions of the json value node type
+**/
+enum JSONTYPE {
+ JNONE = -1,
+ JSTRING = 0,
+ JOBJECT,
+ JARRAY,
+ JNUMBER,
+ JBOOLEAN,
+ JTYPEMAX
+};
+
+/**
+The error codes produced by the JSON parsers
+**/
+enum JSON_PARSE_CODE {
+ JSON_PARSE_ERR,
+ JSON_PARSE_OK,
+ JSON_PARSE_FINISH
+};
+
+/**
+The return codes produced by the JSON parsers
+**/
+enum JSON_PARSE_RESULT {
+ JSON_RESULT_ERR = -1,
+ JSON_RESULT_OK
+};
+
+typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType,
+ void *p_Result);
+
+/**
+* @brief Parse the JSON string, and iterate through all keys and values,
+* then handle the keys and values by callback function.
+*
+* @param[in] p_cJsonStr @n The JSON string
+* @param[in] iStrLen @n The JSON string length
+* @param[in] pfnCB @n Callback function
+* @param[out] p_CBData @n User data
+* @return JSON_RESULT_OK success, JSON_RESULT_ERR failed
+* @see None.
+* @note None.
+**/
+int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData);
+
+/**
+* @brief Get the value by a specified key from a json string
+*
+* @param[in] p_cJsonStr @n the JSON string
+* @param[in] iStrLen @n the JSON string length
+* @param[in] p_cName @n the specified key string
+* @param[out] p_iValueLen @n the value length
+* @param[out] p_iValueType @n the value type
+* @return A pointer to the value
+* @see None.
+* @note None.
+**/
+char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType);
+
+/**
+* @brief Get the value by a specified key from a json string
+*
+* @param[in] p_cJsonStr @n the JSON string
+* @param[in] iStrLen @n the JSON string length
+* @param[in] p_cName @n the specified key string
+* @param[in] p_cNameLen @n the specified key string length
+* @param[out] p_iValueLen @n the value length
+* @param[out] p_iValueType @n the value type
+* @return A pointer to the value
+* @see None.
+* @note None.
+**/
+char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen,
+ int *p_iValueType);
+
+/**
+ * @brief Get the JSON object point associate with a given type.
+ *
+ * @param[in] type @n The object type
+ * @param[in] str @n The JSON string
+ * @param[in] str_end @n The end point of Json string
+ * @returns The json object point with the given field type.
+ * @see None.
+ * @note None.
+ */
+char *json_get_object(int type, char *str, char *str_end);
+char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len, char **val, int *val_len,
+ int *val_type);
+
+/**
+ * @brief retrieve each key&value pair from the json string
+ *
+ * @param[in] str @n Json string to revolve
+ * @param[in] slen @n The length of json string
+ * @param[in] pos @n cursor
+ * @param[out] key @n pointer to the next Key object
+ * @param[out] klen @n Key object length
+ * @param[out] val @n pointer to the next Value object
+ * @param[out] vlen @n Value object length
+ * @param[out] vtype @n Value object type(digital, string, object, array)
+ * @see None.
+ * @note None.
+ */
+#define json_object_for_each_kv(str, slen, pos, key, klen, val, vlen, vtype) \
+ for (pos = json_get_object(JOBJECT, str, str + slen); \
+ pos != NULL && *pos!= 0 && (pos=json_get_next_object(JOBJECT, pos, str + slen , &key, &klen, &val, &vlen, &vtype))!=0; )
+
+/**
+ * @brief retrieve each entry from the json array
+ *
+ * @param[in] str @n Json array to revolve
+ * @param[in] slen @n the length of Json array
+ * @param[in] pos @n cursor
+ * @param[out] entry @n pointer to the next entry from the array
+ * @param[out] len @n entry length
+ * @param[out] type @n entry type(digital, string, object, array)
+ * @see None.
+ * @note None.
+ */
+#define json_array_for_each_entry(str, slen, pos, entry, len, type) \
+ for (pos = json_get_object(JARRAY, str, str + slen); \
+ pos != NULL && *pos!= 0 && (pos=json_get_next_object(JARRAY, ++pos, str + slen, 0, 0, &entry, &len, &type))!=0; )
+
+
+/**
+ * @brief backup the last character to register parameters,
+ * and set the end character with '\0'
+ *
+ * @param[in] json_str @n json string
+ * @param[in] str_len @n json string lenth
+ * @param[out] register @n used to backup the last character
+ * @see None.
+ * @note None.
+ */
+#define backup_json_str_last_char(json_str, str_len, register) { \
+ register = *((char *)json_str + str_len); \
+ *((char *)json_str + str_len) = '\0'; \
+ }
+
+/**
+ * @brief restore the last character from register parameters
+ *
+ * @param[in] json_str @n json string
+ * @param[in] str_len @n json string lenth
+ * @param[in] register @n used to restore the last character
+ * @see None.
+ * @note None.
+ */
+#define restore_json_str_last_char(json_str, str_len, register) { \
+ *((char *)json_str + str_len) = register; \
+ }
+
+char *LITE_json_value_of(char *key, char *src, ...);
+
+#endif /* __JSON_PARSER_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_list.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_list.h
new file mode 100644
index 00000000..b2d6c35e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_list.h
@@ -0,0 +1,346 @@
+
+#ifndef _INFRA_LIST_H_
+#define _INFRA_LIST_H_
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) || defined(__GNUC__)) && \
+ !defined(inline) && !defined(__cplusplus)
+ #define inline __inline
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Get offset of a member variable.
+ *
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the variable within the struct.
+ */
+#define aos_offsetof(type, member) ((size_t)&(((type *)0)->member))
+
+/*
+ * Get the struct for this entry.
+ *
+ * @param[in] ptr the list head to take the element from.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the variable within the struct.
+ */
+#define aos_container_of(ptr, type, member) \
+ ((type *) ((char *) (ptr) - aos_offsetof(type, member)))
+
+/* for double link list */
+typedef struct dlist_s {
+ struct dlist_s *prev;
+ struct dlist_s *next;
+} dlist_t;
+
+static inline void __dlist_add(dlist_t *node, dlist_t *prev, dlist_t *next)
+{
+ node->next = next;
+ node->prev = prev;
+
+ prev->next = node;
+ next->prev = node;
+}
+
+/*
+ * Get the struct for this entry.
+ *
+ * @param[in] addr the list head to take the element from.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the dlist_t within the struct.
+ */
+#define dlist_entry(addr, type, member) \
+ ((type *)((long)addr - aos_offsetof(type, member)))
+
+
+static inline void dlist_add(dlist_t *node, dlist_t *queue)
+{
+ __dlist_add(node, queue, queue->next);
+}
+
+static inline void dlist_add_tail(dlist_t *node, dlist_t *queue)
+{
+ __dlist_add(node, queue->prev, queue);
+}
+
+static inline void dlist_del(dlist_t *node)
+{
+ dlist_t *prev = node->prev;
+ dlist_t *next = node->next;
+
+ prev->next = next;
+ next->prev = prev;
+}
+
+static inline void dlist_init(dlist_t *node)
+{
+ node->next = node->prev = node;
+}
+
+static inline void INIT_AOS_DLIST_HEAD(dlist_t *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+static inline int dlist_empty(const dlist_t *head)
+{
+ return head->next == head;
+}
+
+/*
+ * Initialise the list.
+ *
+ * @param[in] list the list to be inited.
+ */
+#define AOS_DLIST_INIT(list) {&(list), &(list)}
+
+/*
+ * Get the first element from a list
+ *
+ * @param[in] ptr the list head to take the element from.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the dlist_t within the struct.
+ */
+#define dlist_first_entry(ptr, type, member) \
+ dlist_entry((ptr)->next, type, member)
+
+/*
+ * Iterate over a list.
+ *
+ * @param[in] pos the &struct dlist_t to use as a loop cursor.
+ * @param[in] head he head for your list.
+ */
+#define dlist_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/*
+ * Iterate over a list safe against removal of list entry.
+ *
+ * @param[in] pos the &struct dlist_t to use as a loop cursor.
+ * @param[in] n another &struct dlist_t to use as temporary storage.
+ * @param[in] head he head for your list.
+ */
+#define dlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/*
+ * Iterate over list of given type.
+ *
+ * @param[in] queue he head for your list.
+ * @param[in] node the &struct dlist_t to use as a loop cursor.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the dlist_t within the struct.
+ */
+#define dlist_for_each_entry(queue, node, type, member) \
+ for (node = aos_container_of((queue)->next, type, member); \
+ &node->member != (queue); \
+ node = aos_container_of(node->member.next, type, member))
+
+/*
+ * Iterate over list of given type safe against removal of list entry.
+ *
+ * @param[in] queue the head for your list.
+ * @param[in] n the type * to use as a temp.
+ * @param[in] node the type * to use as a loop cursor.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the dlist_t within the struct.
+ */
+#define dlist_for_each_entry_safe(queue, n, node, type, member) \
+ for (node = aos_container_of((queue)->next, type, member), \
+ n = (queue)->next ? (queue)->next->next : NULL; \
+ &node->member != (queue); \
+ node = aos_container_of(n, type, member), n = n ? n->next : NULL)
+
+/*
+ * Get the struct for this entry.
+ * @param[in] ptr the list head to take the element from.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the variable within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ aos_container_of(ptr, type, member)
+
+
+/*
+ * Iterate backwards over list of given type.
+ *
+ * @param[in] pos the type * to use as a loop cursor.
+ * @param[in] head he head for your list.
+ * @param[in] member the name of the dlist_t within the struct.
+ * @param[in] type the type of the struct this is embedded in.
+ */
+#define dlist_for_each_entry_reverse(pos, head, member, type) \
+ for (pos = list_entry((head)->prev, type, member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, type, member))
+
+
+/*
+ * Get the list length.
+ *
+ * @param[in] queue the head for your list.
+ */
+static inline int __dlist_entry_number(dlist_t *queue)
+{
+ int num;
+ dlist_t *cur = queue;
+ for (num = 0; cur->next != queue; cur = cur->next, num++)
+ ;
+
+ return num;
+}
+
+/*
+ * Get the list length.
+ *
+ * @param[in] queue the head for your list.
+ */
+#define dlist_entry_number(head) \
+ __dlist_entry_number(head)
+
+/*
+ * Initialise the list.
+ *
+ * @param[in] name the list to be initialized.
+ */
+#define AOS_DLIST_HEAD_INIT(name) { &(name), &(name) }
+
+/*
+ * Initialise the list.
+ *
+ * @param[in] name the list to be initialized.
+ */
+#define AOS_DLIST_HEAD(name) \
+ dlist_t name = AOS_DLIST_HEAD_INIT(name)
+
+/* for single link list */
+typedef struct slist_s {
+ struct slist_s *next;
+} slist_t;
+
+static inline void slist_add(slist_t *node, slist_t *head)
+{
+ node->next = head->next;
+ head->next = node;
+}
+
+static inline void slist_add_tail(slist_t *node, slist_t *head)
+{
+ while (head->next) {
+ head = head->next;
+ }
+
+ slist_add(node, head);
+}
+
+static inline void slist_del(slist_t *node, slist_t *head)
+{
+ while (head->next) {
+ if (head->next == node) {
+ head->next = node->next;
+ break;
+ }
+
+ head = head->next;
+ }
+}
+
+static inline int slist_empty(const slist_t *head)
+{
+ return !head->next;
+}
+
+static inline void slist_init(slist_t *head)
+{
+ head->next = 0;
+}
+
+/*
+* Iterate over list of given type.
+*
+* @param[in] queue he head for your list.
+* @param[in] node the type * to use as a loop cursor.
+* @param[in] type the type of the struct this is embedded in.
+* @param[in] member the name of the slist_t within the struct.
+*/
+#define slist_for_each_entry(queue, node, type, member) \
+ for (node = aos_container_of((queue)->next, type, member); \
+ &node->member; \
+ node = aos_container_of(node->member.next, type, member))
+
+/*
+ * Iterate over list of given type safe against removal of list entry.
+ *
+ * @param[in] queue the head for your list.
+ * @param[in] tmp the type * to use as a temp.
+ * @param[in] node the type * to use as a loop cursor.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the slist_t within the struct.
+ */
+#define slist_for_each_entry_safe(queue, tmp, node, type, member) \
+ for (node = aos_container_of((queue)->next, type, member), \
+ tmp = (queue)->next ? (queue)->next->next : NULL; \
+ &node->member; \
+ node = aos_container_of(tmp, type, member), tmp = tmp ? tmp->next : tmp)
+
+/*
+ * Initialise the list.
+ *
+ * @param[in] name the list to be initialized.
+ */
+#define AOS_SLIST_HEAD_INIT(name) {0}
+
+/*
+ * Initialise the list.
+ *
+ * @param[in] name the list to be initialized.
+ */
+#define AOS_SLIST_HEAD(name) \
+ slist_t name = AOS_SLIST_HEAD_INIT(name)
+
+/*
+ * Get the struct for this entry.
+ * @param[in] addr the list head to take the element from.
+ * @param[in] type the type of the struct this is embedded in.
+ * @param[in] member the name of the slist_t within the struct.
+ */
+#define slist_entry(addr, type, member) ( \
+ addr ? (type *)((long)addr - aos_offsetof(type, member)) : (type *)addr \
+ )
+
+/*
+* Get the first element from a list.
+*
+* @param[in] ptr the list head to take the element from.
+* @param[in] type the type of the struct this is embedded in.
+* @param[in] member the name of the slist_t within the struct.
+*/
+#define slist_first_entry(ptr, type, member) \
+ slist_entry((ptr)->next, type, member)
+
+/*
+ * Get the list length.
+ *
+ * @param[in] queue the head for your list.
+ */
+static inline int slist_entry_number(slist_t *queue)
+{
+ int num;
+ slist_t *cur = queue;
+ for (num = 0; cur->next; cur = cur->next, num++)
+ ;
+
+ return num;
+}
+
+#include "infra_compat.h"
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_LIST_H */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_log.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_log.c
new file mode 100644
index 00000000..add4f6ee
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_log.c
@@ -0,0 +1,266 @@
+#include "infra_config.h"
+
+extern void **LITE_get_mem_mutex(void);
+extern void *HAL_MutexCreate(void);
+extern void HAL_MutexDestroy(void *);
+
+#include
+#include
+#include "infra_compat.h"
+#include "infra_log.h"
+#if defined(INFRA_CJSON)
+ #include "infra_cjson.h"
+#endif
+
+#if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED)
+static log_client logcb = {
+ .name = "linkkit",
+ .priority = LOG_DEBUG_LEVEL,
+ .text_buf = {0}
+};
+
+static char *lvl_names[] = {
+ "non", "crt", "err", "wrn", "inf", "dbg", "flw"
+};
+
+/* 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. */
+char *lvl_color[] = {
+ "[0m", "[1;31m", "[1;31m", "[1;35m", "[1;33m", "[1;36m", "[1;37m"
+};
+
+void LITE_syslog_routine(char *m, const char *f, const int l, const int level, const char *fmt, va_list *params)
+{
+ char *tmpbuf = logcb.text_buf;
+ char *o = tmpbuf;
+ int truncated = 0;
+
+ if (LITE_get_loglevel() < level || level < LOG_NONE_LEVEL) {
+ return;
+ }
+
+#if !defined(_WIN32)
+ LITE_printf("%s%s", "\033", lvl_color[level]);
+ LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l);
+#endif /* #if !defined(_WIN32) */
+
+ memset(tmpbuf, 0, sizeof(logcb.text_buf));
+
+ o = tmpbuf;
+ o += LITE_vsnprintf(o, LOG_MSG_MAXLEN + 1, fmt, *params);
+
+ if (o - tmpbuf > LOG_MSG_MAXLEN) {
+ o = tmpbuf + strlen(tmpbuf);
+ truncated = 1;
+ }
+ if (strlen(tmpbuf) == LOG_MSG_MAXLEN) {
+ truncated = 1;
+ }
+
+ LITE_printf("%s", tmpbuf);
+ if (truncated) {
+ LITE_printf(" ...");
+ }
+
+ if (tmpbuf[strlen(tmpbuf) - 1] != '\n') {
+ LITE_printf("\r\n");
+ }
+
+#if !defined(_WIN32)
+ LITE_printf("%s", "\033[0m");
+#endif /* #if !defined(_WIN32) */
+ return;
+}
+
+void LITE_syslog(char *m, const char *f, const int l, const int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ LITE_syslog_routine(m, f, l, level, fmt, &ap);
+ va_end(ap);
+}
+
+int LITE_get_loglevel(void)
+{
+ return logcb.priority;
+}
+
+void LITE_set_loglevel(int pri)
+{
+ void **mutex = NULL;
+ logcb.priority = pri;
+
+#if WITH_MEM_STATS
+ mutex = LITE_get_mem_mutex();
+ if (pri != LOG_NONE_LEVEL) {
+ if (*mutex == NULL) {
+ *mutex = HAL_MutexCreate();
+ if (*mutex == NULL) {
+ LITE_printf("\nCreate memStats mutex error\n");
+ }
+ }
+ } else if (*mutex != NULL) {
+ HAL_MutexDestroy(*mutex);
+ *mutex = NULL;
+ }
+#endif
+}
+
+void LITE_rich_hexdump(const char *f, const int l,
+ const int level,
+ const char *buf_str,
+ const void *buf_ptr,
+ const int buf_len)
+{
+ if (LITE_get_loglevel() < level) {
+ return;
+ }
+
+ LITE_printf("%s%s", "\033", lvl_color[level]);
+ LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l);
+ LITE_printf("HEXDUMP %s @ %p[%d]\r\n", buf_str, buf_ptr, buf_len);
+ LITE_hexdump(buf_str, buf_ptr, buf_len);
+
+ LITE_printf("%s", "\033[0m");
+ return;
+}
+
+int log_multi_line_internal(const char *f, const int l,
+ const char *title, int level, char *payload, const char *mark)
+{
+ const char *pos;
+ const char *endl;
+ int i;
+
+ if (LITE_get_loglevel() < level) {
+ return 1;
+ }
+
+ LITE_printf("[%s] %s(%d): %s (Length: %d Bytes)\r\n",
+ lvl_names[LITE_get_loglevel()], f, l, title, (int)strlen(payload));
+
+ pos = payload;
+ while (pos && *pos) {
+ LITE_printf("%s ", mark);
+
+ if (*pos == '\r') {
+ LITE_printf("\r\n");
+ pos += 2;
+ continue;
+ }
+
+ endl = strchr(pos + 1, '\r');
+ if (endl == NULL) {
+ endl = pos;
+ do {
+ ++endl;
+ } while (*endl);
+ }
+
+ for (i = 0; i < endl - pos; ++i) {
+ LITE_printf("%c", pos[i]);
+ }
+ LITE_printf("\r\n");
+
+ pos = *endl ? endl + 2 : 0;
+ }
+
+ return 0;
+}
+
+#define LITE_HEXDUMP_DRAWLINE(start_mark, len, end_mark) \
+ do { \
+ int i; \
+ \
+ LITE_printf("%s", start_mark); \
+ for(i = 0; i < len; ++i) { LITE_printf("-"); } \
+ LITE_printf("%s", end_mark); \
+ LITE_printf("\r\n"); \
+ \
+ } while(0)
+
+int LITE_hexdump(const char *title, const void *buff, const int len)
+{
+ int i, j, written;
+ unsigned char ascii[20] = {0};
+ char header[64] = {0};
+ unsigned char *buf = (unsigned char *)buff;
+
+ LITE_snprintf(header, sizeof(header), "| %s: (len=%d) |\r\n", title, (int)len);
+
+ LITE_HEXDUMP_DRAWLINE("+", strlen(header) - 4, "+");
+ LITE_printf("%s", header);
+ LITE_printf("%s\r\n", HEXDUMP_SEP_LINE);
+
+ written = 0;
+ for (i = 0; i < len; ++ i) {
+ if (i % 16 == 0) {
+ LITE_printf("| %08X: ", (unsigned int)(i + (long)buff));
+ written += 8;
+ }
+
+ LITE_printf("%02X", buf[i]);
+ written += 2;
+
+ if (i % 2 == 1) {
+ LITE_printf(" ");
+ written += 1;
+ }
+ LITE_snprintf((char *)ascii + i % 16, (1 + 1), "%c", ((buf[i] >= ' ' && buf[i] <= '~') ? buf[i] : '.'));
+
+ if (((i + 1) % 16 == 0) || (i == len - 1)) {
+ for (j = 0; j < 48 - written; ++j) {
+ LITE_printf(" ");
+ }
+
+ LITE_printf(" %s", ascii);
+ LITE_printf("\r\n");
+
+ written = 0;
+ memset(ascii, 0, sizeof(ascii));
+ }
+ }
+ LITE_printf("%s\r\n", HEXDUMP_SEP_LINE);
+
+ return 0;
+}
+
+void IOT_SetLogLevel(IOT_LogLevel level)
+{
+ int lvl = (int)level;
+
+ if (lvl > LOG_DEBUG_LEVEL) {
+ HAL_Printf("Invalid input level: %d out of [%d, %d]", level,
+ LOG_NONE_LEVEL,
+ LOG_DEBUG_LEVEL);
+ return;
+ }
+
+ LITE_set_loglevel(lvl);
+ HAL_Printf("[prt] log level set as: [ %d ]\r\n", lvl);
+}
+
+#else
+
+void IOT_SetLogLevel(IOT_LogLevel level)
+{
+ return;
+}
+
+int log_multi_line_internal(const char *f, const int l,
+ const char *title, int level, char *payload, const char *mark)
+{
+ return 0;
+}
+
+void LITE_rich_hexdump(const char *f, const int l,
+ const int level,
+ const char *buf_str,
+ const void *buf_ptr,
+ const int buf_len)
+{
+ return;
+}
+
+#endif /* #if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED) */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_log.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_log.h
new file mode 100644
index 00000000..1a8572ea
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_log.h
@@ -0,0 +1,119 @@
+#ifndef _INFRA_LOG_H_
+#define _INFRA_LOG_H_
+
+#include
+#include "infra_defs.h"
+
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+void HAL_Printf(const char *fmt, ...);
+int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap);
+
+#define LITE_printf HAL_Printf
+#define LITE_snprintf HAL_Snprintf
+#define LITE_vsnprintf HAL_Vsnprintf
+#define LITE_LOG_ENABLED
+
+#define LOG_MSG_MAXLEN (255)
+#define LOG_MOD_NAME_LEN (7)
+#define LOG_PREFIX_FMT "[%s] %s(%d): "
+
+#define HEXDUMP_SEP_LINE "+" \
+ "-----------------------" \
+ "-----------------------" \
+ "-----------------------"
+
+#if defined(_PLATFORM_IS_LINUX_)
+ #undef LOG_MSG_MAXLEN
+ #define LOG_MSG_MAXLEN (512)
+#endif
+
+typedef struct {
+ char name[LOG_MOD_NAME_LEN + 1];
+ int priority;
+ char text_buf[LOG_MSG_MAXLEN + 1];
+} log_client;
+
+int LITE_get_loglevel(void);
+void LITE_set_loglevel(int level);
+int LITE_hexdump(const char *title, const void *buf, const int len);
+
+void LITE_syslog_routine(char *m, const char *f, const int l, const int level, const char *fmt, va_list *params);
+void LITE_syslog(char *m, const char *f, const int l, const int level, const char *fmt, ...);
+
+#define LOG_NONE_LEVEL (0) /* no log printed at all */
+#define LOG_CRIT_LEVEL (1) /* current application aborting */
+#define LOG_ERR_LEVEL (2) /* current app-module error */
+#define LOG_WARNING_LEVEL (3) /* using default parameters */
+#define LOG_INFO_LEVEL (4) /* running messages */
+#define LOG_DEBUG_LEVEL (5) /* debugging messages */
+#define LOG_FLOW_LEVEL (6) /* code/packet flow messages */
+
+#if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED)
+ #if defined(INFRA_LOG_MUTE_FLW)
+ #define log_flow(mod, ...)
+ #else
+ #define log_flow(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_FLOW_LEVEL, __VA_ARGS__)
+ #endif
+
+ #if defined(INFRA_LOG_MUTE_DBG)
+ #define log_debug(mod, ...)
+ #else
+ #define log_debug(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_DEBUG_LEVEL, __VA_ARGS__)
+ #endif
+
+ #if defined(INFRA_LOG_MUTE_INF)
+ #define log_info(mod, ...)
+ #else
+ #define log_info(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_INFO_LEVEL, __VA_ARGS__)
+ #endif
+
+ #if defined(INFRA_LOG_MUTE_WRN)
+ #define log_warning(mod, ...)
+ #else
+ #define log_warning(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_WARNING_LEVEL, __VA_ARGS__)
+ #endif
+
+ #if defined(INFRA_LOG_MUTE_ERR)
+ #define log_err(mod, ...)
+ #else
+ #define log_err(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_ERR_LEVEL, __VA_ARGS__)
+ #endif
+
+ #if defined(INFRA_LOG_MUTE_CRT)
+ #define log_crit(mod, ...)
+ #else
+ #define log_crit(mod, ...) LITE_syslog(mod, __FUNCTION__, __LINE__, LOG_CRIT_LEVEL, __VA_ARGS__)
+ #endif
+#else /* #if defined(INFRA_LOG) */
+
+ #define log_flow(mod, ...)
+ #define log_debug(mod, ...)
+ #define log_info(mod, ...)
+ #define log_warning(mod, ...)
+ #define log_err(mod, ...)
+ #define log_crit(mod, ...)
+
+#endif
+
+int log_multi_line_internal(const char *f, const int l,
+ const char *title, int level, char *payload, const char *mark);
+#define log_multi_line(level, title, fmt, payload, mark) \
+ log_multi_line_internal(__func__, __LINE__, title, level, payload, mark)
+
+void LITE_rich_hexdump(const char *f, const int l,
+ const int level,
+ const char *buf_str,
+ const void *buf_ptr,
+ const int buf_len
+ );
+
+#define HEXDUMP_DEBUG(buf, len) \
+ LITE_rich_hexdump(__func__, __LINE__, LOG_DEBUG_LEVEL, #buf, (const void *)buf, (const int)len)
+
+#define HEXDUMP_INFO(buf, len) \
+ LITE_rich_hexdump(__func__, __LINE__, LOG_INFO_LEVEL, #buf, (const void *)buf, (const int)len)
+
+int iotx_facility_json_print(const char *str, int level, ...);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_md5.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_md5.c
new file mode 100644
index 00000000..cd8dc648
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_md5.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_MD5
+
+#include
+#include
+
+#include "infra_md5.h"
+
+#define MD5_KEY_IOPAD_SIZE (64)
+#define MD5_DIGEST_SIZE (16)
+
+/* Implementation that should never be optimized out by the compiler */
+static void utils_md5_zeroize(void *v, size_t n)
+{
+ volatile unsigned char *p = v;
+ while (n--) {
+ *p++ = 0;
+ }
+}
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef IOT_MD5_GET_UINT32_LE
+#define IOT_MD5_GET_UINT32_LE(n,b,i) \
+ { \
+ (n) = ( (uint32_t) (b)[(i) ] ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
+ }
+#endif
+
+#ifndef IOT_MD5_PUT_UINT32_LE
+#define IOT_MD5_PUT_UINT32_LE(n,b,i) \
+ { \
+ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
+ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
+ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
+ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
+ }
+#endif
+
+void utils_md5_init(iot_md5_context *ctx)
+{
+ memset(ctx, 0, sizeof(iot_md5_context));
+}
+
+void utils_md5_free(iot_md5_context *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ utils_md5_zeroize(ctx, sizeof(iot_md5_context));
+}
+
+void utils_md5_clone(iot_md5_context *dst,
+ const iot_md5_context *src)
+{
+ *dst = *src;
+}
+
+/*
+ * MD5 context setup
+ */
+void utils_md5_starts(iot_md5_context *ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+}
+
+void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64])
+{
+ uint32_t X[16], A, B, C, D;
+
+ IOT_MD5_GET_UINT32_LE(X[ 0], data, 0);
+ IOT_MD5_GET_UINT32_LE(X[ 1], data, 4);
+ IOT_MD5_GET_UINT32_LE(X[ 2], data, 8);
+ IOT_MD5_GET_UINT32_LE(X[ 3], data, 12);
+ IOT_MD5_GET_UINT32_LE(X[ 4], data, 16);
+ IOT_MD5_GET_UINT32_LE(X[ 5], data, 20);
+ IOT_MD5_GET_UINT32_LE(X[ 6], data, 24);
+ IOT_MD5_GET_UINT32_LE(X[ 7], data, 28);
+ IOT_MD5_GET_UINT32_LE(X[ 8], data, 32);
+ IOT_MD5_GET_UINT32_LE(X[ 9], data, 36);
+ IOT_MD5_GET_UINT32_LE(X[10], data, 40);
+ IOT_MD5_GET_UINT32_LE(X[11], data, 44);
+ IOT_MD5_GET_UINT32_LE(X[12], data, 48);
+ IOT_MD5_GET_UINT32_LE(X[13], data, 52);
+ IOT_MD5_GET_UINT32_LE(X[14], data, 56);
+ IOT_MD5_GET_UINT32_LE(X[15], data, 60);
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define P(a,b,c,d,k,s,t) \
+ { \
+ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+ P(A, B, C, D, 0, 7, 0xD76AA478);
+ P(D, A, B, C, 1, 12, 0xE8C7B756);
+ P(C, D, A, B, 2, 17, 0x242070DB);
+ P(B, C, D, A, 3, 22, 0xC1BDCEEE);
+ P(A, B, C, D, 4, 7, 0xF57C0FAF);
+ P(D, A, B, C, 5, 12, 0x4787C62A);
+ P(C, D, A, B, 6, 17, 0xA8304613);
+ P(B, C, D, A, 7, 22, 0xFD469501);
+ P(A, B, C, D, 8, 7, 0x698098D8);
+ P(D, A, B, C, 9, 12, 0x8B44F7AF);
+ P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+ P(B, C, D, A, 11, 22, 0x895CD7BE);
+ P(A, B, C, D, 12, 7, 0x6B901122);
+ P(D, A, B, C, 13, 12, 0xFD987193);
+ P(C, D, A, B, 14, 17, 0xA679438E);
+ P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+ P(A, B, C, D, 1, 5, 0xF61E2562);
+ P(D, A, B, C, 6, 9, 0xC040B340);
+ P(C, D, A, B, 11, 14, 0x265E5A51);
+ P(B, C, D, A, 0, 20, 0xE9B6C7AA);
+ P(A, B, C, D, 5, 5, 0xD62F105D);
+ P(D, A, B, C, 10, 9, 0x02441453);
+ P(C, D, A, B, 15, 14, 0xD8A1E681);
+ P(B, C, D, A, 4, 20, 0xE7D3FBC8);
+ P(A, B, C, D, 9, 5, 0x21E1CDE6);
+ P(D, A, B, C, 14, 9, 0xC33707D6);
+ P(C, D, A, B, 3, 14, 0xF4D50D87);
+ P(B, C, D, A, 8, 20, 0x455A14ED);
+ P(A, B, C, D, 13, 5, 0xA9E3E905);
+ P(D, A, B, C, 2, 9, 0xFCEFA3F8);
+ P(C, D, A, B, 7, 14, 0x676F02D9);
+ P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+ P(A, B, C, D, 5, 4, 0xFFFA3942);
+ P(D, A, B, C, 8, 11, 0x8771F681);
+ P(C, D, A, B, 11, 16, 0x6D9D6122);
+ P(B, C, D, A, 14, 23, 0xFDE5380C);
+ P(A, B, C, D, 1, 4, 0xA4BEEA44);
+ P(D, A, B, C, 4, 11, 0x4BDECFA9);
+ P(C, D, A, B, 7, 16, 0xF6BB4B60);
+ P(B, C, D, A, 10, 23, 0xBEBFBC70);
+ P(A, B, C, D, 13, 4, 0x289B7EC6);
+ P(D, A, B, C, 0, 11, 0xEAA127FA);
+ P(C, D, A, B, 3, 16, 0xD4EF3085);
+ P(B, C, D, A, 6, 23, 0x04881D05);
+ P(A, B, C, D, 9, 4, 0xD9D4D039);
+ P(D, A, B, C, 12, 11, 0xE6DB99E5);
+ P(C, D, A, B, 15, 16, 0x1FA27CF8);
+ P(B, C, D, A, 2, 23, 0xC4AC5665);
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+ P(A, B, C, D, 0, 6, 0xF4292244);
+ P(D, A, B, C, 7, 10, 0x432AFF97);
+ P(C, D, A, B, 14, 15, 0xAB9423A7);
+ P(B, C, D, A, 5, 21, 0xFC93A039);
+ P(A, B, C, D, 12, 6, 0x655B59C3);
+ P(D, A, B, C, 3, 10, 0x8F0CCC92);
+ P(C, D, A, B, 10, 15, 0xFFEFF47D);
+ P(B, C, D, A, 1, 21, 0x85845DD1);
+ P(A, B, C, D, 8, 6, 0x6FA87E4F);
+ P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+ P(C, D, A, B, 6, 15, 0xA3014314);
+ P(B, C, D, A, 13, 21, 0x4E0811A1);
+ P(A, B, C, D, 4, 6, 0xF7537E82);
+ P(D, A, B, C, 11, 10, 0xBD3AF235);
+ P(C, D, A, B, 2, 15, 0x2AD7D2BB);
+ P(B, C, D, A, 9, 21, 0xEB86D391);
+
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+}
+
+/*
+ * MD5 process buffer
+ */
+void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen)
+{
+ uint32_t fill;
+ uint32_t left;
+
+ if (ilen == 0) {
+ return;
+ }
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < (uint32_t) ilen) {
+ ctx->total[1]++;
+ }
+
+ if (left && ilen >= fill) {
+ memcpy((void *)(ctx->buffer + left), input, fill);
+ utils_md5_process(ctx, ctx->buffer);
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while (ilen >= 64) {
+ utils_md5_process(ctx, input);
+ input += 64;
+ ilen -= 64;
+ }
+
+ if (ilen > 0) {
+ memcpy((void *)(ctx->buffer + left), input, ilen);
+ }
+}
+
+static const unsigned char iot_md5_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * MD5 final digest
+ */
+void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16])
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = (ctx->total[0] >> 29)
+ | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ IOT_MD5_PUT_UINT32_LE(low, msglen, 0);
+ IOT_MD5_PUT_UINT32_LE(high, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ utils_md5_update(ctx, iot_md5_padding, padn);
+ utils_md5_update(ctx, msglen, 8);
+
+ IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0);
+ IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4);
+ IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8);
+ IOT_MD5_PUT_UINT32_LE(ctx->state[3], output, 12);
+}
+
+
+/*
+ * output = MD5( input buffer )
+ */
+void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16])
+{
+ iot_md5_context ctx;
+
+ utils_md5_init(&ctx);
+ utils_md5_starts(&ctx);
+ utils_md5_update(&ctx, input, ilen);
+ utils_md5_finish(&ctx, output);
+ utils_md5_free(&ctx);
+}
+
+static int8_t utils_hb2hex(uint8_t hb)
+{
+ hb = hb & 0xF;
+ return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
+}
+
+void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len)
+{
+ iot_md5_context context;
+ unsigned char k_ipad[MD5_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ unsigned char k_opad[MD5_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ unsigned char out[MD5_DIGEST_SIZE];
+ int i;
+
+ if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
+ return;
+ }
+
+ if (key_len > MD5_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < MD5_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner MD5 */
+ utils_md5_init(&context); /* init context for 1st pass */
+ utils_md5_starts(&context); /* setup context for 1st pass */
+ utils_md5_update(&context, k_ipad, MD5_KEY_IOPAD_SIZE); /* start with inner pad */
+ utils_md5_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
+ utils_md5_finish(&context, out); /* finish up 1st pass */
+
+ /* perform outer MD5 */
+ utils_md5_init(&context); /* init context for 2nd pass */
+ utils_md5_starts(&context); /* setup context for 2nd pass */
+ utils_md5_update(&context, k_opad, MD5_KEY_IOPAD_SIZE); /* start with outer pad */
+ utils_md5_update(&context, out, MD5_DIGEST_SIZE); /* then results of 1st hash */
+ utils_md5_finish(&context, out); /* finish up 2nd pass */
+
+ for (i = 0; i < MD5_DIGEST_SIZE; ++i) {
+ digest[i * 2] = utils_hb2hex(out[i] >> 4);
+ digest[i * 2 + 1] = utils_hb2hex(out[i]);
+ }
+}
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_md5.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_md5.h
new file mode 100644
index 00000000..f850163e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_md5.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef _INFRA_MD5_H_
+#define _INFRA_MD5_H_
+
+#include "infra_types.h"
+
+typedef struct {
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[4]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+} iot_md5_context;
+
+/**
+ * \brief Initialize MD5 context
+ *
+ * \param ctx MD5 context to be initialized
+ */
+void utils_md5_init(iot_md5_context *ctx);
+
+/**
+ * \brief Clear MD5 context
+ *
+ * \param ctx MD5 context to be cleared
+ */
+void utils_md5_free(iot_md5_context *ctx);
+
+/**
+ * \brief Clone (the state of) an MD5 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ */
+void utils_md5_clone(iot_md5_context *dst,
+ const iot_md5_context *src);
+
+/**
+ * \brief MD5 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void utils_md5_starts(iot_md5_context *ctx);
+
+/**
+ * \brief MD5 process buffer
+ *
+ * \param ctx MD5 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen);
+
+/**
+ * \brief MD5 final digest
+ *
+ * \param ctx MD5 context
+ * \param output MD5 checksum result
+ */
+void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]);
+
+/* Internal use */
+void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]);
+
+/**
+ * \brief Output = MD5( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output MD5 checksum result
+ */
+void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16]);
+
+void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_net.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_net.c
new file mode 100644
index 00000000..6aaf049b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_net.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "infra_config.h"
+
+#ifdef INFRA_NET
+#include
+#include
+#include "infra_defs.h"
+#include "infra_net.h"
+#include "wrappers_defs.h"
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define net_err(...) log_err("infra_net", __VA_ARGS__)
+#else
+ #define net_err(...)
+#endif
+
+
+
+/*** SSL connection ***/
+#ifdef SUPPORT_TLS
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define NET_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "infra_net")
+ #define NET_FREE(ptr) LITE_free(ptr)
+#else
+ #define NET_MALLOC(size) HAL_Malloc(size)
+ #define NET_FREE(ptr) HAL_Free(ptr)
+#endif
+
+static void *ssl_malloc(uint32_t size)
+{
+ return NET_MALLOC(size);
+}
+static void ssl_free(void *ptr)
+{
+ NET_FREE(ptr);
+}
+#endif
+
+#if defined(SUPPORT_TLS) || defined(SUPPORT_ITLS)
+uintptr_t HAL_SSL_Establish(const char *host, uint16_t port, const char *ca_crt, size_t ca_crt_len);
+int32_t HAL_SSL_Destroy(uintptr_t handle);
+int HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms);
+int HAL_SSL_Write(uintptr_t handle, const char *buf, int len, int timeout_ms);
+int HAL_SSLHooks_set(ssl_hooks_t *hooks);
+int HAL_GetProductKey(char *product_key);
+int HAL_GetProductSecret(char *product_secret);
+
+static int read_ssl(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return -1;
+ }
+
+ return HAL_SSL_Read((uintptr_t)pNetwork->handle, buffer, len, timeout_ms);
+}
+
+static int write_ssl(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return -1;
+ }
+
+ return HAL_SSL_Write((uintptr_t)pNetwork->handle, buffer, len, timeout_ms);
+}
+
+static int disconnect_ssl(utils_network_pt pNetwork)
+{
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return -1;
+ }
+
+ HAL_SSL_Destroy((uintptr_t)pNetwork->handle);
+ pNetwork->handle = 0;
+
+ return 0;
+}
+
+static int connect_ssl(utils_network_pt pNetwork)
+{
+ ssl_hooks_t ssl_hooks;
+
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return 1;
+ }
+
+#if defined(SUPPORT_ITLS)
+ char pkps[IOTX_PRODUCT_KEY_LEN + IOTX_PRODUCT_SECRET_LEN + 3] = {0};
+
+ HAL_GetProductKey(pkps);
+ int len = strlen(pkps);
+ HAL_GetProductSecret(pkps + len + 1);
+ len += strlen(pkps + len + 1) + 2;
+
+ if (0 != (pNetwork->handle = (intptr_t)HAL_SSL_Establish(
+ pNetwork->pHostAddress,
+ pNetwork->port,
+ pkps, len))) {
+ return 0;
+ }
+#else
+ memset(&ssl_hooks, 0, sizeof(ssl_hooks_t));
+ ssl_hooks.malloc = ssl_malloc;
+ ssl_hooks.free = ssl_free;
+
+ HAL_SSLHooks_set(&ssl_hooks);
+
+ if (0 != (pNetwork->handle = (intptr_t)HAL_SSL_Establish(
+ pNetwork->pHostAddress,
+ pNetwork->port,
+ pNetwork->ca_crt,
+ pNetwork->ca_crt_len + 1))) {
+ return 0;
+ }
+#endif
+ else {
+ /* TODO SHOLUD not remove this handle space */
+ /* The space will be freed by calling disconnect_ssl() */
+ /* utils_memory_free((void *)pNetwork->handle); */
+#ifdef INFRA_EVENT
+ iotx_event_post(IOTX_CONN_CLOUD_FAIL);
+#endif
+ return -1;
+ }
+}
+#elif defined(AT_TCP_ENABLED)
+uintptr_t AT_TCP_Establish(const char *host, uint16_t port);
+int AT_TCP_Destroy(uintptr_t fd);
+int32_t AT_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms);
+int32_t AT_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+/*** TCP connection ***/
+static int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ return AT_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
+}
+
+static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ return AT_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
+}
+
+static int disconnect_tcp(utils_network_pt pNetwork)
+{
+ if (pNetwork->handle == (uintptr_t)(-1)) {
+ net_err("Network->handle = -1");
+ return -1;
+ }
+
+ AT_TCP_Destroy(pNetwork->handle);
+ pNetwork->handle = (uintptr_t)(-1);
+ return 0;
+}
+
+static int connect_tcp(utils_network_pt pNetwork)
+{
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return 1;
+ }
+
+ pNetwork->handle = AT_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
+ if (pNetwork->handle == (uintptr_t)(-1)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+#else
+uintptr_t HAL_TCP_Establish(const char *host, uint16_t port);
+int HAL_TCP_Destroy(uintptr_t fd);
+int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms);
+int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+/*** TCP connection ***/
+static int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ return HAL_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
+}
+
+
+static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ return HAL_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
+}
+
+static int disconnect_tcp(utils_network_pt pNetwork)
+{
+ if (pNetwork->handle == (uintptr_t)(-1)) {
+ net_err("Network->handle = -1");
+ return -1;
+ }
+
+ HAL_TCP_Destroy(pNetwork->handle);
+ pNetwork->handle = (uintptr_t)(-1);
+ return 0;
+}
+
+static int connect_tcp(utils_network_pt pNetwork)
+{
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return 1;
+ }
+
+ pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
+ if (pNetwork->handle == (uintptr_t)(-1)) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* #ifdef SUPPORT_TLS */
+
+/****** network interface ******/
+int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ int ret = 0;
+#ifdef SUPPORT_TLS
+ if (NULL != pNetwork->ca_crt) {
+ ret = read_ssl(pNetwork, buffer, len, timeout_ms);
+ }
+#else
+ if (NULL == pNetwork->ca_crt) {
+#ifdef SUPPORT_ITLS
+ ret = read_ssl(pNetwork, buffer, len, timeout_ms);
+#else
+ ret = read_tcp(pNetwork, buffer, len, timeout_ms);
+#endif
+ }
+#endif
+ else {
+ ret = -1;
+ net_err("no method match!");
+ }
+
+ return ret;
+}
+
+int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ int ret = 0;
+#ifdef SUPPORT_TLS
+ if (NULL != pNetwork->ca_crt) {
+ ret = write_ssl(pNetwork, buffer, len, timeout_ms);
+ }
+#else
+ if (NULL == pNetwork->ca_crt) {
+#ifdef SUPPORT_ITLS
+ ret = write_ssl(pNetwork, buffer, len, timeout_ms);
+#else
+ ret = write_tcp(pNetwork, buffer, len, timeout_ms);
+#endif
+ }
+#endif
+
+ else {
+ ret = -1;
+ net_err("no method match!");
+ }
+
+ return ret;
+}
+
+int iotx_net_disconnect(utils_network_pt pNetwork)
+{
+ int ret = 0;
+#ifdef SUPPORT_TLS
+ if (NULL != pNetwork->ca_crt) {
+ ret = disconnect_ssl(pNetwork);
+ }
+#else
+ if (NULL == pNetwork->ca_crt) {
+#ifdef SUPPORT_ITLS
+ ret = disconnect_ssl(pNetwork);
+#else
+ ret = disconnect_tcp(pNetwork);
+#endif
+ }
+#endif
+ else {
+ ret = -1;
+ net_err("no method match!");
+ }
+
+ return ret;
+}
+
+int iotx_net_connect(utils_network_pt pNetwork)
+{
+ int ret = 0;
+#ifdef SUPPORT_TLS
+ if (NULL != pNetwork->ca_crt) {
+ ret = connect_ssl(pNetwork);
+ }
+#else
+ if (NULL == pNetwork->ca_crt) {
+#ifdef SUPPORT_ITLS
+ ret = connect_ssl(pNetwork);
+#else
+ ret = connect_tcp(pNetwork);
+#endif
+ }
+#endif
+ else {
+ ret = -1;
+ net_err("no method match!");
+ }
+
+ return ret;
+}
+
+int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt)
+{
+ if (!pNetwork || !host) {
+ net_err("parameter error! pNetwork=%p, host = %p", pNetwork, host);
+ return -1;
+ }
+ pNetwork->pHostAddress = host;
+ pNetwork->port = port;
+ pNetwork->ca_crt = ca_crt;
+
+ if (NULL == ca_crt) {
+ pNetwork->ca_crt_len = 0;
+ } else {
+ pNetwork->ca_crt_len = strlen(ca_crt);
+ }
+
+ pNetwork->handle = 0;
+ pNetwork->read = utils_net_read;
+ pNetwork->write = utils_net_write;
+ pNetwork->disconnect = iotx_net_disconnect;
+ pNetwork->connect = iotx_net_connect;
+
+ return 0;
+}
+
+#ifdef SUPPORT_TCP
+uintptr_t HAL_TCP_Establish(const char *host, uint16_t port);
+int HAL_TCP_Destroy(uintptr_t fd);
+int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms);
+int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+/*** TCP connection ***/
+static int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ return HAL_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
+}
+
+
+static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ return HAL_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
+}
+
+static int disconnect_tcp(utils_network_pt pNetwork)
+{
+ if (pNetwork->handle == (uintptr_t)(-1)) {
+ net_err("Network->handle = -1");
+ return -1;
+ }
+
+ HAL_TCP_Destroy(pNetwork->handle);
+ pNetwork->handle = (uintptr_t)(-1);
+ return 0;
+}
+
+static int connect_tcp(utils_network_pt pNetwork)
+{
+ if (NULL == pNetwork) {
+ net_err("network is null");
+ return 1;
+ }
+
+ pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
+ if (pNetwork->handle == (uintptr_t)(-1)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/****** network interface ******/
+int utils_net_tcp_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ int ret = 0;
+
+ if (NULL == pNetwork->ca_crt) {
+ ret = read_tcp(pNetwork, buffer, len, timeout_ms);
+ }
+ else {
+ ret = read_ssl(pNetwork, buffer, len, timeout_ms);
+ }
+
+ return ret;
+}
+
+int utils_net_tcp_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
+{
+ int ret = 0;
+
+ if (NULL == pNetwork->ca_crt) {
+ ret = write_tcp(pNetwork, buffer, len, timeout_ms);
+ }
+ else {
+ ret = write_ssl(pNetwork, buffer, len, timeout_ms);
+ }
+
+ return ret;
+}
+
+int iotx_net_tcp_disconnect(utils_network_pt pNetwork)
+{
+ int ret = 0;
+
+ if (NULL == pNetwork->ca_crt) {
+ ret = disconnect_tcp(pNetwork);
+ }
+ else {
+ ret = disconnect_ssl(pNetwork);
+ }
+
+ return ret;
+}
+
+int iotx_net_tcp_connect(utils_network_pt pNetwork)
+{
+ int ret = 0;
+ if (NULL == pNetwork->ca_crt) {
+ ret = connect_tcp(pNetwork);
+ }
+ else {
+ ret = connect_ssl(pNetwork);
+ }
+
+ return ret;
+}
+
+int iotx_net_tcp_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt)
+{
+ if (!pNetwork || !host) {
+ net_err("parameter error! pNetwork=%p, host = %p", pNetwork, host);
+ return -1;
+ }
+ pNetwork->pHostAddress = host;
+ pNetwork->port = port;
+ pNetwork->ca_crt = ca_crt;
+
+ if (NULL == ca_crt) {
+ pNetwork->ca_crt_len = 0;
+ } else {
+ pNetwork->ca_crt_len = strlen(ca_crt);
+ }
+
+ pNetwork->handle = 0;
+ pNetwork->read = utils_net_tcp_read;
+ pNetwork->write = utils_net_tcp_write;
+ pNetwork->disconnect = iotx_net_tcp_disconnect;
+ pNetwork->connect = iotx_net_tcp_connect;
+
+ return 0;
+}
+#endif
+
+#endif
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_net.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_net.h
new file mode 100644
index 00000000..1d716624
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_net.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _INFRA_NET_H_
+#define _INFRA_NET_H_
+
+#include "infra_types.h"
+
+/**
+ * @brief The structure of network connection(TCP or SSL).
+ * The user has to allocate memory for this structure.
+ */
+
+struct utils_network;
+typedef struct utils_network utils_network_t, *utils_network_pt;
+
+struct utils_network {
+ const char *pHostAddress;
+ uint16_t port;
+ uint16_t ca_crt_len;
+
+ /**< NULL, TCP connection; NOT NULL, SSL connection */
+ const char *ca_crt;
+ /**< NOT NULL,iTLS connection*/
+ char *product_key;
+ /**< connection handle: 0, NOT connection; NOT 0, handle of the connection */
+ uintptr_t handle;
+
+ /**< Read data from server function pointer. */
+ int (*read)(utils_network_pt, char *, uint32_t, uint32_t);
+
+ /**< Send data to server function pointer. */
+ int (*write)(utils_network_pt, const char *, uint32_t, uint32_t);
+
+ /**< Disconnect the network */
+ int (*disconnect)(utils_network_pt);
+
+ /**< Establish the network */
+ int (*connect)(utils_network_pt);
+};
+
+int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms);
+int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms);
+int iotx_net_disconnect(utils_network_pt pNetwork);
+int iotx_net_connect(utils_network_pt pNetwork);
+int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt);
+#ifdef SUPPORT_TCP
+int iotx_net_tcp_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt);
+#endif
+#endif /* IOTX_COMMON_NET_H */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_preauth.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_preauth.c
new file mode 100644
index 00000000..044dc575
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_preauth.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_PREAUTH
+
+#include
+#include
+#include
+
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_httpc.h"
+#include "infra_preauth.h"
+#include "infra_string.h"
+#include "dev_sign_api.h"
+
+#define PREAUTH_HTTP_REQ_LEN 300
+#define PREAUTH_HTTP_RSP_LEN 300
+
+#define PREAUTH_IOT_ID_MAXLEN (64)
+#define PREAUTH_IOT_TOKEN_MAXLEN (65)
+#define PREAUTH_IOT_HOST_MAXLEN (64)
+
+#ifndef CONFIG_GUIDER_AUTH_TIMEOUT
+ #define CONFIG_GUIDER_AUTH_TIMEOUT (10 * 1000)
+#endif
+
+#ifdef SUPPORT_TLS
+ extern const char *iotx_ca_crt;
+#endif
+
+int _preauth_assemble_auth_req_string(const iotx_dev_meta_info_t *dev_meta, const char *sign,
+ const char *device_id, char *request_buff, uint32_t buff_len)
+{
+ uint8_t i = 0;
+ const char *kv[][2] = {
+ { "productKey", NULL },
+ { "deviceName", NULL },
+ { "signmethod", "hmacsha256"},
+ { "sign", NULL },
+ { "version", "default" },
+ { "clientId", NULL },
+ { "timestamp", "2524608000000" },
+ { "resources", "mqtt" }
+ };
+
+ if (dev_meta == NULL || sign == NULL || device_id == NULL || request_buff == NULL) {
+ return FAIL_RETURN;
+ }
+
+ kv[0][1] = dev_meta->product_key;
+ kv[1][1] = dev_meta->device_name;
+ kv[3][1] = sign;
+ kv[5][1] = device_id;
+
+ for (i = 0; i < (sizeof(kv) / (sizeof(kv[0]))); i++) {
+ if ((strlen(request_buff) + strlen(kv[i][0]) + strlen(kv[i][1]) + 2) >=
+ buff_len) {
+ return FAIL_RETURN;
+ }
+
+ memcpy(request_buff + strlen(request_buff), kv[i][0], strlen(kv[i][0]));
+ memcpy(request_buff + strlen(request_buff), "=", 1);
+ memcpy(request_buff + strlen(request_buff), kv[i][1], strlen(kv[i][1]));
+ memcpy(request_buff + strlen(request_buff), "&", 1);
+ }
+
+ memset(request_buff + strlen(request_buff) - 1, '\0', 1);
+ return SUCCESS_RETURN;
+}
+
+static int _preauth_get_string_value(char *p_string, char *value_buff, uint32_t buff_len)
+{
+ char *p = p_string;
+ char *p_start = NULL;
+ char *p_end = NULL;
+ uint32_t len = 0;
+
+ while (*(++p) != ',' || *p != '}') {
+ if (*p == '\"') {
+ if (p_start) {
+ p_end = p;
+ break;
+ } else {
+ p_start = p + 1;
+ }
+ }
+ }
+
+ if (p_start == NULL || p_end == NULL) {
+ return FAIL_RETURN;
+ }
+
+ len = p_end - p_start;
+ if (len > buff_len) {
+ return FAIL_RETURN;
+ }
+
+ memcpy(value_buff, p_start, len);
+ return SUCCESS_RETURN;
+}
+
+static int _preauth_parse_auth_rsp_string(char *json_string, uint32_t string_len, iotx_sign_mqtt_t *output)
+{
+ int res = FAIL_RETURN;
+ char *p = json_string;
+ char *p_start, *p_end, *pt;
+ uint8_t len;
+ int code = 0;
+
+ while (p < (json_string + string_len)) {
+ while (*(++p) != ':') {
+ if (p >= (json_string + string_len)) {
+ if (code != 200) {
+ return FAIL_RETURN;
+ }
+ else {
+ return SUCCESS_RETURN;
+ }
+ }
+ }
+
+ pt = p;
+ p_start = p_end = NULL;
+ while (--pt > json_string) {
+ if (*pt == '\"') {
+ if (p_end != NULL) {
+ p_start = pt + 1;
+ break;
+ } else {
+ p_end = pt;
+ }
+ }
+ }
+
+ if (p_start == NULL || p_end == NULL) {
+ return FAIL_RETURN;
+ }
+ len = p_end - p_start;
+
+ if (strlen("code") == len && !memcmp(p_start, "code", len)) {
+ infra_str2int(++p, &code);
+ if (code != 200) {
+ return FAIL_RETURN;
+ }
+ } else if (strlen("iotId") == len && !memcmp(p_start, "iotId", len)) {
+ res = _preauth_get_string_value(p, output->username, PREAUTH_IOT_ID_MAXLEN);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+ } else if (strlen("iotToken") == len && !memcmp(p_start, "iotToken", len)) {
+ res = _preauth_get_string_value(p, output->password, PREAUTH_IOT_TOKEN_MAXLEN);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+ } else if (strlen("host") == len && !memcmp(p_start, "host", len)) {
+ res = _preauth_get_string_value(p, output->hostname, PREAUTH_IOT_HOST_MAXLEN);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+ } else if (strlen("port") == len && !memcmp(p_start, "port", len)) {
+ int port_temp;
+ infra_str2int(++p, &port_temp);
+ output->port = port_temp;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+int preauth_get_connection_info(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *dev_meta,
+ const char *sign, const char *device_id, iotx_sign_mqtt_t *preauth_output)
+{
+ char http_url[128] = "http://";
+ char http_url_frag[] = "/auth/devicename";
+#ifdef SUPPORT_TLS
+ int http_port = 443;
+#else
+ int http_port = 80;
+#endif
+ int res = FAIL_RETURN;
+ httpclient_t httpc;
+ httpclient_data_t httpc_data;
+ char request_buff[PREAUTH_HTTP_REQ_LEN] = {0};
+ char response_buff[PREAUTH_HTTP_RSP_LEN] = {0};
+
+ if (g_infra_http_domain[region] == NULL) {
+ return FAIL_RETURN;
+ }
+
+ memset(&httpc, 0, sizeof(httpclient_t));
+ memset(&httpc_data, 0, sizeof(httpclient_data_t));
+ memcpy(http_url + strlen(http_url), g_infra_http_domain[region], strlen(g_infra_http_domain[region]));
+ memcpy(http_url + strlen(http_url), http_url_frag, sizeof(http_url_frag));
+
+ httpc.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n";
+
+ _preauth_assemble_auth_req_string(dev_meta, sign, device_id, request_buff, sizeof(request_buff));
+
+ httpc_data.post_content_type = "application/x-www-form-urlencoded;charset=utf-8";
+ httpc_data.post_buf = request_buff;
+ httpc_data.post_buf_len = strlen(request_buff);
+ httpc_data.response_buf = response_buff;
+ httpc_data.response_buf_len = sizeof(response_buff);
+
+ res = httpclient_common(&httpc,
+ http_url,
+ http_port,
+#ifdef SUPPORT_TLS
+ iotx_ca_crt,
+#else
+ NULL,
+#endif
+ HTTPCLIENT_POST,
+ CONFIG_GUIDER_AUTH_TIMEOUT,
+ &httpc_data);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+ preauth_info("Downstream Payload:");
+ iotx_facility_json_print(response_buff, LOG_INFO_LEVEL, '<');
+#endif
+ res = _preauth_parse_auth_rsp_string(response_buff, strlen(response_buff), preauth_output);
+
+ return res;
+}
+
+#endif /* #ifdef MQTT_PRE_AUTH */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_preauth.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_preauth.h
new file mode 100644
index 00000000..61723fc3
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_preauth.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __INFRA_PREAUTH__
+#define __INFRA_PREAUTH__
+
+#include "infra_defs.h"
+#include "infra_types.h"
+#include "dev_sign_api.h"
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define preauth_err(...) log_err("preauth", __VA_ARGS__)
+ #define preauth_info(...) log_info("preauth", __VA_ARGS__)
+ #define preauth_debug(...) log_debug("preauth", __VA_ARGS__)
+#else
+ #define preauth_err(...)
+ #define preauth_info(...)
+ #define preauth_debug(...)
+#endif
+
+int preauth_get_connection_info(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *dev_meta,
+ const char *sign, const char *device_id, iotx_sign_mqtt_t *preauth_output);
+
+#endif /* #ifndef __INFRA_PREAUTH__ */
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_prt_nwk_payload.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_prt_nwk_payload.c
new file mode 100644
index 00000000..97c0bf9b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_prt_nwk_payload.c
@@ -0,0 +1,159 @@
+#include "infra_config.h"
+
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+#include
+#include
+#include "infra_log.h"
+#if defined(INFRA_CJSON)
+ #include "infra_cjson.h"
+#endif
+
+#define JSON_NEWLINE "\r\n"
+#define JSON_INDENT " "
+
+#define JSON_PRINT_NEWSTR HAL_Printf("%s", newstr);
+#define JSON_PRINT_NEWLINE \
+ do { \
+ HAL_Printf("%s", JSON_NEWLINE); \
+ if (mark == '>' || mark == '<' || mark == ':') { \
+ HAL_Printf("%c ", mark); \
+ } \
+ } while(0)
+
+/* 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. */
+static char *_color[] = {
+ "[0m", "[1;31m", "[1;31m", "[1;35m", "[1;33m", "[1;36m", "[1;37m"
+};
+
+int iotx_facility_json_print(const char *str, int level, ...)
+{
+ int length = 0;
+ char newstr[2];
+ int quoted = 0;
+ int escaped = 0;
+ int indent = 0;
+ int i = 0, j = 0;
+#if defined(INFRA_CJSON)
+ int res = -1;
+ lite_cjson_t lite;
+#endif
+ va_list ap;
+ int mark = ' ';
+
+ newstr[0] = 0x00;
+ newstr[1] = 0x00;
+
+ if (str == NULL || strlen(str) == 0) {
+ return -1;
+ }
+
+#if defined(INFRA_CJSON)
+ res = lite_cjson_parse(str, strlen(str), &lite);
+ if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite)) {
+ return -2;
+ }
+#endif
+
+ length = strlen(str);
+ HAL_Printf("%s%s", "\033", _color[level]);
+ va_start(ap, level);
+ mark = va_arg(ap, int);
+ JSON_PRINT_NEWLINE;
+ va_end(ap);
+
+ for (i = 0 ; i < length ; i++) {
+ char ch = str[i];
+ switch (ch) {
+ case '{':
+ case '[':
+ newstr[0] = ch;
+ JSON_PRINT_NEWSTR;
+
+ if (!quoted) {
+ JSON_PRINT_NEWLINE;
+
+ if (!(str[i + 1] == '}' || str[i + 1] == ']')) {
+ ++indent;
+
+ for (j = 0 ; j < indent ; j++) {
+ HAL_Printf("%s", JSON_INDENT);
+ }
+ }
+ }
+
+ break;
+
+ case '}':
+ case ']':
+ if (!quoted) {
+ if ((i > 0) && (!(str[i - 1] == '{' || str[i - 1] == '['))) {
+ JSON_PRINT_NEWLINE;
+ --indent;
+
+ for (j = 0 ; j < indent ; j++) {
+ HAL_Printf("%s", JSON_INDENT);
+ }
+ } else if ((i > 0) && ((str[i - 1] == '[' && ch == ']') || (str[i - 1] == '{' && ch == '}'))) {
+ for (j = 0 ; j < indent ; j++) {
+ HAL_Printf("%s", JSON_INDENT);
+ }
+ }
+ }
+
+ newstr[0] = ch;
+ JSON_PRINT_NEWSTR;
+
+ break;
+
+ case '"':
+ newstr[0] = ch;
+ JSON_PRINT_NEWSTR;
+ escaped = 1;
+
+ if (i > 0 && str[i - 1] == '\\') {
+ escaped = !escaped;
+ }
+
+ if (!escaped) {
+ quoted = !quoted;
+ }
+
+ break;
+
+ case ',':
+ newstr[0] = ch;
+ JSON_PRINT_NEWSTR;
+ if (!quoted) {
+ JSON_PRINT_NEWLINE;
+
+ for (j = 0 ; j < indent ; j++) {
+ HAL_Printf("%s", JSON_INDENT);
+ }
+ }
+
+ break;
+
+ case ':':
+ newstr[0] = ch;
+ JSON_PRINT_NEWSTR;
+ if (!quoted) {
+ HAL_Printf("%s", " ");
+ }
+
+ break;
+
+ default:
+ newstr[0] = ch;
+ JSON_PRINT_NEWSTR;
+
+ break;
+ }
+ }
+
+ HAL_Printf("%s", JSON_NEWLINE JSON_NEWLINE);
+ HAL_Printf("%s", "\033[0m");
+ return 0;
+}
+
+#endif /* #ifdef INFRA_LOG_NETWORK_PAYLOAD */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_redirect_region.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_redirect_region.c
new file mode 100644
index 00000000..7b699007
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_redirect_region.c
@@ -0,0 +1,384 @@
+#include "infra_config.h"
+
+#ifdef MQTT_COMM_ENABLED
+
+#include
+#include
+#include
+#include
+#include "infra_compat.h"
+
+#include "infra_json_parser.h"
+#include "iotx_mqtt_config.h"
+#include "mqtt_api.h"
+#include "coap_api.h"
+#include "infra_redirect_region.h"
+
+static iotx_conn_info_t iotx_redir_info = {0, 0, NULL, NULL, NULL, NULL, NULL};
+static int redirect_region_flag = 0;
+static int redirect_region_retry_cnt = 0;
+
+
+//#define REDIRECT_DEBUG
+//#define REDIRECT_DEBUG_TOPIC
+
+#define TOPIC_LENGTH (128)
+#define DATA_LENGTH (48)
+#define REDIRECT_IOT_ID_LEN (128)
+#define REDIRECT_IOT_TOKEN_LEN (64)
+#define REDIRECT_MAX_RETRY_CNT (3)
+
+#ifdef REDIRECT_DEBUG_TOPIC
+#define REDIRECT_SUB_TOPIC "/%s/%s/user/thing/bootstrap/config/push"
+#define REDIRECT_PUB_TOPIC "/%s/%s/user/thing/bootstrap/config/push_reply"
+#else
+#define REDIRECT_SUB_TOPIC "/sys/%s/%s/thing/bootstrap/config/push"
+#define REDIRECT_PUB_TOPIC "/sys/%s/%s/thing/bootstrap/config/push_reply"
+#endif
+#define REDIRECT_MSG_ID "id"
+#define REDIRECT_MSG_IOTID "params.iotId"
+#define REDIRECT_MSG_HOST "params.endpoint.mqtt.host"
+#define REDIRECT_MSG_PORT "params.endpoint.mqtt.port"
+#define REDIRECT_MSG_TOKEN "params.endpoint.mqtt.token"
+
+#define PUB_DATA_STR "{\"id\":%d,\"code\":%d,\"data\":{}}"
+
+#ifdef INFRA_LOG
+#include "infra_log.h"
+#define redirect_err(...) log_err("redirect", __VA_ARGS__)
+#define redirect_warn(...) log_warning("redirect", __VA_ARGS__)
+//#ifdef REDIRECT_DEBUG
+#define redirect_info(...) log_info("redirect", __VA_ARGS__)
+// #else
+// #define redirect_info(...)
+// #endif
+#else
+#define redirect_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define redirect_warn(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define redirect_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define REDIRECT_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "infra_redirect")
+ #define REDIRECT_FREE(ptr) LITE_free(ptr)
+#else
+ #define REDIRECT_MALLOC(size) HAL_Malloc(size)
+ #define REDIRECT_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#define MEM_MAGIC (0x1234)
+
+int HAL_GetProductKey(char *product_key);
+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]);
+
+enum _response_code
+{
+ SUCCESS = 200,
+ PARAM_ERROR = 2000,
+ JSON_PARSE_ERROR
+};
+
+iotx_conn_info_pt iotx_redirect_info_get(void)
+{
+ return &iotx_redir_info;
+}
+
+int iotx_device_info_get(iotx_device_info_t *device_info)
+{
+ if (device_info == NULL) {
+ return -1;
+ }
+ memset(device_info, 0x0, sizeof(iotx_device_info_t));
+ HAL_GetProductKey(device_info->product_key);
+ HAL_GetDeviceName(device_info->device_name);
+ HAL_GetDeviceSecret(device_info->device_secret);
+ // HAL_GetDeviceID(device_info->device_id);
+
+ return 0;
+}
+
+void iotx_redirect_info_release(void)
+{
+ redirect_region_flag = 0;
+
+ if (iotx_redir_info.host_name != NULL) {
+ REDIRECT_FREE(iotx_redir_info.host_name);
+ }
+ if (iotx_redir_info.username != NULL) {
+ REDIRECT_FREE(iotx_redir_info.username);
+ }
+ if (iotx_redir_info.password != NULL) {
+ REDIRECT_FREE(iotx_redir_info.password);
+ }
+ if (iotx_redir_info.client_id != NULL) {
+ REDIRECT_FREE(iotx_redir_info.client_id);
+ }
+ memset(&iotx_redir_info, 0, sizeof(iotx_redir_info));
+}
+
+int iotx_redirect_set_flag(int flag)
+{
+ redirect_region_flag = flag;
+ redirect_region_retry_cnt = 0;
+
+ return redirect_region_flag;
+}
+
+int iotx_redirect_get_flag(void)
+{
+ if(redirect_region_flag == 1){
+ if(redirect_region_retry_cnt <= REDIRECT_MAX_RETRY_CNT){
+ redirect_region_retry_cnt++;
+ }else{
+ redirect_region_retry_cnt = 0;
+ redirect_region_flag = 0;
+ }
+ }
+
+ return redirect_region_flag;
+}
+/*
+static int _response_cloud(int id, int code)
+{
+ int ret = 0;
+ char *p_topic = NULL;
+ char data[DATA_LENGTH] = {0};
+ iotx_device_info_t *p_device = NULL;
+
+ p_device = LITE_malloc(sizeof(iotx_device_info_t));
+ if (!p_device)
+ {
+ redirect_err("no mem");
+ goto ERROR;
+ }
+
+ ret = iotx_device_info_get(p_device);
+ if (ret < 0)
+ {
+ redirect_err("get device info err");
+ goto ERROR;
+ }
+
+ p_topic = LITE_malloc(TOPIC_LENGTH);
+ if (!p_topic)
+ {
+ redirect_err("no mem");
+ goto ERROR;
+ }
+
+ memset(p_topic, 0, TOPIC_LENGTH);
+ snprintf(p_topic, TOPIC_LENGTH, REDIRECT_PUB_TOPIC, p_device->product_key, p_device->device_name);
+ redirect_info("pub p_topic:%s", p_topic);
+
+ memset(data, 0, DATA_LENGTH);
+ snprintf(data, DATA_LENGTH, PUB_DATA_STR, id, code);
+
+ ret = IOT_MQTT_Publish_Simple(NULL, p_topic, IOTX_MQTT_QOS1, data, strlen(data));
+ERROR:
+ if (p_topic)
+ LITE_free(p_topic);
+ if (p_device)
+ LITE_free(p_device);
+
+ return ret;
+}
+*/
+static void redirect_msg_cb(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
+{
+ int id = 0;
+ int code = 200;
+ char *pvalue = NULL;
+ iotx_mqtt_topic_info_pt ptopic_info = NULL;
+
+ char port_str[6] = {0};
+ iotx_conn_info_pt conn = NULL;
+ char *payload = NULL;
+ void *callback = NULL;
+
+ redirect_info("-----------------------");
+ if (msg == NULL){
+ redirect_err("params error");
+ code = PARAM_ERROR;
+ goto ERROR;
+ }
+
+ ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;
+
+ if (ptopic_info == NULL){
+ redirect_err("params error");
+ code = PARAM_ERROR;
+ goto ERROR;
+ }
+
+ payload = (char *)ptopic_info->payload;
+ if(payload == NULL){
+ redirect_err("params error");
+ goto ERROR;
+ }
+
+ // print topic name and topic message
+ redirect_info("Event(%d)", msg->event_type);
+ if (msg->event_type != IOTX_MQTT_EVENT_PUBLISH_RECEIVED){
+ redirect_info("do nothing");
+ return;
+ }
+
+ #ifdef REDIRECT_DEBUG
+ redirect_info("Topic: '%.*s' (Length: %d)",
+ ptopic_info->topic_len,
+ ptopic_info->ptopic,
+ ptopic_info->topic_len);
+ redirect_info("Payload: '%.*s' (Length: %d)",
+ ptopic_info->payload_len,
+ ptopic_info->payload,
+ ptopic_info->payload_len);
+ #endif
+
+ iotx_redirect_info_release();
+
+ conn = iotx_redirect_info_get();
+ if(conn == NULL){
+ goto ERROR;
+ }
+
+
+ pvalue = LITE_json_value_of(REDIRECT_MSG_ID, payload, MEM_MAGIC,"redirect");
+ if (!pvalue){
+ redirect_err("id parse error");
+ code = JSON_PARSE_ERROR;
+ goto ERROR;
+ }
+
+ id = atoi(pvalue);
+ redirect_info("id=%d", id);
+
+ REDIRECT_FREE(pvalue);
+
+ pvalue = LITE_json_value_of(REDIRECT_MSG_IOTID, payload, MEM_MAGIC,"redirect");
+ if (!pvalue){
+ redirect_err("REDIRECT_MSG_IOTID parse error");
+ code = JSON_PARSE_ERROR;
+ goto ERROR;
+ }
+ redirect_info("iotid = %s", pvalue);
+ conn->username = pvalue;
+
+ pvalue = LITE_json_value_of(REDIRECT_MSG_TOKEN, payload, MEM_MAGIC,"redirect");
+ if (NULL == pvalue){
+ redirect_err("REDIRECT_MSG_TOKEN parse error");
+ code = JSON_PARSE_ERROR;
+ goto ERROR;
+ }
+ redirect_info("token=%s", pvalue);
+ conn->password = pvalue;
+
+ pvalue = LITE_json_value_of(REDIRECT_MSG_HOST, payload, MEM_MAGIC,"redirect");
+ if (NULL == pvalue){
+ redirect_err("REDIRECT_MSG_HOST parse error");
+ code = JSON_PARSE_ERROR;
+ goto ERROR;
+ }
+ redirect_info("host = %s", pvalue);
+ conn->host_name = pvalue;
+
+ pvalue = LITE_json_value_of(REDIRECT_MSG_PORT, payload, MEM_MAGIC,"redirect");
+ if (NULL == pvalue){
+ redirect_err("REDIRECT_MSG_PORT parse error");
+ code = JSON_PARSE_ERROR;
+ goto ERROR;
+ }
+ redirect_info("port=%s", pvalue);
+ strcpy(port_str, pvalue);
+ pvalue = NULL;
+ conn->port = atoi(port_str);
+ REDIRECT_FREE(pvalue);
+ pvalue = NULL;
+
+ iotx_redirect_set_flag(1);
+ redirect_info("set redirect region flag");
+
+ callback = iotx_event_callback(ITE_REDIRECT);
+ if (callback) {
+ ((int (*)(void))callback)();
+ }
+
+ERROR:
+ if (code != 200){
+ redirect_err("redirect parse error");
+ }
+
+ //_response_cloud(id, code);
+}
+
+int iotx_redirect_region_subscribe(void)
+{
+ int ret = 0;
+ char *p_topic = NULL;
+ iotx_device_info_t p_device;
+
+ ret = iotx_device_info_get(&p_device);
+ if (ret < 0){
+ redirect_err("get device info err");
+ goto ERROR;
+ }
+
+ p_topic = REDIRECT_MALLOC(TOPIC_LENGTH);
+ if (!p_topic){
+ redirect_err("no mem");
+ goto ERROR;
+ }
+
+ memset(p_topic, 0, TOPIC_LENGTH);
+ snprintf(p_topic, TOPIC_LENGTH, REDIRECT_SUB_TOPIC, p_device.product_key, p_device.device_name);
+ redirect_info("p_topic:%s", p_topic);
+
+ ret = IOT_MQTT_Subscribe(NULL, p_topic, IOTX_MQTT_QOS0, redirect_msg_cb, NULL);
+ if (ret < 0){
+ redirect_err("sub failed");
+ }else{
+ redirect_info("sub success");
+ }
+ return ret;
+
+ERROR:
+ if (p_topic){
+ REDIRECT_FREE(p_topic);
+ }
+
+ iotx_redirect_info_release();
+
+ return -1;
+}
+
+int iotx_redirect_get_iotId_iotToken(char *iot_id,char *iot_token,char *host,uint16_t *pport)
+{
+ iotx_conn_info_t *redir_conn = NULL;
+
+ redir_conn = iotx_redirect_info_get();
+
+ if(redir_conn == NULL ||
+ redir_conn->username == NULL ||
+ redir_conn->password == NULL ||
+ redir_conn->host_name == NULL ||
+ iot_id == NULL ||
+ iot_token == NULL ||
+ host == NULL||
+ pport == NULL){
+ return -1;
+ }
+
+ strcpy(iot_id, redir_conn->username);
+ strcpy(iot_token, redir_conn->password);
+ strcpy(host, redir_conn->host_name);
+ *pport = redir_conn->port;
+
+ return 0;
+}
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_redirect_region.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_redirect_region.h
new file mode 100644
index 00000000..3985a837
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_redirect_region.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _INFRA_REDIRECT_REGION_H_
+#define _INFRA_REDIRECT_REGION_H_
+
+#include "infra_types.h"
+
+int iotx_redirect_region_subscribe(void);
+int iotx_redirect_set_flag(int flag);
+int iotx_redirect_get_flag(void);
+int iotx_redirect_get_iotId_iotToken(char *iot_id,char *iot_token,char *host, uint16_t *pport);
+
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_report.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_report.c
new file mode 100644
index 00000000..a989ae90
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_report.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_REPORT
+
+#include
+#include
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_string.h"
+#include "infra_report.h"
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+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]);
+uint64_t HAL_UptimeMs(void);
+int HAL_GetFirmwareVersion(char *version);
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define SYS_REPORT_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "sys.report")
+ #define SYS_REPORT_FREE(ptr) LITE_free(ptr)
+#else
+ #define SYS_REPORT_MALLOC(size) HAL_Malloc(size)
+ #define SYS_REPORT_FREE(ptr) HAL_Free(ptr)
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define VERSION_DEBUG(...) log_debug("version", __VA_ARGS__)
+ #define VERSION_ERR(...) log_err("version", __VA_ARGS__)
+#else
+ #define VERSION_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define VERSION_ERR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+static unsigned int g_report_id = 0;
+
+int iotx_report_id(void)
+{
+ return g_report_id++;
+}
+
+static info_report_func_pt info_report_func = NULL;
+
+void iotx_set_report_func(info_report_func_pt func)
+{
+ info_report_func = func;
+}
+/* aos will implement this function */
+#if defined(BUILD_AOS)
+extern void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE]);
+#else
+void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE])
+{
+ const char *p_version = IOTX_SDK_VERSION;
+ int i = 0, j = 0;
+ unsigned char res = 0;
+
+ for (j = 0; j < 3; j++) {
+ for (res = 0; p_version[i] <= '9' && p_version[i] >= '0'; i++) {
+ res = res * 10 + p_version[i] - '0';
+ }
+ version[j] = res;
+ i++;
+ }
+ version[3] = 0x00;
+}
+#endif
+
+
+
+/* aos will implement this function */
+#if defined(BUILD_AOS)
+extern void aos_get_mac_hex(unsigned char mac[MAC_ADDRESS_SIZE]);
+#else
+void aos_get_mac_hex(unsigned char mac[MAC_ADDRESS_SIZE])
+{
+ memcpy(mac, "\x01\x02\x03\x04\x05\x06\x07\x08", MAC_ADDRESS_SIZE);
+}
+#endif
+
+/* aos will implement this function */
+#if defined(BUILD_AOS)
+extern void aos_get_chip_code(unsigned char chip_code[CHIP_CODE_SIZE]);
+#else
+void aos_get_chip_code(unsigned char chip_code[CHIP_CODE_SIZE])
+{
+ memcpy(chip_code, "\x01\x02\x03\x04", CHIP_CODE_SIZE);
+}
+#endif
+
+const char *DEVICE_INFO_UPDATE_FMT = "{\"id\":\"%d\",\"version\":\"1.0\",\"params\":["
+ "{\"attrKey\":\"SYS_LP_SDK_VERSION\",\"attrValue\":\"%s\",\"domain\":\"SYSTEM\"},"
+ "{\"attrKey\":\"SYS_SDK_LANGUAGE\",\"attrValue\":\"C\",\"domain\":\"SYSTEM\"}"
+ "],\"method\":\"thing.deviceinfo.update\"}";
+
+int iotx_report_devinfo(void *pclient)
+{
+ int ret = 0;
+ char topic_name[IOTX_URI_MAX_LEN + 1] = {0};
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char *msg = NULL;
+ int msg_len = 0;
+
+
+ if (info_report_func == NULL) {
+ VERSION_ERR("report func not register!");
+ return -1;
+ }
+
+ HAL_GetProductKey(product_key);
+ HAL_GetDeviceName(device_name);
+ VERSION_DEBUG("devinfo report");
+
+ /* devinfo update topic name */
+ ret = HAL_Snprintf(topic_name,
+ IOTX_URI_MAX_LEN,
+ "/sys/%s/%s/thing/deviceinfo/update",
+ product_key,
+ device_name);
+ if (ret <= 0) {
+ VERSION_ERR("topic generate err");
+ return FAIL_RETURN;
+ }
+ VERSION_DEBUG("devinfo report topic: %s", topic_name);
+
+ msg_len = strlen(DEVICE_INFO_UPDATE_FMT) + 10 + strlen(IOTX_SDK_VERSION) + 1;
+ msg = (char *)SYS_REPORT_MALLOC(msg_len);
+ if (msg == NULL) {
+ VERSION_ERR("malloc err");
+ return FAIL_RETURN;
+ }
+ memset(msg, 0, msg_len);
+
+ /* devinfo update message */
+ ret = HAL_Snprintf(msg,
+ msg_len,
+ DEVICE_INFO_UPDATE_FMT,
+ iotx_report_id(),
+ IOTX_SDK_VERSION
+ );
+ if (ret <= 0) {
+ VERSION_ERR("topic msg generate err");
+ SYS_REPORT_FREE(msg);
+ return FAIL_RETURN;
+ }
+ VERSION_DEBUG("devinfo report data: %s", msg);
+
+ if (info_report_func != NULL) {
+ info_report_func(pclient, topic_name, 1, msg, strlen(msg));
+ }
+
+ SYS_REPORT_FREE(msg);
+ if (ret < 0) {
+ VERSION_ERR("publish failed, ret = %d", ret);
+ return FAIL_RETURN;
+ }
+ VERSION_DEBUG("devinfo report succeed");
+
+ return SUCCESS_RETURN;
+}
+
+/* report Firmware version */
+int iotx_report_firmware_version(void *pclient)
+{
+ int ret;
+ char topic_name[IOTX_URI_MAX_LEN + 1] = {0};
+ char msg[FIRMWARE_VERSION_MSG_LEN] = {0};
+ char version[IOTX_FIRMWARE_VERSION_LEN + 1] = {0};
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+
+ if (info_report_func == NULL) {
+ VERSION_ERR("report func not register!");
+ return -1;
+ }
+
+ HAL_GetProductKey(product_key);
+ HAL_GetDeviceName(device_name);
+
+ ret = HAL_GetFirmwareVersion(version);
+ if (ret <= 0) {
+ VERSION_ERR("firmware version does not implement");
+ return FAIL_RETURN;
+ }
+
+ VERSION_DEBUG("firmware version report start in MQTT");
+
+ /* firmware report topic name generate */
+ ret = HAL_Snprintf(topic_name,
+ IOTX_URI_MAX_LEN,
+ "/ota/device/inform/%s/%s",
+ product_key,
+ device_name
+ );
+ if (ret <= 0) {
+ VERSION_ERR("firmware report topic generate err");
+ return FAIL_RETURN;
+ }
+ VERSION_DEBUG("firmware report topic: %s", topic_name);
+
+ /* firmware report message json data generate */
+ ret = HAL_Snprintf(msg,
+ FIRMWARE_VERSION_MSG_LEN,
+ "{\"id\":\"%d\",\"params\":{\"version\":\"%s\"}}",
+ iotx_report_id(),
+ version
+ );
+ if (ret <= 0) {
+ VERSION_ERR("firmware report message json data generate err");
+ return FAIL_RETURN;
+ }
+ VERSION_DEBUG("firmware report data: %s", msg);
+
+ ret = info_report_func(pclient, topic_name, 1, msg, strlen(msg));
+
+ if (ret < 0) {
+ VERSION_ERR("publish failed, ret = %d", ret);
+ return ret;
+ }
+
+ VERSION_DEBUG("firmware version report finished, iotx_publish() = %d", ret);
+ return SUCCESS_RETURN;
+}
+
+/* report ModuleID */
+int iotx_report_mid(void *pclient)
+{
+ return SUCCESS_RETURN;
+}
+
+#ifndef BUILD_AOS
+unsigned int aos_get_version_info(unsigned char version_num[VERSION_NUM_SIZE],
+ unsigned char random_num[RANDOM_NUM_SIZE], unsigned char mac_address[MAC_ADDRESS_SIZE],
+ unsigned char chip_code[CHIP_CODE_SIZE], unsigned char *output_buffer, unsigned int output_buffer_size)
+{
+ char *p = (char *)output_buffer;
+
+ if (output_buffer_size < AOS_ACTIVE_INFO_LEN) {
+ return 1;
+ }
+
+ memset(p, 0, output_buffer_size);
+
+ infra_hex2str(version_num, VERSION_NUM_SIZE, p);
+ p += VERSION_NUM_SIZE * 2;
+ infra_hex2str(random_num, RANDOM_NUM_SIZE, p);
+ p += RANDOM_NUM_SIZE * 2;
+ infra_hex2str(mac_address, MAC_ADDRESS_SIZE, p);
+ p += MAC_ADDRESS_SIZE * 2;
+ infra_hex2str(chip_code, CHIP_CODE_SIZE, p);
+ p += CHIP_CODE_SIZE * 2;
+ strcat(p, "1111111111222222222233333333334444444444");
+
+ return 0;
+}
+#endif
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_report.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_report.h
new file mode 100644
index 00000000..8947fea5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_report.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "infra_defs.h"
+
+#ifndef _INFRA_REPORT_H_
+#define _INFRA_REPORT_H_
+
+#ifndef VERSION_NUM_SIZE
+ #define VERSION_NUM_SIZE 4
+#endif
+
+#ifndef RANDOM_NUM_SIZE
+ #define RANDOM_NUM_SIZE 4
+#endif
+
+#ifndef MAC_ADDRESS_SIZE
+ #define MAC_ADDRESS_SIZE 8
+#endif
+
+#ifndef CHIP_CODE_SIZE
+ #define CHIP_CODE_SIZE 4
+#endif
+
+#define AOS_ACTIVE_INFO_LEN (81)
+
+/* activation device type */
+typedef enum {
+ ACTIVE_SUBDEV, /* it's a subDevice */
+ ACTIVE_SINGLE_GW /* it s a single or gateway device */
+} active_device_type_t;
+
+/* activation system type */
+typedef enum {
+ ACTIVE_LINKKIT_ONLY, /* only linkkit implement */
+ ACTIVE_LINKKIT_AOS, /* both linkkit and AOS implement */
+ ACTIVE_LINKKIT_OTHERS /* linkkit and 3-party OS implement */
+} active_system_type_t;
+
+typedef int (*info_report_func_pt)(void *handle, const char *topic_name,int req_ack,void *data, int len);
+
+#define MIDREPORT_PAYLOAD_LEN (62 + IOTX_PARTNER_ID_LEN + IOTX_MODULE_ID_LEN + 32 +1)
+#define MIDREPORT_REQID_LEN (IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 6)
+#define AOS_VERSON_MSG_LEN (256)
+#define LINKKIT_VERSION_MSG_LEN (192)
+#define FIRMWARE_VERSION_MSG_LEN (64)
+#define DEBUG_REPORT_MID_DEVINFO_FIRMWARE (1)
+
+int iotx_report_id(void);
+int iotx_midreport_reqid(char *requestId, char *product_key, char *device_name);
+int iotx_midreport_payload(char *msg, char *requestId, char *mid, char *pid);
+int iotx_midreport_topic(char *topic_name, char *topic_head, char *product_key, char *device_name);
+
+/* AOS version report API */
+int iotx_gen_aos_report_topic(char *topic_name, char *product_key, char *device_name);
+int iotx_gen_aos_report_payload(char *msg, int requestId, char *versionData);
+
+void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE]);
+
+#ifndef BUILD_AOS
+unsigned int aos_get_version_info(unsigned char version_num[VERSION_NUM_SIZE],
+ unsigned char random_num[RANDOM_NUM_SIZE], unsigned char mac_address[MAC_ADDRESS_SIZE],
+ unsigned char chip_code[CHIP_CODE_SIZE], unsigned char *output_buffer, unsigned int output_buffer_size);
+#endif
+
+void iotx_set_report_func(info_report_func_pt func);
+int iotx_report_devinfo(void *pclient);
+int iotx_report_mid(void *pclient);
+int iotx_report_firmware_version(void *pclient);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha1.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha1.c
new file mode 100644
index 00000000..eecb1a8b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha1.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_SHA1
+
+#include
+#include
+#include "infra_sha1.h"
+
+#define SHA1_KEY_IOPAD_SIZE (64)
+#define SHA1_DIGEST_SIZE (20)
+
+/* Implementation that should never be optimized out by the compiler */
+static void utils_sha1_zeroize( void *v, uint32_t n ) {
+ volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+void utils_sha1_init(iot_sha1_context *ctx)
+{
+ memset(ctx, 0, sizeof(iot_sha1_context));
+}
+
+void utils_sha1_free(iot_sha1_context *ctx)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ utils_sha1_zeroize(ctx, sizeof(iot_sha1_context));
+}
+
+void utils_sha1_clone(iot_sha1_context *dst,
+ const iot_sha1_context *src)
+{
+ *dst = *src;
+}
+
+/*
+ * SHA-1 context setup
+ */
+void utils_sha1_starts(iot_sha1_context *ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+}
+
+void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64])
+{
+ uint32_t temp, W[16], A, B, C, D, E;
+
+ GET_UINT32_BE( W[ 0], data, 0 );
+ GET_UINT32_BE( W[ 1], data, 4 );
+ GET_UINT32_BE( W[ 2], data, 8 );
+ GET_UINT32_BE( W[ 3], data, 12 );
+ GET_UINT32_BE( W[ 4], data, 16 );
+ GET_UINT32_BE( W[ 5], data, 20 );
+ GET_UINT32_BE( W[ 6], data, 24 );
+ GET_UINT32_BE( W[ 7], data, 28 );
+ GET_UINT32_BE( W[ 8], data, 32 );
+ GET_UINT32_BE( W[ 9], data, 36 );
+ GET_UINT32_BE( W[10], data, 40 );
+ GET_UINT32_BE( W[11], data, 44 );
+ GET_UINT32_BE( W[12], data, 48 );
+ GET_UINT32_BE( W[13], data, 52 );
+ GET_UINT32_BE( W[14], data, 56 );
+ GET_UINT32_BE( W[15], data, 60 );
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
+ W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P( A, B, C, D, E, W[0] );
+ P( E, A, B, C, D, W[1] );
+ P( D, E, A, B, C, W[2] );
+ P( C, D, E, A, B, W[3] );
+ P( B, C, D, E, A, W[4] );
+ P( A, B, C, D, E, W[5] );
+ P( E, A, B, C, D, W[6] );
+ P( D, E, A, B, C, W[7] );
+ P( C, D, E, A, B, W[8] );
+ P( B, C, D, E, A, W[9] );
+ P( A, B, C, D, E, W[10] );
+ P( E, A, B, C, D, W[11] );
+ P( D, E, A, B, C, W[12] );
+ P( C, D, E, A, B, W[13] );
+ P( B, C, D, E, A, W[14] );
+ P( A, B, C, D, E, W[15] );
+ P( E, A, B, C, D, R(16) );
+ P( D, E, A, B, C, R(17) );
+ P( C, D, E, A, B, R(18) );
+ P( B, C, D, E, A, R(19) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P( A, B, C, D, E, R(20) );
+ P( E, A, B, C, D, R(21) );
+ P( D, E, A, B, C, R(22) );
+ P( C, D, E, A, B, R(23) );
+ P( B, C, D, E, A, R(24) );
+ P( A, B, C, D, E, R(25) );
+ P( E, A, B, C, D, R(26) );
+ P( D, E, A, B, C, R(27) );
+ P( C, D, E, A, B, R(28) );
+ P( B, C, D, E, A, R(29) );
+ P( A, B, C, D, E, R(30) );
+ P( E, A, B, C, D, R(31) );
+ P( D, E, A, B, C, R(32) );
+ P( C, D, E, A, B, R(33) );
+ P( B, C, D, E, A, R(34) );
+ P( A, B, C, D, E, R(35) );
+ P( E, A, B, C, D, R(36) );
+ P( D, E, A, B, C, R(37) );
+ P( C, D, E, A, B, R(38) );
+ P( B, C, D, E, A, R(39) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P( A, B, C, D, E, R(40) );
+ P( E, A, B, C, D, R(41) );
+ P( D, E, A, B, C, R(42) );
+ P( C, D, E, A, B, R(43) );
+ P( B, C, D, E, A, R(44) );
+ P( A, B, C, D, E, R(45) );
+ P( E, A, B, C, D, R(46) );
+ P( D, E, A, B, C, R(47) );
+ P( C, D, E, A, B, R(48) );
+ P( B, C, D, E, A, R(49) );
+ P( A, B, C, D, E, R(50) );
+ P( E, A, B, C, D, R(51) );
+ P( D, E, A, B, C, R(52) );
+ P( C, D, E, A, B, R(53) );
+ P( B, C, D, E, A, R(54) );
+ P( A, B, C, D, E, R(55) );
+ P( E, A, B, C, D, R(56) );
+ P( D, E, A, B, C, R(57) );
+ P( C, D, E, A, B, R(58) );
+ P( B, C, D, E, A, R(59) );
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P( A, B, C, D, E, R(60) );
+ P( E, A, B, C, D, R(61) );
+ P( D, E, A, B, C, R(62) );
+ P( C, D, E, A, B, R(63) );
+ P( B, C, D, E, A, R(64) );
+ P( A, B, C, D, E, R(65) );
+ P( E, A, B, C, D, R(66) );
+ P( D, E, A, B, C, R(67) );
+ P( C, D, E, A, B, R(68) );
+ P( B, C, D, E, A, R(69) );
+ P( A, B, C, D, E, R(70) );
+ P( E, A, B, C, D, R(71) );
+ P( D, E, A, B, C, R(72) );
+ P( C, D, E, A, B, R(73) );
+ P( B, C, D, E, A, R(74) );
+ P( A, B, C, D, E, R(75) );
+ P( E, A, B, C, D, R(76) );
+ P( D, E, A, B, C, R(77) );
+ P( C, D, E, A, B, R(78) );
+ P( B, C, D, E, A, R(79) );
+
+#undef K
+#undef F
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+/*
+ * SHA-1 process buffer
+ */
+void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen)
+{
+ uint32_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ utils_sha1_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ utils_sha1_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha1_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-1 final digest
+ */
+void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20])
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ utils_sha1_update( ctx, sha1_padding, padn );
+ utils_sha1_update( ctx, msglen, 8 );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+}
+
+
+/*
+ * output = SHA-1( input buffer )
+ */
+void utils_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20])
+{
+ iot_sha1_context ctx;
+
+ utils_sha1_init(&ctx);
+ utils_sha1_starts(&ctx);
+ utils_sha1_update(&ctx, input, ilen);
+ utils_sha1_finish(&ctx, output);
+ utils_sha1_free(&ctx);
+}
+
+static int8_t utils_hb2hex(uint8_t hb)
+{
+ hb = hb & 0xF;
+ return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a');
+}
+
+void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len)
+{
+ iot_sha1_context context;
+ unsigned char k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ unsigned char k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ unsigned char out[SHA1_DIGEST_SIZE];
+ int i;
+
+ if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
+ return;
+ }
+
+ if (key_len > SHA1_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < SHA1_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner SHA */
+ utils_sha1_init(&context); /* init context for 1st pass */
+ utils_sha1_starts(&context); /* setup context for 1st pass */
+ utils_sha1_update(&context, k_ipad, SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
+ utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
+ utils_sha1_finish(&context, out); /* finish up 1st pass */
+
+ /* perform outer SHA */
+ utils_sha1_init(&context); /* init context for 2nd pass */
+ utils_sha1_starts(&context); /* setup context for 2nd pass */
+ utils_sha1_update(&context, k_opad, SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
+ utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
+ utils_sha1_finish(&context, out); /* finish up 2nd pass */
+
+ for (i = 0; i < SHA1_DIGEST_SIZE; ++i) {
+ digest[i * 2] = utils_hb2hex(out[i] >> 4);
+ digest[i * 2 + 1] = utils_hb2hex(out[i]);
+ }
+}
+
+void utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len)
+{
+ iot_sha1_context context;
+ unsigned char k_ipad[SHA1_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ unsigned char k_opad[SHA1_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ unsigned char out[SHA1_DIGEST_SIZE];
+ int i;
+
+ if ((NULL == msg) || (NULL == digest) || (NULL == key)) {
+ return;
+ }
+
+ if (key_len > SHA1_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < SHA1_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner SHA */
+ utils_sha1_init(&context); /* init context for 1st pass */
+ utils_sha1_starts(&context); /* setup context for 1st pass */
+ utils_sha1_update(&context, k_ipad, SHA1_KEY_IOPAD_SIZE); /* start with inner pad */
+ utils_sha1_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */
+ utils_sha1_finish(&context, out); /* finish up 1st pass */
+
+ /* perform outer SHA */
+ utils_sha1_init(&context); /* init context for 2nd pass */
+ utils_sha1_starts(&context); /* setup context for 2nd pass */
+ utils_sha1_update(&context, k_opad, SHA1_KEY_IOPAD_SIZE); /* start with outer pad */
+ utils_sha1_update(&context, out, SHA1_DIGEST_SIZE); /* then results of 1st hash */
+ utils_sha1_finish(&context, out); /* finish up 2nd pass */
+ memcpy(digest, out, SHA1_DIGEST_SIZE);
+}
+
+#endif
\ No newline at end of file
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha1.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha1.h
new file mode 100644
index 00000000..c3fd35d2
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha1.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef _INFRA_SHA1_H_
+#define _INFRA_SHA1_H_
+
+#include "infra_types.h"
+
+#define SHA1_DIGEST_SIZE (20)
+
+/**
+ * \brief SHA-1 context structure
+ */
+typedef struct {
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[5]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+} iot_sha1_context;
+
+/**
+ * \brief Initialize SHA-1 context
+ *
+ * \param ctx SHA-1 context to be initialized
+ */
+void utils_sha1_init(iot_sha1_context *ctx);
+
+/**
+ * \brief Clear SHA-1 context
+ *
+ * \param ctx SHA-1 context to be cleared
+ */
+void utils_sha1_free(iot_sha1_context *ctx);
+
+/**
+ * \brief Clone (the state of) a SHA-1 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ */
+void utils_sha1_clone(iot_sha1_context *dst,
+ const iot_sha1_context *src);
+
+/**
+ * \brief SHA-1 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void utils_sha1_starts(iot_sha1_context *ctx);
+
+/**
+ * \brief SHA-1 process buffer
+ *
+ * \param ctx SHA-1 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen);
+
+/**
+ * \brief SHA-1 final digest
+ *
+ * \param ctx SHA-1 context
+ * \param output SHA-1 checksum result
+ */
+void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]);
+
+/* Internal use */
+void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]);
+
+/**
+ * \brief Output = SHA-1( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-1 checksum result
+ */
+void utils_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20]);
+
+void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
+void utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len);
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha256.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha256.c
new file mode 100644
index 00000000..f8cd83a5
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha256.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_config.h"
+
+#ifdef INFRA_SHA256
+
+#define INFRA_SHA256_SMALLER
+
+#include
+#include
+#include "infra_sha256.h"
+
+#define SHA256_KEY_IOPAD_SIZE (64)
+#define SHA256_DIGEST_SIZE (32)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+ do { \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+ } while( 0 )
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+ do { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+ } while( 0 )
+#endif
+
+
+static void utils_sha256_zeroize(void *v, uint32_t n)
+{
+ volatile unsigned char *p = v;
+ while (n--) {
+ *p++ = 0;
+ }
+}
+
+void utils_sha256_init(iot_sha256_context *ctx)
+{
+ memset(ctx, 0, sizeof(iot_sha256_context));
+}
+
+void utils_sha256_free(iot_sha256_context *ctx)
+{
+ if (NULL == ctx) {
+ return;
+ }
+
+ utils_sha256_zeroize(ctx, sizeof(iot_sha256_context));
+}
+
+void utils_sha256_starts(iot_sha256_context *ctx)
+{
+ int is224 = 0;
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if (is224 == 0) {
+ /* SHA-256 */
+ 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->is224 = is224;
+}
+
+static const uint32_t K[] = {
+ 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,
+};
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+ ( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+ )
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+ { \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+ }
+
+void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64])
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A[8];
+ unsigned int i;
+
+ for (i = 0; i < 8; i++) {
+ A[i] = ctx->state[i];
+ }
+
+#if defined(INFRA_SHA256_SMALLER)
+ for (i = 0; i < 64; i++) {
+ if (i < 16) {
+ GET_UINT32_BE(W[i], data, 4 * i);
+ } else {
+ R(i);
+ }
+
+ P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]);
+
+ temp1 = A[7];
+ A[7] = A[6];
+ A[6] = A[5];
+ A[5] = A[4];
+ A[4] = A[3];
+ A[3] = A[2];
+ A[2] = A[1];
+ A[1] = A[0];
+ A[0] = temp1;
+ }
+#else /* INFRA_SHA256_SMALLER */
+ for (i = 0; i < 16; i++) {
+ GET_UINT32_BE(W[i], data, 4 * i);
+ }
+
+ for (i = 0; i < 16; i += 8) {
+ P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0]);
+ P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1]);
+ P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2]);
+ P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3]);
+ P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4]);
+ P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5]);
+ P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6]);
+ P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7]);
+ }
+
+ for (i = 16; i < 64; i += 8) {
+ P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0]);
+ P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1]);
+ P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2]);
+ P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3]);
+ P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4]);
+ P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5]);
+ P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6]);
+ P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7]);
+ }
+#endif /* INFRA_SHA256_SMALLER */
+
+ for (i = 0; i < 8; i++) {
+ ctx->state[i] += A[i];
+ }
+}
+void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen)
+{
+ size_t fill;
+ uint32_t left;
+
+ if (ilen == 0) {
+ return;
+ }
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if (ctx->total[0] < (uint32_t) ilen) {
+ ctx->total[1]++;
+ }
+
+ if (left && ilen >= fill) {
+ memcpy((void *)(ctx->buffer + left), input, fill);
+ utils_sha256_process(ctx, ctx->buffer);
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while (ilen >= 64) {
+ utils_sha256_process(ctx, input);
+ input += 64;
+ ilen -= 64;
+ }
+
+ if (ilen > 0) {
+ memcpy((void *)(ctx->buffer + left), input, ilen);
+ }
+}
+
+static const unsigned char sha256_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32])
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = (ctx->total[0] >> 29)
+ | (ctx->total[1] << 3);
+ low = (ctx->total[0] << 3);
+
+ PUT_UINT32_BE(high, msglen, 0);
+ PUT_UINT32_BE(low, msglen, 4);
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < 56) ? (56 - last) : (120 - last);
+
+ utils_sha256_update(ctx, sha256_padding, padn);
+ utils_sha256_update(ctx, msglen, 8);
+
+ PUT_UINT32_BE(ctx->state[0], output, 0);
+ PUT_UINT32_BE(ctx->state[1], output, 4);
+ PUT_UINT32_BE(ctx->state[2], output, 8);
+ PUT_UINT32_BE(ctx->state[3], output, 12);
+ PUT_UINT32_BE(ctx->state[4], output, 16);
+ PUT_UINT32_BE(ctx->state[5], output, 20);
+ PUT_UINT32_BE(ctx->state[6], output, 24);
+
+ if (ctx->is224 == 0) {
+ PUT_UINT32_BE(ctx->state[7], output, 28);
+ }
+}
+
+void utils_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32])
+{
+ iot_sha256_context ctx;
+
+ utils_sha256_init(&ctx);
+ utils_sha256_starts(&ctx);
+ utils_sha256_update(&ctx, input, ilen);
+ utils_sha256_finish(&ctx, output);
+ utils_sha256_free(&ctx);
+}
+
+void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32])
+{
+ iot_sha256_context context;
+ uint8_t k_ipad[SHA256_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */
+ uint8_t k_opad[SHA256_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */
+ int32_t i;
+
+ if ((NULL == msg) || (NULL == key) || (NULL == output)) {
+ return;
+ }
+
+ if (key_len > SHA256_KEY_IOPAD_SIZE) {
+ return;
+ }
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < SHA256_KEY_IOPAD_SIZE; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner SHA */
+ utils_sha256_init(&context); /* init context for 1st pass */
+ utils_sha256_starts(&context); /* setup context for 1st pass */
+ utils_sha256_update(&context, k_ipad, SHA256_KEY_IOPAD_SIZE); /* start with inner pad */
+ utils_sha256_update(&context, msg, msg_len); /* then text of datagram */
+ utils_sha256_finish(&context, output); /* finish up 1st pass */
+
+ /* perform outer SHA */
+ utils_sha256_init(&context); /* init context for 2nd pass */
+ utils_sha256_starts(&context); /* setup context for 2nd pass */
+ utils_sha256_update(&context, k_opad, SHA256_KEY_IOPAD_SIZE); /* start with outer pad */
+ utils_sha256_update(&context, output, SHA256_DIGEST_SIZE); /* then results of 1st hash */
+ utils_sha256_finish(&context, output); /* finish up 2nd pass */
+}
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha256.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha256.h
new file mode 100644
index 00000000..7fc337d1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_sha256.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOTX_COMMON_SHA256_H_
+#define _IOTX_COMMON_SHA256_H_
+
+#include
+
+#define SHA256_DIGEST_LENGTH (32)
+#define SHA256_BLOCK_LENGTH (64)
+#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
+#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
+
+/**
+ * \brief SHA-256 context structure
+ */
+typedef struct {
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[8]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+ int is224; /*!< 0 => SHA-256, else SHA-224 */
+} iot_sha256_context;
+
+typedef union {
+ char sptr[8];
+ uint64_t lint;
+} u_retLen;
+
+/**
+ * \brief Initialize SHA-256 context
+ *
+ * \param ctx SHA-256 context to be initialized
+ */
+void utils_sha256_init(iot_sha256_context *ctx);
+
+/**
+ * \brief Clear SHA-256 context
+ *
+ * \param ctx SHA-256 context to be cleared
+ */
+void utils_sha256_free(iot_sha256_context *ctx);
+
+
+/**
+ * \brief SHA-256 context setup
+ *
+ * \param ctx context to be initialized
+ */
+void utils_sha256_starts(iot_sha256_context *ctx);
+
+/**
+ * \brief SHA-256 process buffer
+ *
+ * \param ctx SHA-256 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen);
+
+/**
+ * \brief SHA-256 final digest
+ *
+ * \param ctx SHA-256 context
+ * \param output SHA-256 checksum result
+ */
+void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32]);
+
+/* Internal use */
+void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64]);
+
+/**
+ * \brief Output = SHA-256( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-256 checksum result
+ */
+void utils_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32]);
+
+void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32]);
+
+#endif
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_string.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_string.c
new file mode 100644
index 00000000..2b65d561
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_string.c
@@ -0,0 +1,207 @@
+#include "infra_config.h"
+
+#ifdef INFRA_STRING
+
+#include
+#include
+#include "infra_types.h"
+#include "infra_string.h"
+
+int8_t infra_hex2char(uint8_t hex)
+{
+ hex = hex & 0xF;
+ return (int8_t)(hex < 10 ? '0' + hex : hex - 10 + 'a');
+}
+
+void infra_hex2str(uint8_t *input, uint16_t input_len, char *output)
+{
+ char *zEncode = "0123456789ABCDEF";
+ int i = 0, j = 0;
+
+ for (i = 0; i < input_len; i++) {
+ output[j++] = zEncode[(input[i] >> 4) & 0xf];
+ output[j++] = zEncode[(input[i]) & 0xf];
+ }
+}
+
+void infra_int2str(uint32_t input, char output[10])
+{
+ uint8_t i = 0, j = 0;
+ char tmp[10] = {0};
+
+ do {
+ tmp[i++] = input%10 + '0';
+ }while((input/=10)>0);
+
+ do {
+ output[--i] = tmp[j++];
+ }while(i > 0);
+}
+
+char *infra_strtok(char *str, const char *delim)
+{
+ int only_delim = 1;
+ static char *pos = NULL;
+ static char *target = NULL;
+
+ pos = (str == NULL)?(pos):(str);
+
+ if (pos == NULL || delim == NULL ||
+ strlen(pos) <= strlen(delim)) {
+ return NULL;
+ }
+
+ target = pos;
+ while (strlen(pos) >= strlen(delim)) {
+ if (memcmp(pos,delim,strlen(delim)) != 0) {
+ only_delim = 0;
+ pos++;
+ continue;
+ }
+
+ if (strlen(pos) == strlen(delim)) {
+ memset(pos,0,strlen(delim));
+ if (only_delim) {
+ return NULL;
+ }
+ return target;
+ }
+
+ if (target == pos) {
+ pos += strlen(delim);
+ target = pos;
+ }else{
+ memset(pos,0,strlen(delim));
+ pos += strlen(delim);
+ break;
+ }
+ }
+
+ return target;
+}
+
+#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (1) : (0))
+
+static uint8_t _hexval_of_char(char hex)
+{
+ if (LITE_isdigit(hex)) {
+ return (hex - '0');
+ }
+ if (hex >= 'a' && hex <= 'f') {
+ return (hex - 'a' + 10);
+ }
+ if (hex >= 'A' && hex <= 'F') {
+ return (hex - 'A' + 10);
+ }
+
+ return 0;
+}
+
+void LITE_hexstr_convert(char *input, int input_len, unsigned char *output, int output_len)
+{
+ int i = 0;
+ uint8_t ch0, ch1;
+
+ if (input_len % 2 != 0) {
+ return;
+ }
+
+ while (i < input_len / 2 && i < output_len) {
+ ch0 = _hexval_of_char((char)input[2 * i]);
+ ch1 = _hexval_of_char((char)input[2 * i + 1]);
+ output[i] = (ch0 << 4 | ch1);
+ i++;
+ }
+}
+
+void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase)
+{
+ static char *zEncode[] = {"0123456789abcdef", "0123456789ABCDEF"};
+ int j = 0;
+ int i = 0;
+ int idx = uppercase ? 1 : 0;
+
+ for (i = 0; i < in_len; i ++) {
+ int a = digest[i];
+
+ out[j++] = zEncode[idx][(a >> 4) & 0xf];
+ out[j++] = zEncode[idx][a & 0xf];
+ }
+}
+
+int infra_str2int(const char *input, int *val)
+{
+ int sign = 0;
+ int temp = 0;
+
+ if (input == NULL || val == NULL) {
+ return -1;
+ }
+
+ while(*input == ' ') { /* only support skipping space */
+ input++;
+ }
+
+ if (*input == '+') {
+ input++;
+ }
+ else if (*input == '-') {
+ input++;
+ sign = -1;
+ }
+
+ while (*input != 0) {
+ if (*input < '0' || *input > '9') {
+ break;
+ }
+
+ temp = temp * 10 + (*input - '0');
+ input++;
+ }
+
+ if (sign == -1) {
+ temp = -temp;
+ }
+
+ *val = temp;
+ return 0;
+}
+
+#endif
+
+#ifdef INFRA_RANDOM
+
+uint64_t HAL_UptimeMs(void);
+void HAL_Srandom(uint32_t seed);
+uint32_t HAL_Random(uint32_t region);
+
+int infra_randstr(char *random, int length)
+{
+ int index = 0;
+
+ HAL_Srandom(HAL_UptimeMs());
+
+ for (index = 0; index < length; index++) {
+ switch (HAL_Random(3)) {
+ case 0: {
+ random[index] = 'A' + HAL_Random(26);
+ }
+ break;
+ case 1: {
+ random[index] = 'a' + HAL_Random(26);
+ }
+ break;
+ case 2: {
+ random[index] = '0' + HAL_Random(10);
+ }
+ break;
+ default: {
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_string.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_string.h
new file mode 100644
index 00000000..5026b2de
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_string.h
@@ -0,0 +1,16 @@
+#ifndef _INFRA_STRING_H_
+#define _INFRA_STRING_H_
+
+#include "infra_types.h"
+
+int8_t infra_hex2char(uint8_t hex);
+void infra_hex2str(uint8_t *input, uint16_t input_len, char *output);
+void infra_int2str(uint32_t input, char output[10]);
+char *infra_strtok(char *str, const char *delim);
+int infra_randstr(char *random, int length);
+void LITE_hexstr_convert(char *input, int input_len, unsigned char *output, int output_len);
+int infra_str2int(const char *input, int *val);
+void LITE_hexbuf_convert(unsigned char *digest, char *out, int in_len, int uppercase);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_timer.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_timer.c
new file mode 100644
index 00000000..f1996cf6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_timer.c
@@ -0,0 +1,95 @@
+#include "infra_config.h"
+
+#ifdef INFRA_TIMER
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "infra_types.h"
+#include "infra_timer.h"
+
+uint64_t HAL_UptimeMs(void);
+
+void iotx_time_start(iotx_time_t *timer)
+{
+ if (!timer) {
+ return;
+ }
+
+ timer->time = HAL_UptimeMs();
+}
+
+uint32_t utils_time_spend(iotx_time_t *start)
+{
+ uint32_t now, res;
+
+ if (!start) {
+ return 0;
+ }
+
+ now = HAL_UptimeMs();
+ res = now - start->time;
+ return res;
+}
+
+uint32_t iotx_time_left(iotx_time_t *end)
+{
+ uint32_t now, res;
+
+ if (!end) {
+ return 0;
+ }
+
+ if (utils_time_is_expired(end)) {
+ return 0;
+ }
+
+ now = HAL_UptimeMs();
+ res = end->time - now;
+ return res;
+}
+
+uint32_t utils_time_is_expired(iotx_time_t *timer)
+{
+ uint32_t cur_time;
+
+ if (!timer) {
+ return 1;
+ }
+
+ cur_time = HAL_UptimeMs();
+ /*
+ * WARNING: Do NOT change the following code until you know exactly what it do!
+ *
+ * check whether it reach destination time or not.
+ */
+ if ((cur_time - timer->time) < (UINT32_MAX / 2)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void iotx_time_init(iotx_time_t *timer)
+{
+ if (!timer) {
+ return;
+ }
+
+ timer->time = 0;
+}
+
+void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond)
+{
+ if (!timer) {
+ return;
+ }
+
+ timer->time = HAL_UptimeMs() + millisecond;
+}
+
+uint32_t utils_time_get_ms(void)
+{
+ return HAL_UptimeMs();
+}
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_timer.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_timer.h
new file mode 100644
index 00000000..e018aab2
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_timer.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#ifndef _INFRA_TIMER_H_
+#define _INFRA_TIMER_H_
+
+#include "infra_types.h"
+
+typedef struct {
+ uint32_t time;
+} iotx_time_t;
+
+
+void iotx_time_start(iotx_time_t *timer);
+
+uint32_t utils_time_spend(iotx_time_t *start);
+
+uint32_t iotx_time_left(iotx_time_t *end);
+
+uint32_t utils_time_is_expired(iotx_time_t *timer);
+
+void iotx_time_init(iotx_time_t *timer);
+
+void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond);
+
+uint32_t utils_time_get_ms(void);
+
+#endif /* _IOTX_COMMON_TIMER_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_types.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_types.h
new file mode 100644
index 00000000..7037296e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/infra/infra_types.h
@@ -0,0 +1,29 @@
+#ifndef _INFRA_TYPES_H_
+#define _INFRA_TYPES_H_
+
+#include
+#include "infra_config.h"
+
+#define IOT_TRUE (1) /* indicate boolean value true */
+#define IOT_FALSE (0) /* indicate boolean value false */
+
+#if !defined(PLATFORM_HAS_STDINT)
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+typedef unsigned long int uint64_t;
+typedef signed long int int64_t;
+typedef unsigned int uintptr_t;
+
+#else
+
+#include
+
+#endif /* #if !defined(PLATFORM_HAS_STDINT) */
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTConnect.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTConnect.h
new file mode 100644
index 00000000..20ec833d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTConnect.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef MQTTCONNECT_H_
+#define MQTTCONNECT_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+
+#define MQTT_CONN_FLAG_USER_NAME (0x80)
+#define MQTT_CONN_FLAG_PASSWORD (0x40)
+#define MQTT_CONN_FLAG_WILL_RETAIN (0x20)
+#define MQTT_CONN_FLAG_WILL_QOS (0x18)
+#define MQTT_CONN_FLAG_WILL_FLAG (0x04)
+#define MQTT_CONN_FLAG_CLEAN_SESSION (0x02)
+
+typedef union {
+ unsigned char all; /**< all connect flags */
+} MQTTConnectFlags; /**< connect flags byte */
+
+/**
+ * Defines the MQTT "Last Will and Testament" (LWT) settings for
+ * the connect packet.
+ */
+typedef struct {
+ /** The eyecatcher for this structure. must be MQTW. */
+ char struct_id[4];
+ /** The version number of this structure. Must be 0 */
+ int struct_version;
+ /** The LWT topic to which the LWT message will be published. */
+ MQTTString topicName;
+ /** The LWT payload. */
+ MQTTString message;
+ /**
+ * The retained flag for the LWT message (see MQTTAsync_message.retained).
+ */
+ unsigned char retained;
+ /**
+ * The quality of service setting for the LWT message (see
+ * MQTTAsync_message.qos and @ref qos).
+ */
+ char qos;
+} MQTTPacket_willOptions;
+
+
+#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
+
+
+typedef struct {
+ /** The eyecatcher for this structure. must be MQTC. */
+ char struct_id[4];
+ /** The version number of this structure. Must be 0 */
+ int struct_version;
+ /** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1
+ */
+ unsigned char MQTTVersion;
+ MQTTString clientID;
+ unsigned short keepAliveInterval; /* 单位s */
+ unsigned char cleansession;
+ unsigned char willFlag;
+ MQTTPacket_willOptions will;
+ MQTTString username;
+ MQTTString password;
+} MQTTPacket_connectData;
+
+typedef union {
+ unsigned char all; /**< all connack flags */
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ struct {
+ unsigned int sessionpresent : 1; /**< session present flag */
+ unsigned int : 7; /**< unused */
+ } bits;
+#else
+ struct {
+ unsigned int : 7; /**< unused */
+ unsigned int sessionpresent : 1; /**< session present flag */
+ } bits;
+#endif
+} MQTTConnackFlags; /**< connack flags byte */
+
+#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN, 1, 0, \
+ MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
+
+DLLExport int MQTTSerialize_connect(unsigned char *buf, int buflen, MQTTPacket_connectData *options);
+DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData *data, unsigned char *buf, int len);
+
+DLLExport int MQTTSerialize_connack(unsigned char *buf, int buflen, unsigned char connack_rc,
+ unsigned char sessionPresent);
+DLLExport int MQTTDeserialize_connack(unsigned char *sessionPresent, unsigned char *connack_rc, unsigned char *buf,
+ int buflen);
+
+DLLExport int MQTTSerialize_disconnect(unsigned char *buf, int buflen);
+DLLExport int MQTTSerialize_pingreq(unsigned char *buf, int buflen);
+
+#endif /* MQTTCONNECT_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTConnectClient.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTConnectClient.c
new file mode 100644
index 00000000..71cb8ac9
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTConnectClient.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "MQTTPacket.h"
+
+#include
+
+/**
+ * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
+ * @param options the options to be used to build the connect packet
+ * @return the length of buffer needed to contain the serialized version of the packet
+ */
+int MQTTSerialize_connectLength(MQTTPacket_connectData *options)
+{
+ int len = 0;
+
+
+ if (options->MQTTVersion == 3) {
+ len = 12; /* variable depending on MQTT or MQIsdp */
+ } else if (options->MQTTVersion == 4) {
+ len = 10;
+ }
+
+ len += MQTTstrlen(options->clientID) + 2;
+ if (options->willFlag) {
+ len += MQTTstrlen(options->will.topicName) + 2 + MQTTstrlen(options->will.message) + 2;
+ }
+ if (options->username.cstring || options->username.lenstring.data) {
+ len += MQTTstrlen(options->username) + 2;
+ }
+ if (options->password.cstring || options->password.lenstring.data) {
+ len += MQTTstrlen(options->password) + 2;
+ }
+
+ return len;
+}
+
+
+/**
+ * Serializes the connect options into the buffer.
+ * @param buf the buffer into which the packet will be serialized
+ * @param len the length in bytes of the supplied buffer
+ * @param options the options to be used to build the connect packet
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_connect(unsigned char *buf, int buflen, MQTTPacket_connectData *options)
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ MQTTConnectFlags flags = {0};
+ int len = 0;
+ int rc = -1;
+
+ if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen) {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.byte = 0;
+ MQTT_HEADER_SET_TYPE(header.byte, CONNECT);
+
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
+
+ if (options->MQTTVersion == 4) {
+ writeCString(&ptr, "MQTT");
+ writeChar(&ptr, (char) 4);
+ } else {
+ writeCString(&ptr, "MQIsdp");
+ writeChar(&ptr, (char) 3);
+ }
+
+ flags.all = 0;
+ flags.all |= (options->cleansession) ? MQTT_CONN_FLAG_CLEAN_SESSION : 0;
+ flags.all |= (options->willFlag) ? MQTT_CONN_FLAG_WILL_FLAG : 0;
+ if (flags.all & MQTT_CONN_FLAG_WILL_FLAG) {
+ flags.all |= ((options->will.qos & 0x03) << 3);
+ flags.all |= (options->will.retained) ? MQTT_CONN_FLAG_WILL_RETAIN : 0;
+ }
+
+ if (options->username.cstring || options->username.lenstring.data) {
+ flags.all |= MQTT_CONN_FLAG_USER_NAME;
+ }
+ if (options->password.cstring || options->password.lenstring.data) {
+ flags.all |= MQTT_CONN_FLAG_PASSWORD;
+ }
+
+ writeChar(&ptr, flags.all);
+ writeInt(&ptr, options->keepAliveInterval);
+ writeMQTTString(&ptr, options->clientID);
+ if (options->willFlag) {
+ writeMQTTString(&ptr, options->will.topicName);
+ writeMQTTString(&ptr, options->will.message);
+ }
+ if (flags.all & MQTT_CONN_FLAG_USER_NAME) {
+ writeMQTTString(&ptr, options->username);
+ }
+ if (flags.all & MQTT_CONN_FLAG_PASSWORD) {
+ writeMQTTString(&ptr, options->password);
+ }
+
+ rc = ptr - buf;
+
+exit:
+ return rc;
+}
+
+
+/**
+ * Deserializes the supplied (wire) buffer into connack data - return code
+ * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
+ * @param connack_rc returned integer value of the connack return code
+ * @param buf the raw buffer data, of the correct length determined by the remaining length field
+ * @param len the length in bytes of the data in the supplied buffer
+ * @return error code. 1 is success, 0 is failure
+ */
+int MQTTDeserialize_connack(unsigned char *sessionPresent, unsigned char *connack_rc, unsigned char *buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char *curdata = buf;
+ unsigned char *enddata = NULL;
+ int rc = 0;
+ int mylen;
+ MQTTConnackFlags flags = {0};
+
+ header.byte = readChar(&curdata);
+ if (MQTT_HEADER_GET_TYPE(header.byte) != CONNACK) {
+ goto exit;
+ }
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+ if (enddata - curdata < 2) {
+ goto exit;
+ }
+
+ flags.all = readChar(&curdata);
+ *sessionPresent = flags.bits.sessionpresent;
+ *connack_rc = readChar(&curdata);
+
+ rc = 1;
+exit:
+ return rc;
+}
+
+
+/**
+ * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+ * @param packettype the message type
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_zero(unsigned char *buf, int buflen, unsigned char packettype)
+{
+ MQTTHeader header = {0};
+ int rc = -1;
+ unsigned char *ptr = buf;
+
+ if (buflen < 2) {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ header.byte = 0;
+ MQTT_HEADER_SET_TYPE(header.byte, packettype);
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
+ rc = ptr - buf;
+exit:
+ return rc;
+}
+
+
+/**
+ * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_disconnect(unsigned char *buf, int buflen)
+{
+ return MQTTSerialize_zero(buf, buflen, DISCONNECT);
+}
+
+
+/**
+ * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_pingreq(unsigned char *buf, int buflen)
+{
+ return MQTTSerialize_zero(buf, buflen, PINGREQ);
+}
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTDeserializePublish.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTDeserializePublish.c
new file mode 100644
index 00000000..9713db3f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTDeserializePublish.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "MQTTPacket.h"
+#include
+
+#define min(a, b) ((a < b) ? 1 : 0)
+
+/**
+ * Deserializes the supplied (wire) buffer into publish data
+ * @param dup returned integer - the MQTT dup flag
+ * @param qos returned integer - the MQTT QoS value
+ * @param retained returned integer - the MQTT retained flag
+ * @param packetid returned integer - the MQTT packet identifier
+ * @param topicName returned MQTTString - the MQTT topic in the publish
+ * @param payload returned byte buffer - the MQTT publish payload
+ * @param payloadlen returned integer - the length of the MQTT payload
+ * @param buf the raw buffer data, of the correct length determined by the remaining length field
+ * @param buflen the length in bytes of the data in the supplied buffer
+ * @return error code. 1 is success
+ */
+int MQTTDeserialize_publish(unsigned char *dup, int *qos, unsigned char *retained, unsigned short *packetid,
+ MQTTString *topicName,
+ unsigned char **payload, int *payloadlen, unsigned char *buf, int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char *curdata = buf;
+ unsigned char *enddata = NULL;
+ int rc = 0;
+ int mylen = 0;
+
+ header.byte = readChar(&curdata);
+ if (MQTT_HEADER_GET_TYPE(header.byte) != PUBLISH) {
+ goto exit;
+ }
+ *dup = MQTT_HEADER_GET_DUP(header.byte);
+ *qos = MQTT_HEADER_GET_QOS(header.byte);
+ *retained = MQTT_HEADER_GET_RETAIN(header.byte);
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+
+ if (!readMQTTLenString(topicName, &curdata, enddata) ||
+ enddata - curdata < 0) { /* do we have enough data to read the protocol version byte? */
+ goto exit;
+ }
+
+ if (*qos > 0) {
+ *packetid = readInt(&curdata);
+ }
+
+ *payloadlen = enddata - curdata;
+ *payload = curdata;
+ rc = 1;
+exit:
+ return rc;
+}
+
+
+
+/**
+ * Deserializes the supplied (wire) buffer into an ack
+ * @param packettype returned integer - the MQTT packet type
+ * @param dup returned integer - the MQTT dup flag
+ * @param packetid returned integer - the MQTT packet identifier
+ * @param buf the raw buffer data, of the correct length determined by the remaining length field
+ * @param buflen the length in bytes of the data in the supplied buffer
+ * @return error code. 1 is success, 0 is failure
+ */
+int MQTTDeserialize_ack(unsigned char *packettype, unsigned char *dup, unsigned short *packetid, unsigned char *buf,
+ int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char *curdata = buf;
+ unsigned char *enddata = NULL;
+ int rc = 0;
+ int mylen;
+
+ header.byte = readChar(&curdata);
+ *dup = MQTT_HEADER_GET_DUP(header.byte);
+ *packettype = MQTT_HEADER_GET_TYPE(header.byte);
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+
+ if (enddata - curdata < 2) {
+ goto exit;
+ }
+ *packetid = readInt(&curdata);
+
+ rc = 1;
+exit:
+ return rc;
+}
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPacket.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPacket.c
new file mode 100644
index 00000000..931a9305
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPacket.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "MQTTPacket.h"
+
+#include
+
+/**
+ * Encodes the message length according to the MQTT algorithm
+ * @param buf the buffer into which the encoded data is written
+ * @param length the length to be encoded
+ * @return the number of bytes written to buffer
+ */
+int MQTTPacket_encode(unsigned char *buf, int length)
+{
+ int rc = 0;
+
+ do {
+ char d = length % 128;
+ length /= 128;
+ /* if there are more digits to encode, set the top bit of this digit */
+ if (length > 0) {
+ d |= 0x80;
+ }
+ buf[rc++] = d;
+ } while (length > 0);
+ return rc;
+}
+
+
+/**
+ * Decodes the message length according to the MQTT algorithm
+ * @param getcharfn pointer to function to read the next character from the data source
+ * @param value the decoded length returned
+ * @return the number of bytes read from the socket
+ */
+int MQTTPacket_decode(int (*getcharfn)(unsigned char *, int), int *value)
+{
+ unsigned char c;
+ int multiplier = 1;
+ int len = 0;
+#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
+
+ *value = 0;
+ do {
+ int rc = MQTTPACKET_READ_ERROR;
+
+ if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) {
+ rc = MQTTPACKET_READ_ERROR; /* bad data */
+ goto exit;
+ }
+ rc = (*getcharfn)(&c, 1);
+ if (rc != 1) {
+ goto exit;
+ }
+ *value += (c & 127) * multiplier;
+ multiplier *= 128;
+ } while ((c & 128) != 0);
+exit:
+ return len;
+}
+
+
+int MQTTPacket_len(int rem_len)
+{
+ rem_len += 1; /* header byte */
+
+ /* now remaining_length field */
+ if (rem_len < 128) {
+ rem_len += 1;
+ } else if (rem_len < 16384) {
+ rem_len += 2;
+ } else if (rem_len < 2097151) {
+ rem_len += 3;
+ } else {
+ rem_len += 4;
+ }
+ return rem_len;
+}
+
+
+static unsigned char *bufptr;
+
+int bufchar(unsigned char *c, int count)
+{
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ *c = *bufptr++;
+ }
+ return count;
+}
+
+
+int MQTTPacket_decodeBuf(unsigned char *buf, int *value)
+{
+ bufptr = buf;
+ return MQTTPacket_decode(bufchar, value);
+}
+
+
+/**
+ * Calculates an integer from two bytes read from the input buffer
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the integer value calculated
+ */
+int readInt(unsigned char **pptr)
+{
+ unsigned char *ptr = *pptr;
+ int len = 256 * (*ptr) + (*(ptr + 1));
+ *pptr += 2;
+ return len;
+}
+
+
+/**
+ * Reads one character from the input buffer.
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the character read
+ */
+char readChar(unsigned char **pptr)
+{
+ char c = **pptr;
+ (*pptr)++;
+ return c;
+}
+
+
+/**
+ * Writes one character to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param c the character to write
+ */
+void writeChar(unsigned char **pptr, char c)
+{
+ **pptr = c;
+ (*pptr)++;
+}
+
+
+/**
+ * Writes an integer as 2 bytes to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param anInt the integer to write
+ */
+void writeInt(unsigned char **pptr, int anInt)
+{
+ **pptr = (unsigned char)(anInt / 256);
+ (*pptr)++;
+ **pptr = (unsigned char)(anInt % 256);
+ (*pptr)++;
+}
+
+
+/**
+ * Writes a "UTF" string to an output buffer. Converts C string to length-delimited.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param string the C string to write
+ */
+void writeCString(unsigned char **pptr, const char *string)
+{
+ int len = strlen(string);
+ writeInt(pptr, len);
+ memcpy(*pptr, string, len);
+ *pptr += len;
+}
+
+
+int getLenStringLen(char *ptr)
+{
+ int len = 256 * ((unsigned char)(*ptr)) + (unsigned char)(*(ptr + 1));
+ return len;
+}
+
+
+void writeMQTTString(unsigned char **pptr, MQTTString mqttstring)
+{
+ if (mqttstring.lenstring.len > 0) {
+ writeInt(pptr, mqttstring.lenstring.len);
+ memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
+ *pptr += mqttstring.lenstring.len;
+ } else if (mqttstring.cstring) {
+ writeCString(pptr, mqttstring.cstring);
+ } else {
+ writeInt(pptr, 0);
+ }
+}
+
+
+/**
+ * @param mqttstring the MQTTString structure into which the data is to be read
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param enddata pointer to the end of the data: do not read beyond
+ * @return 1 if successful, 0 if not
+ */
+int readMQTTLenString(MQTTString *mqttstring, unsigned char **pptr, unsigned char *enddata)
+{
+ int rc = 0;
+
+ /* the first two bytes are the length of the string */
+ if (enddata - (*pptr) > 1) { /* enough length to read the integer? */
+ mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
+ if (&(*pptr)[mqttstring->lenstring.len] <= enddata) {
+ mqttstring->lenstring.data = (char *)*pptr;
+ *pptr += mqttstring->lenstring.len;
+ rc = 1;
+ }
+ }
+ mqttstring->cstring = NULL;
+ return rc;
+}
+
+
+/**
+ * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
+ * @param mqttstring the string to return the length of
+ * @return the length of the string
+ */
+int MQTTstrlen(MQTTString mqttstring)
+{
+ int rc = 0;
+
+ if (mqttstring.cstring) {
+ rc = strlen(mqttstring.cstring);
+ } else {
+ rc = mqttstring.lenstring.len;
+ }
+ return rc;
+}
+
+
+/**
+ * Compares an MQTTString to a C string
+ * @param a the MQTTString to compare
+ * @param bptr the C string to compare
+ * @return int - equal or not
+ */
+int MQTTPacket_equals(MQTTString *a, char *bptr)
+{
+ int alen = 0,
+ blen = 0;
+ char *aptr;
+#if !(WITH_MQTT_ZIP_TOPIC)
+ if (a->cstring) {
+ aptr = a->cstring;
+ alen = strlen(a->cstring);
+ } else {
+ aptr = a->lenstring.data;
+ alen = a->lenstring.len;
+ }
+ blen = strlen(bptr);
+#else
+ aptr = a->lenstring.data;
+ alen = a->lenstring.len;
+ blen = alen;
+#endif
+ return (alen == blen) && (memcmp(aptr, bptr, alen) == 0);
+
+}
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPacket.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPacket.h
new file mode 100644
index 00000000..e93dfc50
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPacket.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef MQTTPACKET_H_
+#define MQTTPACKET_H_
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#if defined(WIN32_DLL) || defined(WIN64_DLL)
+#define DLLImport __declspec(dllimport)
+#define DLLExport __declspec(dllexport)
+#elif defined(LINUX_SO)
+#define DLLImport extern
+#define DLLExport __attribute__ ((visibility ("default")))
+#else
+#define DLLImport
+#define DLLExport
+#endif
+
+enum errors {
+ MQTTPACKET_BUFFER_TOO_SHORT = -2,
+ MQTTPACKET_READ_ERROR = -1,
+ MQTTPACKET_READ_COMPLETE
+};
+
+
+/* CPT, control packet type */
+enum msgTypes {
+ MQTT_CPT_RESERVED = 0, CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
+ PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
+ PINGREQ, PINGRESP, DISCONNECT
+};
+
+#define MQTT_HEADER_BIT_MASK_TYPE (0xF0)
+#define MQTT_HEADER_BIT_MASK_DUP (0x08)
+#define MQTT_HEADER_BIT_MASK_QOS (0x06)
+#define MQTT_HEADER_BIT_MASK_RETAIN (0x01)
+
+#define MQTT_HEADER_GET_TYPE(head) ((head & 0xF0) >> 4)
+#define MQTT_HEADER_GET_DUP(head) ((head & 0x08) >> 3)
+#define MQTT_HEADER_GET_QOS(head) ((head & 0x06) >> 1)
+#define MQTT_HEADER_GET_RETAIN(head) (head & 0x01)
+
+#define MQTT_HEADER_SET_TYPE(head, type) do {head |= ((type << 4) & 0xF0); } while (0)
+#define MQTT_HEADER_SET_DUP(head, dup) do {head |= ((dup << 3) & 0x08); } while (0)
+#define MQTT_HEADER_SET_QOS(head, qos) do {head |= ((qos << 1) & 0x06); } while (0)
+#define MQTT_HEADER_SET_RETAIN(head, retain) do {head |= (retain & 0x01); } while (0)
+
+/**
+ * Bitfields for the MQTT header byte.
+ */
+typedef union
+{
+ unsigned char byte; /**< the whole byte */
+} MQTTHeader;
+
+typedef struct {
+ int len;
+ char *data;
+} MQTTLenString;
+
+typedef struct {
+ char *cstring;
+ MQTTLenString lenstring;
+} MQTTString;
+
+#define MQTTString_initializer {NULL, {0, NULL}}
+
+int MQTTstrlen(MQTTString mqttstring);
+
+#include "MQTTConnect.h"
+#include "MQTTPublish.h"
+#include "MQTTSubscribe.h"
+#include "MQTTUnsubscribe.h"
+
+int MQTTSerialize_ack(unsigned char *buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
+int MQTTDeserialize_ack(unsigned char *packettype, unsigned char *dup, unsigned short *packetid, unsigned char *buf,
+ int buflen);
+
+int MQTTPacket_len(int rem_len);
+int MQTTPacket_equals(MQTTString *a, char *b);
+
+int MQTTPacket_encode(unsigned char *buf, int length);
+int MQTTPacket_decode(int (*getcharfn)(unsigned char *, int), int *value);
+int MQTTPacket_decodeBuf(unsigned char *buf, int *value);
+
+int readInt(unsigned char **pptr);
+char readChar(unsigned char **pptr);
+void writeChar(unsigned char **pptr, char c);
+void writeInt(unsigned char **pptr, int anInt);
+int readMQTTLenString(MQTTString *mqttstring, unsigned char **pptr, unsigned char *enddata);
+void writeCString(unsigned char **pptr, const char *string);
+void writeMQTTString(unsigned char **pptr, MQTTString mqttstring);
+
+typedef struct {
+ int (*getfn)(void *, unsigned char *,
+ int); /* must return -1 for error, 0 for call again, or the number of bytes read */
+ void *sck; /* pointer to whatever the system may use to identify the transport */
+ int multiplier;
+ int rem_len;
+ int len;
+ char state;
+} MQTTTransport;
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+
+#endif /* MQTTPACKET_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPublish.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPublish.h
new file mode 100644
index 00000000..4cb4e6a6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTPublish.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef MQTTPUBLISH_H_
+#define MQTTPUBLISH_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_publish(unsigned char *buf, int buflen, unsigned char dup, int qos, unsigned char retained,
+ unsigned short packetid,
+ MQTTString topicName, unsigned char *payload, int payloadlen);
+
+DLLExport int MQTTDeserialize_publish(unsigned char *dup, int *qos, unsigned char *retained, unsigned short *packetid,
+ MQTTString *topicName,
+ unsigned char **payload, int *payloadlen, unsigned char *buf, int len);
+
+/* DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid); */
+DLLExport int MQTTSerialize_pubrel(unsigned char *buf, int buflen, unsigned char dup, unsigned short packetid);
+DLLExport int MQTTSerialize_pubcomp(unsigned char *buf, int buflen, unsigned short packetid);
+
+#endif /* MQTTPUBLISH_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSerializePublish.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSerializePublish.c
new file mode 100644
index 00000000..4c068b70
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSerializePublish.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "MQTTPacket.h"
+
+#include
+
+
+/**
+ * Determines the length of the MQTT publish packet that would be produced using the supplied parameters
+ * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
+ * @param topicName the topic name to be used in the publish
+ * @param payloadlen the length of the payload to be sent
+ * @return the length of buffer needed to contain the serialized version of the packet
+ */
+int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen)
+{
+ int len = 0;
+
+ len += 2 + MQTTstrlen(topicName) + payloadlen;
+ if (qos > 0) {
+ len += 2; /* packetid */
+ }
+ return len;
+}
+
+
+/**
+ * Serializes the supplied publish data into the supplied buffer, ready for sending
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param dup integer - the MQTT dup flag
+ * @param qos integer - the MQTT QoS value
+ * @param retained integer - the MQTT retained flag
+ * @param packetid integer - the MQTT packet identifier
+ * @param topicName MQTTString - the MQTT topic in the publish
+ * @param payload byte buffer - the MQTT publish payload
+ * @param payloadlen integer - the length of the MQTT payload
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_publish(unsigned char *buf, int buflen, unsigned char dup, int qos, unsigned char retained,
+ unsigned short packetid,
+ MQTTString topicName, unsigned char *payload, int payloadlen)
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ int rem_len = 0;
+ int rc = 0;
+
+ if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen) {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ MQTT_HEADER_SET_TYPE(header.byte, PUBLISH);
+ MQTT_HEADER_SET_DUP(header.byte, dup);
+ MQTT_HEADER_SET_QOS(header.byte, qos);
+ MQTT_HEADER_SET_RETAIN(header.byte, retained);
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+ writeMQTTString(&ptr, topicName);
+
+ if (qos > 0) {
+ writeInt(&ptr, packetid);
+ }
+
+ memcpy(ptr, payload, payloadlen);
+ ptr += payloadlen;
+
+ rc = ptr - buf;
+
+exit:
+ return rc;
+}
+
+
+
+/**
+ * Serializes the ack packet into the supplied buffer.
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param type the MQTT packet type
+ * @param dup the MQTT dup flag
+ * @param packetid the MQTT packet identifier
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_ack(unsigned char *buf, int buflen, unsigned char packettype, unsigned char dup,
+ unsigned short packetid)
+{
+ MQTTHeader header = {0};
+ int rc = 0;
+ unsigned char *ptr = buf;
+
+ if (buflen < 4) {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+ MQTT_HEADER_SET_TYPE(header.byte, packettype);
+ MQTT_HEADER_SET_DUP(header.byte, dup);
+ MQTT_HEADER_SET_QOS(header.byte, ((packettype == PUBREL) ? 1 : 0));
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+ writeInt(&ptr, packetid);
+ rc = ptr - buf;
+exit:
+ return rc;
+}
+
+
+/**
+ * Serializes a puback packet into the supplied buffer.
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param packetid integer - the MQTT packet identifier
+ * @return serialized length, or error if 0
+ */
+/* int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid) */
+/* { */
+/* return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid); */
+/* } */
+
+#if WITH_MQTT_QOS2_PACKET
+/**
+ * Serializes a pubrel packet into the supplied buffer.
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param dup integer - the MQTT dup flag
+ * @param packetid integer - the MQTT packet identifier
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_pubrel(unsigned char *buf, int buflen, unsigned char dup, unsigned short packetid)
+{
+ return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid);
+}
+
+
+/**
+ * Serializes a pubrel packet into the supplied buffer.
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param packetid integer - the MQTT packet identifier
+ * @return serialized length, or error if 0
+ */
+int MQTTSerialize_pubcomp(unsigned char *buf, int buflen, unsigned short packetid)
+{
+ return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
+}
+#endif /* #if WITH_MQTT_QOS2_PACKET */
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSubscribe.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSubscribe.h
new file mode 100644
index 00000000..ecd04d6a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSubscribe.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef MQTTSUBSCRIBE_H_
+#define MQTTSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_subscribe(unsigned char *buf, int buflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[], int requestedQoSs[]);
+
+DLLExport int MQTTDeserialize_subscribe(unsigned char *dup, unsigned short *packetid,
+ int maxcount, int *count, MQTTString topicFilters[], int requestedQoSs[], unsigned char *buf, int len);
+
+DLLExport int MQTTSerialize_suback(unsigned char *buf, int buflen, unsigned short packetid, int count,
+ int *grantedQoSs);
+
+DLLExport int MQTTDeserialize_suback(unsigned short *packetid, int maxcount, int *count, int grantedQoSs[],
+ unsigned char *buf, int len);
+
+
+#endif /* MQTTSUBSCRIBE_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSubscribeClient.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSubscribeClient.c
new file mode 100644
index 00000000..4a26ca29
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTSubscribeClient.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "MQTTPacket.h"
+
+#include
+
+/**
+ * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
+ * @param count the number of topic filter strings in topicFilters
+ * @param topicFilters the array of topic filter strings to be used in the publish
+ * @return the length of buffer needed to contain the serialized version of the packet
+ */
+int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[])
+{
+ int i;
+ int len = 2; /* packetid */
+
+ for (i = 0; i < count; ++i) {
+ len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
+ }
+ return len;
+}
+
+
+/**
+ * Serializes the supplied subscribe data into the supplied buffer, ready for sending
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied bufferr
+ * @param dup integer - the MQTT dup flag
+ * @param packetid integer - the MQTT packet identifier
+ * @param count - number of members in the topicFilters and reqQos arrays
+ * @param topicFilters - array of topic filter names
+ * @param requestedQoSs - array of requested QoS
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_subscribe(unsigned char *buf, int buflen, unsigned char dup, unsigned short packetid, int count,
+ MQTTString topicFilters[], int requestedQoSs[])
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ int rem_len = 0;
+ int rc = 0;
+ int i = 0;
+
+ if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen) {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.byte = 0;
+ MQTT_HEADER_SET_TYPE(header.byte, SUBSCRIBE);
+ MQTT_HEADER_SET_DUP(header.byte, dup);
+ MQTT_HEADER_SET_QOS(header.byte, 1);
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+ writeInt(&ptr, packetid);
+
+ for (i = 0; i < count; ++i) {
+ writeMQTTString(&ptr, topicFilters[i]);
+ writeChar(&ptr, requestedQoSs[i]);
+ }
+
+ rc = ptr - buf;
+exit:
+ return rc;
+}
+
+
+
+/**
+ * Deserializes the supplied (wire) buffer into suback data
+ * @param packetid returned integer - the MQTT packet identifier
+ * @param maxcount - the maximum number of members allowed in the grantedQoSs array
+ * @param count returned integer - number of members in the grantedQoSs array
+ * @param grantedQoSs returned array of integers - the granted qualities of service
+ * @param buf the raw buffer data, of the correct length determined by the remaining length field
+ * @param buflen the length in bytes of the data in the supplied buffer
+ * @return error code. 1 is success, 0 is failure
+ */
+int MQTTDeserialize_suback(unsigned short *packetid, int maxcount, int *count, int grantedQoSs[], unsigned char *buf,
+ int buflen)
+{
+ MQTTHeader header = {0};
+ unsigned char *curdata = buf;
+ unsigned char *enddata = NULL;
+ int rc = 0;
+ int mylen;
+
+ header.byte = readChar(&curdata);
+ if (MQTT_HEADER_GET_TYPE(header.byte) != SUBACK) {
+ goto exit;
+ }
+
+ curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+ enddata = curdata + mylen;
+ if (enddata - curdata < 2) {
+ goto exit;
+ }
+
+ *packetid = readInt(&curdata);
+
+ *count = 0;
+ while (curdata < enddata) {
+ if (*count >= maxcount) {
+ rc = -1;
+ goto exit;
+ }
+ grantedQoSs[(*count)++] = readChar(&curdata);
+ }
+
+ rc = 1;
+exit:
+ return rc;
+}
+
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTUnsubscribe.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTUnsubscribe.h
new file mode 100644
index 00000000..ab449115
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTUnsubscribe.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef MQTTUNSUBSCRIBE_H_
+#define MQTTUNSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+ #define DLLImport
+#endif
+#if !defined(DLLExport)
+ #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_unsubscribe(unsigned char *buf, int buflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[]);
+
+DLLExport int MQTTDeserialize_unsubscribe(unsigned char *dup, unsigned short *packetid, int max_count, int *count,
+ MQTTString topicFilters[],
+ unsigned char *buf, int len);
+
+DLLExport int MQTTSerialize_unsuback(unsigned char *buf, int buflen, unsigned short packetid);
+
+DLLExport int MQTTDeserialize_unsuback(unsigned short *packetid, unsigned char *buf, int len);
+
+#endif /* MQTTUNSUBSCRIBE_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTUnsubscribeClient.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTUnsubscribeClient.c
new file mode 100644
index 00000000..2463a4d8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/MQTTUnsubscribeClient.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "MQTTPacket.h"
+
+#include
+
+/**
+ * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
+ * @param count the number of topic filter strings in topicFilters
+ * @param topicFilters the array of topic filter strings to be used in the publish
+ * @return the length of buffer needed to contain the serialized version of the packet
+ */
+int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[])
+{
+ int i;
+ int len = 2; /* packetid */
+
+ for (i = 0; i < count; ++i) {
+ len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
+ }
+ return len;
+}
+
+
+/**
+ * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
+ * @param buf the raw buffer data, of the correct length determined by the remaining length field
+ * @param buflen the length in bytes of the data in the supplied buffer
+ * @param dup integer - the MQTT dup flag
+ * @param packetid integer - the MQTT packet identifier
+ * @param count - number of members in the topicFilters array
+ * @param topicFilters - array of topic filter names
+ * @return the length of the serialized data. <= 0 indicates error
+ */
+int MQTTSerialize_unsubscribe(unsigned char *buf, int buflen, unsigned char dup, unsigned short packetid,
+ int count, MQTTString topicFilters[])
+{
+ unsigned char *ptr = buf;
+ MQTTHeader header = {0};
+ int rem_len = 0;
+ int rc = -1;
+ int i = 0;
+
+ if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen) {
+ rc = MQTTPACKET_BUFFER_TOO_SHORT;
+ goto exit;
+ }
+
+ header.byte = 0;
+ MQTT_HEADER_SET_TYPE(header.byte, UNSUBSCRIBE);
+ MQTT_HEADER_SET_DUP(header.byte, dup);
+ MQTT_HEADER_SET_QOS(header.byte, 1);
+ writeChar(&ptr, header.byte); /* write header */
+
+ ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+ writeInt(&ptr, packetid);
+
+ for (i = 0; i < count; ++i) {
+ writeMQTTString(&ptr, topicFilters[i]);
+ }
+
+ rc = ptr - buf;
+exit:
+ return rc;
+}
+
+
+/**
+ * Deserializes the supplied (wire) buffer into unsuback data
+ * @param packetid returned integer - the MQTT packet identifier
+ * @param buf the raw buffer data, of the correct length determined by the remaining length field
+ * @param buflen the length in bytes of the data in the supplied buffer
+ * @return error code. 1 is success, 0 is failure
+ */
+int MQTTDeserialize_unsuback(unsigned short *packetid, unsigned char *buf, int buflen)
+{
+ unsigned char type = 0;
+ unsigned char dup = 0;
+ int rc = 0;
+
+ rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
+ if (type == UNSUBACK) {
+ rc = 1;
+ }
+ return rc;
+}
+
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_client.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_client.c
new file mode 100644
index 00000000..b36f35a6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_client.c
@@ -0,0 +1,3174 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "mqtt_internal.h"
+
+#ifdef LOG_REPORT_TO_CLOUD
+ #include "iotx_log_report.h"
+#endif
+static int _in_yield_cb;
+
+#ifndef PLATFORM_HAS_DYNMEM
+iotx_mc_client_t g_iotx_mc_client[IOTX_MC_CLIENT_MAX_COUNT] = {0};
+#endif
+
+static void iotx_mc_release(iotx_mc_client_t *pclient)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(pclient);
+#else
+ memset(pclient, 0, sizeof(iotx_mc_client_t));
+#endif
+}
+
+#if !WITH_MQTT_ONLY_QOS0
+static void iotx_mc_pub_wait_list_init(iotx_mc_client_t *pClient)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ INIT_LIST_HEAD(&pClient->list_pub_wait_ack);
+#else
+ memset(pClient->list_pub_wait_ack, 0, sizeof(iotx_mc_pub_info_t) * IOTX_MC_PUBWAIT_LIST_MAX_LEN);
+#endif
+}
+
+static void iotx_mc_pub_wait_list_deinit(iotx_mc_client_t *pClient)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_pub_info_t *node = NULL, *next_node = NULL;
+ list_for_each_entry_safe(node, next_node, &pClient->list_pub_wait_ack, linked_list, iotx_mc_pub_info_t) {
+ list_del(&node->linked_list);
+ mqtt_free(node);
+ }
+#else
+ memset(pClient->list_pub_wait_ack, 0, sizeof(iotx_mc_pub_info_t) * IOTX_MC_PUBWAIT_LIST_MAX_LEN);
+#endif
+}
+#endif
+/* set MQTT connection parameter */
+static int iotx_mc_set_connect_params(iotx_mc_client_t *pClient, MQTTPacket_connectData *pConnectParams)
+{
+ if (NULL == pClient || NULL == pConnectParams) {
+ return NULL_VALUE_ERROR;
+ }
+
+ memcpy(pClient->connect_data.struct_id, pConnectParams->struct_id, 4);
+ pClient->connect_data.struct_version = pConnectParams->struct_version;
+ pClient->connect_data.MQTTVersion = pConnectParams->MQTTVersion;
+ pClient->connect_data.clientID = pConnectParams->clientID;
+ pClient->connect_data.cleansession = pConnectParams->cleansession;
+ pClient->connect_data.willFlag = pConnectParams->willFlag;
+ pClient->connect_data.username = pConnectParams->username;
+ pClient->connect_data.password = pConnectParams->password;
+ memcpy(pClient->connect_data.will.struct_id, pConnectParams->will.struct_id, 4);
+ pClient->connect_data.will.struct_version = pConnectParams->will.struct_version;
+ pClient->connect_data.will.topicName = pConnectParams->will.topicName;
+ pClient->connect_data.will.message = pConnectParams->will.message;
+ pClient->connect_data.will.qos = pConnectParams->will.qos;
+ pClient->connect_data.will.retained = pConnectParams->will.retained;
+
+ if (pConnectParams->keepAliveInterval < CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN) {
+ mqtt_warning("Input heartbeat interval(%d ms) < Allowed minimum(%d ms)",
+ (pConnectParams->keepAliveInterval * 1000),
+ (CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN * 1000)
+ );
+ mqtt_warning("Reset heartbeat interval => %d Millisecond",
+ (CONFIG_MQTT_KEEPALIVE_INTERVAL * 1000)
+ );
+ pClient->connect_data.keepAliveInterval = CONFIG_MQTT_KEEPALIVE_INTERVAL;
+ } else if (pConnectParams->keepAliveInterval > CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX) {
+ mqtt_warning("Input heartbeat interval(%d ms) > Allowed maximum(%d ms)",
+ (pConnectParams->keepAliveInterval * 1000),
+ (CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX * 1000)
+ );
+ mqtt_warning("Reset heartbeat interval => %d Millisecond",
+ (CONFIG_MQTT_KEEPALIVE_INTERVAL * 1000)
+ );
+ pClient->connect_data.keepAliveInterval = CONFIG_MQTT_KEEPALIVE_INTERVAL;
+ } else {
+ pClient->connect_data.keepAliveInterval = pConnectParams->keepAliveInterval;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+/* set state of MQTT client */
+static void iotx_mc_set_client_state(iotx_mc_client_t *pClient, iotx_mc_state_t newState)
+{
+ HAL_MutexLock(pClient->lock_generic);
+ pClient->client_state = newState;
+ HAL_MutexUnlock(pClient->lock_generic);
+}
+
+static iotx_mc_state_t iotx_mc_get_client_state(iotx_mc_client_t *pClient)
+{
+ iotx_mc_state_t state;
+ HAL_MutexLock(pClient->lock_generic);
+ state = pClient->client_state;
+ HAL_MutexUnlock(pClient->lock_generic);
+
+ return state;
+}
+
+/* Initialize MQTT client */
+static int iotx_mc_init(iotx_mc_client_t *pClient, iotx_mqtt_param_t *pInitParams)
+{
+ int rc = FAIL_RETURN;
+ iotx_mc_state_t mc_state = IOTX_MC_STATE_INVALID;
+ MQTTPacket_connectData connectdata = MQTTPacket_connectData_initializer;
+
+ if (pClient == NULL || pInitParams == NULL || pInitParams->write_buf_size == 0 || pInitParams->read_buf_size == 0) {
+ return NULL_VALUE_ERROR;
+ }
+
+ pClient->lock_generic = HAL_MutexCreate();
+ if (!pClient->lock_generic) {
+ return FAIL_RETURN;
+ }
+
+ pClient->lock_list_pub = HAL_MutexCreate();
+ if (!pClient->lock_list_pub) {
+ goto RETURN;
+ }
+
+ pClient->lock_yield = HAL_MutexCreate();
+ if (!pClient->lock_yield) {
+ goto RETURN;
+ }
+
+ pClient->lock_write_buf = HAL_MutexCreate();
+ if (!pClient->lock_write_buf) {
+ goto RETURN;
+ }
+
+ pClient->lock_read_buf = HAL_MutexCreate();
+ if (!pClient->lock_read_buf) {
+ goto RETURN;
+ }
+
+ connectdata.MQTTVersion = IOTX_MC_MQTT_VERSION;
+ connectdata.keepAliveInterval = pInitParams->keepalive_interval_ms / 1000;
+
+
+ connectdata.clientID.cstring = (char *)pInitParams->client_id;
+ connectdata.username.cstring = (char *)pInitParams->username;
+ connectdata.password.cstring = (char *)pInitParams->password;
+ connectdata.cleansession = pInitParams->clean_session;
+
+ if (pInitParams->request_timeout_ms < CONFIG_MQTT_REQ_TIMEOUT_MIN
+ || pInitParams->request_timeout_ms > CONFIG_MQTT_REQ_TIMEOUT_MAX) {
+
+ pClient->request_timeout_ms = CONFIG_MQTT_REQUEST_TIMEOUT;
+ } else {
+ pClient->request_timeout_ms = pInitParams->request_timeout_ms;
+ }
+
+#ifdef PLATFORM_HAS_DYNMEM
+#if !( WITH_MQTT_DYN_BUF)
+ pClient->buf_send = mqtt_malloc(pInitParams->write_buf_size);
+ if (pClient->buf_send == NULL) {
+ goto RETURN;
+ }
+ pClient->buf_size_send = pInitParams->write_buf_size;
+
+ pClient->buf_read = mqtt_malloc(pInitParams->read_buf_size);
+ if (pClient->buf_read == NULL) {
+ goto RETURN;
+ }
+ pClient->buf_size_read = pInitParams->read_buf_size;
+#else
+ pClient->buf_size_send_max = pInitParams->write_buf_size;
+ pClient->buf_size_read_max = pInitParams->read_buf_size;
+#endif
+#else
+ pClient->buf_size_send = IOTX_MC_TX_MAX_LEN;
+ pClient->buf_size_read = IOTX_MC_RX_MAX_LEN;
+#endif
+
+ pClient->keepalive_probes = 0;
+
+ pClient->handle_event.h_fp = pInitParams->handle_event.h_fp;
+ pClient->handle_event.pcontext = pInitParams->handle_event.pcontext;
+
+ /* Initialize reconnect parameter */
+ pClient->reconnect_param.reconnect_time_interval_ms = IOTX_MC_RECONNECT_INTERVAL_MIN_MS;
+#if !WITH_MQTT_ONLY_QOS0
+ iotx_mc_pub_wait_list_init(pClient);
+#endif
+
+#ifdef PLATFORM_HAS_DYNMEM
+ INIT_LIST_HEAD(&pClient->list_sub_handle);
+ INIT_LIST_HEAD(&pClient->list_sub_sync_ack);
+#endif
+ /* Initialize MQTT connect parameter */
+ rc = iotx_mc_set_connect_params(pClient, &connectdata);
+ if (SUCCESS_RETURN != rc) {
+ mc_state = IOTX_MC_STATE_INVALID;
+ goto RETURN;
+ }
+
+ iotx_time_init(&pClient->next_ping_time);
+ iotx_time_init(&pClient->reconnect_param.reconnect_next_time);
+
+ memset(&pClient->ipstack, 0, sizeof(utils_network_t));
+
+#ifdef SUPPORT_TLS
+ {
+ extern const char *iotx_ca_crt;
+ pInitParams->pub_key = iotx_ca_crt;
+ }
+#endif
+
+ rc = iotx_net_init(&pClient->ipstack, pInitParams->host, pInitParams->port, pInitParams->pub_key);
+
+ if (SUCCESS_RETURN != rc) {
+ mc_state = IOTX_MC_STATE_INVALID;
+ goto RETURN;
+ }
+
+ mc_state = IOTX_MC_STATE_INITIALIZED;
+ rc = SUCCESS_RETURN;
+ mqtt_info("MQTT init success!");
+
+RETURN :
+ iotx_mc_set_client_state(pClient, mc_state);
+ if (rc != SUCCESS_RETURN) {
+#ifdef PLATFORM_HAS_DYNMEM
+ if (pClient->buf_send != NULL) {
+ mqtt_free(pClient->buf_send);
+ pClient->buf_send = NULL;
+ }
+ if (pClient->buf_read != NULL) {
+ mqtt_free(pClient->buf_read);
+ pClient->buf_read = NULL;
+ }
+#endif
+ if (pClient->lock_list_pub) {
+ HAL_MutexDestroy(pClient->lock_list_pub);
+ pClient->lock_list_pub = NULL;
+ }
+ if (pClient->lock_write_buf) {
+ HAL_MutexDestroy(pClient->lock_write_buf);
+ pClient->lock_write_buf = NULL;
+ }
+ if (pClient->lock_read_buf) {
+ HAL_MutexDestroy(pClient->lock_read_buf);
+ pClient->lock_read_buf = NULL;
+ }
+ if (pClient->lock_yield) {
+ HAL_MutexDestroy(pClient->lock_yield);
+ pClient->lock_yield = NULL;
+ }
+ }
+
+ return rc;
+}
+
+#ifdef PLATFORM_HAS_DYNMEM
+ #if WITH_MQTT_DYN_BUF
+ extern int MQTTPacket_len(int rem_len);
+ extern int MQTTSerialize_connectLength(MQTTPacket_connectData *options);
+ #endif
+#endif
+
+static int _get_connect_length(MQTTPacket_connectData *options)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+#if WITH_MQTT_DYN_BUF
+ return MQTTPacket_len(MQTTSerialize_connectLength(options));
+#else
+ return 0;
+#endif
+#else
+ return 0;
+#endif
+}
+
+static int _reset_send_buffer(iotx_mc_client_t *c)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+#if WITH_MQTT_DYN_BUF
+ if (c == NULL || c->buf_send == NULL) {
+ return FAIL_RETURN;
+ }
+
+ mqtt_free(c->buf_send);
+ c->buf_send = NULL;
+ c->buf_size_send = 0;
+ return 0;
+#else
+ return 0;
+#endif
+#else
+ return 0;
+#endif
+}
+
+static int _reset_recv_buffer(iotx_mc_client_t *c)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+#if WITH_MQTT_DYN_BUF
+ if (c == NULL || c->buf_read == NULL) {
+ return FAIL_RETURN;
+ }
+
+ mqtt_free(c->buf_read);
+ c->buf_read = NULL;
+ c->buf_size_read = 0;
+ return 0;
+#else
+ return 0;
+#endif
+#else
+ return 0;
+#endif
+}
+
+static int _alloc_send_buffer(iotx_mc_client_t *c, int len)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+#if WITH_MQTT_DYN_BUF
+ int tmp_len;
+
+ if (c == NULL) {
+ return FAIL_RETURN;
+ }
+
+ tmp_len = MQTT_DYNBUF_SEND_MARGIN + len;
+ if (tmp_len > c->buf_size_send_max) {
+ tmp_len = c->buf_size_send_max;
+ }
+ if (c->buf_send != NULL) {
+ mqtt_warning("c->buf_send is not null,free it first!");
+ mqtt_free(c->buf_send);
+ }
+ c->buf_send = mqtt_malloc(tmp_len);
+ if (c->buf_send == NULL) {
+ return ERROR_MALLOC;
+ }
+ memset(c->buf_send, 0, tmp_len);
+ c->buf_size_send = tmp_len;
+ return SUCCESS_RETURN;
+#else
+ return 0;
+#endif
+#else
+ return 0;
+#endif
+}
+
+static int _alloc_recv_buffer(iotx_mc_client_t *c, int len)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+#if WITH_MQTT_DYN_BUF
+ int tmp_len;
+
+ if (c == NULL) {
+ return FAIL_RETURN;
+ }
+
+ tmp_len = MQTT_DYNBUF_RECV_MARGIN + len;
+ if (tmp_len > c->buf_size_read_max) {
+ tmp_len = c->buf_size_read_max;
+ }
+ if (c->buf_read != NULL) { /* do realloc */
+ char *temp = mqtt_malloc(tmp_len);
+ if (temp == NULL) {
+ mqtt_err("realloc err");
+ return ERROR_MALLOC;
+ }
+ memset(temp, 0, tmp_len);
+ memcpy(temp, c->buf_read, c->buf_size_read < tmp_len ? c->buf_size_read : tmp_len);
+ mqtt_free(c->buf_read);
+ c->buf_read = temp;
+ } else {
+ c->buf_read = mqtt_malloc(tmp_len);
+ if (c->buf_read == NULL) {
+ mqtt_err("calloc err");
+ return ERROR_MALLOC;
+ }
+ memset(c->buf_read, 0, tmp_len);
+ }
+ c->buf_size_read = tmp_len;
+ return SUCCESS_RETURN;
+#else
+ return 0;
+#endif
+#else
+ return 0;
+#endif
+}
+
+static int iotx_mc_send_packet(iotx_mc_client_t *c, char *buf, int length, iotx_time_t *time)
+{
+ int rc = FAIL_RETURN;
+ int sent = 0;
+ unsigned int left_t = 0;
+
+ if (!c || !buf || !time) {
+ return rc;
+ }
+
+ while (sent < length && !utils_time_is_expired(time)) {
+ left_t = iotx_time_left(time);
+ left_t = (left_t == 0) ? 1 : left_t;
+ rc = c->ipstack.write(&c->ipstack, &buf[sent], length - sent, left_t);
+ if (rc < 0) { /* there was an error writing the data */
+ break;
+ }
+ sent += rc;
+ }
+
+ if (sent == length) {
+ rc = SUCCESS_RETURN;
+ } else {
+ rc = MQTT_NETWORK_ERROR;
+ }
+ return rc;
+}
+
+int MQTTConnect(iotx_mc_client_t *pClient)
+{
+ MQTTPacket_connectData *pConnectParams;
+ iotx_time_t connectTimer;
+ int len = 0;
+
+ if (!pClient) {
+ return FAIL_RETURN;
+ }
+
+ pConnectParams = &pClient->connect_data;
+ HAL_MutexLock(pClient->lock_write_buf);
+
+ len = _get_connect_length(pConnectParams);
+
+ if (_alloc_send_buffer(pClient, len) != SUCCESS_RETURN) {
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return FAIL_RETURN;
+ }
+
+ if ((len = MQTTSerialize_connect((unsigned char *)pClient->buf_send, pClient->buf_size_send, pConnectParams)) <= 0) {
+ mqtt_err("Serialize connect packet failed, len = %d", len);
+ _reset_send_buffer(pClient);
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return MQTT_CONNECT_PACKET_ERROR;
+ }
+
+ /* send the connect packet */
+ iotx_time_init(&connectTimer);
+ utils_time_countdown_ms(&connectTimer, pClient->request_timeout_ms);
+ if ((iotx_mc_send_packet(pClient, pClient->buf_send, len, &connectTimer)) != SUCCESS_RETURN) {
+ mqtt_err("send connect packet failed");
+ _reset_send_buffer(pClient);
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+ _reset_send_buffer(pClient);
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_decode_packet(iotx_mc_client_t *c, int *value, int timeout)
+{
+ char i;
+ int multiplier = 1;
+ int len = 0;
+ const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+ if (!c || !value) {
+ return FAIL_RETURN;
+ }
+
+ *value = 0;
+ do {
+ int rc = MQTTPACKET_READ_ERROR;
+
+ if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) {
+ return MQTTPACKET_READ_ERROR; /* bad data */
+ }
+
+ rc = c->ipstack.read(&c->ipstack, &i, 1, timeout == 0 ? 1 : timeout);
+ if (rc == 0) {
+ return FAIL_RETURN;
+ } else if (rc != 1) {
+ return MQTT_NETWORK_ERROR;
+ }
+
+ *value += (i & 127) * multiplier;
+ multiplier *= 128;
+ } while ((i & 128) != 0);
+
+ return len;
+}
+
+static int _handle_event(iotx_mqtt_event_handle_pt handle, iotx_mc_client_t *c, iotx_mqtt_event_msg_pt msg)
+{
+ if (handle == NULL || handle->h_fp == NULL) {
+ return FAIL_RETURN;
+ }
+
+ _in_yield_cb = 1;
+ handle->h_fp(handle->pcontext, c, msg);
+ _in_yield_cb = 0;
+ return 0;
+}
+
+static int iotx_mc_read_packet(iotx_mc_client_t *c, iotx_time_t *timer, unsigned int *packet_type)
+{
+ MQTTHeader header = {0};
+ int len = 0;
+ int rem_len = 0;
+ int rc = 0;
+ unsigned int left_t = 0;
+
+ if (!c || !timer || !packet_type) {
+ return FAIL_RETURN;
+ }
+ HAL_MutexLock(c->lock_read_buf);
+ rc = _alloc_recv_buffer(c, 0);
+ if (rc < 0) {
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+ /* 1. read the header byte. This has the packet type in it */
+ left_t = iotx_time_left(timer);
+ left_t = (left_t == 0) ? 1 : left_t;
+ rc = c->ipstack.read(&c->ipstack, c->buf_read, 1, left_t);
+ if (0 == rc) { /* timeout */
+ *packet_type = 0;
+ HAL_MutexUnlock(c->lock_read_buf);
+ return SUCCESS_RETURN;
+ } else if (1 != rc) {
+ mqtt_err("mqtt read error, rc=%d", rc);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+
+ len = 1;
+
+ /* 2. read the remaining length. This is variable in itself */
+ left_t = iotx_time_left(timer);
+ left_t = (left_t == 0) ? 1 : left_t;
+ if ((rc = iotx_mc_decode_packet(c, &rem_len, left_t)) < 0) {
+ mqtt_err("decodePacket error,rc = %d", rc);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return rc;
+ }
+
+ len += MQTTPacket_encode((unsigned char *)c->buf_read + 1,
+ rem_len); /* put the original remaining length back into the buffer */
+
+ rc = _alloc_recv_buffer(c, rem_len + len);
+ if (rc < 0) {
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+
+ /* Check if the received data length exceeds mqtt read buffer length */
+ if ((rem_len > 0) && ((rem_len + len) > c->buf_size_read)) {
+ int needReadLen;
+ int remainDataLen;
+#ifdef PLATFORM_HAS_DYNMEM
+ char *remainDataBuf;
+#else
+ char remainDataBuf[IOTX_MC_RX_MAX_LEN] = {0};
+#endif
+ mqtt_err("mqtt read buffer is too short, mqttReadBufLen : %u, remainDataLen : %d", c->buf_size_read, rem_len);
+ needReadLen = c->buf_size_read - len;
+ left_t = iotx_time_left(timer);
+ left_t = (left_t == 0) ? 1 : left_t;
+ rc = c->ipstack.read(&c->ipstack, c->buf_read + len, needReadLen, left_t);
+ if (rc < 0) {
+ mqtt_err("mqtt read error");
+ HAL_MutexUnlock(c->lock_read_buf);
+ return MQTT_NETWORK_ERROR;
+ } else if (rc != needReadLen) {
+ mqtt_warning("mqtt read timeout");
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+
+ /* drop data whitch over the length of mqtt buffer */
+ remainDataLen = rem_len - needReadLen;
+#ifdef PLATFORM_HAS_DYNMEM
+ remainDataBuf = mqtt_malloc(remainDataLen + 1);
+ if (!remainDataBuf) {
+ mqtt_err("allocate remain buffer failed");
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+#else
+ if (remainDataLen >= IOTX_MC_RX_MAX_LEN) {
+ mqtt_err("IOTX_MC_RX_MAX_LEN too short, remainDataLen: %d, IOTX_MC_RX_MAX_LEN: %d", remainDataLen, IOTX_MC_RX_MAX_LEN);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+#endif
+
+ left_t = iotx_time_left(timer);
+ left_t = (left_t == 0) ? 1 : left_t;
+ rc = c->ipstack.read(&c->ipstack, remainDataBuf, remainDataLen, left_t);
+ if (rc < 0) {
+ mqtt_err("mqtt read error");
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(remainDataBuf);
+ remainDataBuf = NULL;
+#endif
+ HAL_MutexUnlock(c->lock_read_buf);
+ return MQTT_NETWORK_ERROR;
+ } else if (rc != remainDataLen) {
+ mqtt_warning("mqtt read timeout");
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(remainDataBuf);
+ remainDataBuf = NULL;
+#endif
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(remainDataBuf);
+ remainDataBuf = NULL;
+#endif
+ HAL_MutexUnlock(c->lock_read_buf);
+ if (NULL != c->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+
+ msg.event_type = IOTX_MQTT_EVENT_BUFFER_OVERFLOW;
+ msg.msg = "mqtt read buffer is too short";
+ _handle_event(&c->handle_event, c, &msg);
+ }
+
+ return SUCCESS_RETURN;
+
+ }
+
+ /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+ left_t = iotx_time_left(timer);
+ left_t = (left_t == 0) ? 1 : left_t;
+
+ rc = c->ipstack.read(&c->ipstack, c->buf_read + len, rem_len, left_t);
+ if (rem_len > 0) {
+ if (rc < 0) {
+ mqtt_err("mqtt read error");
+ HAL_MutexUnlock(c->lock_read_buf);
+ return MQTT_NETWORK_ERROR;
+ } else if (rc != rem_len) {
+ mqtt_warning("mqtt read timeout");
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+ }
+
+ header.byte = c->buf_read[0];
+ *packet_type = MQTT_HEADER_GET_TYPE(header.byte);
+ if ((len + rem_len) < c->buf_size_read) {
+ c->buf_read[len + rem_len] = '\0';
+ }
+ HAL_MutexUnlock(c->lock_read_buf);
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_handle_recv_CONNACK(iotx_mc_client_t *c)
+{
+ int rc = SUCCESS_RETURN;
+ unsigned char connack_rc = 255;
+ char sessionPresent = 0;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ if (MQTTDeserialize_connack((unsigned char *)&sessionPresent, &connack_rc, (unsigned char *)c->buf_read,
+ c->buf_size_read) != 1) {
+ mqtt_err("connect ack is error");
+ return MQTT_CONNECT_ACK_PACKET_ERROR;
+ }
+
+ switch (connack_rc) {
+ case IOTX_MC_CONNECTION_ACCEPTED:
+ rc = SUCCESS_RETURN;
+ break;
+ case IOTX_MC_CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION:
+ rc = MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
+ break;
+ case IOTX_MC_CONNECTION_REFUSED_IDENTIFIER_REJECTED:
+ rc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR;
+ break;
+ case IOTX_MC_CONNECTION_REFUSED_SERVER_UNAVAILABLE:
+ rc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR;
+ break;
+ case IOTX_MC_CONNECTION_REFUSED_BAD_USERDATA:
+ rc = MQTT_CONNACK_BAD_USERDATA_ERROR;
+ break;
+ case IOTX_MC_CONNECTION_REFUSED_NOT_AUTHORIZED:
+ rc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR;
+ break;
+ default:
+ rc = MQTT_CONNACK_UNKNOWN_ERROR;
+ break;
+ }
+
+ return rc;
+}
+
+static int iotx_mc_wait_CONNACK(iotx_mc_client_t *c)
+{
+#define WAIT_CONNACK_MAX (10)
+ unsigned char wait_connack = 0;
+ unsigned int packetType = 0;
+ int rc = 0;
+ iotx_time_t timer;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+ do {
+ /* read the socket, see what work is due */
+
+ rc = iotx_mc_read_packet(c, &timer, &packetType);
+ if (rc != SUCCESS_RETURN) {
+ mqtt_err("readPacket error,result = %d", rc);
+ HAL_MutexLock(c->lock_read_buf);
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return rc;
+ }
+
+ if (++wait_connack > WAIT_CONNACK_MAX) {
+ mqtt_err("wait connack timeout");
+ HAL_MutexLock(c->lock_read_buf);
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+ } while (packetType != CONNACK);
+ HAL_MutexLock(c->lock_read_buf);
+
+ rc = iotx_mc_handle_recv_CONNACK(c);
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("recvConnackProc error,result = %d", rc);
+ }
+
+ return rc;
+}
+
+static int _mqtt_connect(void *client)
+{
+#define RETRY_TIME_LIMIT (8+1)
+#define RETRY_INTV_PERIOD (2000)
+ int rc = FAIL_RETURN;
+ int try_count = 1;
+ iotx_mc_client_t *pClient = (iotx_mc_client_t *)client;
+
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+
+ mqtt_info("connect params: MQTTVersion=%d, clientID=%s, keepAliveInterval=%d, username=%s",
+ pClient->connect_data.MQTTVersion,
+ pClient->connect_data.clientID.cstring,
+ pClient->connect_data.keepAliveInterval,
+ pClient->connect_data.username.cstring);
+
+ /* Establish TCP or TLS connection */
+ do {
+ rc = MQTTConnect(pClient);
+
+ if (rc != SUCCESS_RETURN) {
+ pClient->ipstack.disconnect(&pClient->ipstack);
+ mqtt_err("send connect packet failed, rc = %d", rc);
+ return rc;
+ }
+
+ rc = iotx_mc_wait_CONNACK(pClient);
+
+ if (rc <= MQTT_CONNACK_NOT_AUTHORIZED_ERROR && rc >= MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR) {
+ mqtt_err("received reject ACK from MQTT server! rc = %d", rc);
+ pClient->ipstack.disconnect(&pClient->ipstack);
+ return MQTT_CONNECT_ERROR;
+ }
+
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("wait connect ACK timeout! rc = %d", rc);
+ mqtt_warning("tried [%d/%d] times CONN, waiting for %d ms...", try_count, RETRY_TIME_LIMIT - 1, RETRY_INTV_PERIOD);
+
+ HAL_SleepMs(RETRY_INTV_PERIOD);
+
+ pClient->ipstack.disconnect(&pClient->ipstack);
+ pClient->ipstack.connect(&pClient->ipstack);
+ continue;
+ } else {
+ break;
+ }
+
+ } while (++try_count < RETRY_TIME_LIMIT);
+
+ if (try_count == RETRY_TIME_LIMIT) {
+ return MQTT_CONNECT_ERROR;
+ }
+
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECTED);
+
+ utils_time_countdown_ms(&pClient->next_ping_time, pClient->connect_data.keepAliveInterval * 1000);
+
+ mqtt_info("mqtt connect success!");
+ return SUCCESS_RETURN;
+}
+
+#if !WITH_MQTT_ONLY_QOS0
+static int iotx_mc_push_pubInfo_to(iotx_mc_client_t *c, int len, unsigned short msgId, iotx_mc_pub_info_t **node)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ int list_number;
+ iotx_mc_pub_info_t *repubInfo;
+#else
+ int idx;
+#endif
+
+ if (!c || !node) {
+ mqtt_err("the param of c is error!");
+ return FAIL_RETURN;
+ }
+
+ if ((len < 0) || (len > c->buf_size_send)) {
+ mqtt_err("the param of len is error!");
+#ifndef PLATFORM_HAS_DYNMEM
+ if (len >= c->buf_size_send) {
+ mqtt_err("IOTX_MC_TX_MAX_LEN is too short, len: %d, IOTX_MC_TX_MAX_LEN: %d", len, IOTX_MC_TX_MAX_LEN);
+ }
+#endif
+ return FAIL_RETURN;
+ }
+
+#ifdef PLATFORM_HAS_DYNMEM
+ list_number = list_entry_number(&c->list_pub_wait_ack);
+
+ if (list_number >= IOTX_MC_REPUB_NUM_MAX) {
+ mqtt_err("more than %u elements in republish list. List overflow!", list_number);
+ return FAIL_RETURN;
+ }
+
+ repubInfo = (iotx_mc_pub_info_t *)mqtt_malloc(sizeof(iotx_mc_pub_info_t) + len);
+ if (NULL == repubInfo) {
+ mqtt_err("run iotx_memory_malloc is error!");
+ return FAIL_RETURN;
+ }
+
+ repubInfo->node_state = IOTX_MC_NODE_STATE_NORMANL;
+ repubInfo->msg_id = msgId;
+ repubInfo->len = len;
+ iotx_time_start(&repubInfo->pub_start_time);
+ repubInfo->buf = (unsigned char *)repubInfo + sizeof(iotx_mc_pub_info_t);
+
+ memcpy(repubInfo->buf, c->buf_send, len);
+ INIT_LIST_HEAD(&repubInfo->linked_list);
+
+ list_add_tail(&repubInfo->linked_list, &c->list_pub_wait_ack);
+
+ *node = repubInfo;
+ return SUCCESS_RETURN;
+#else
+ for (idx = 0; idx < IOTX_MC_PUBWAIT_LIST_MAX_LEN; idx++) {
+ if (c->list_pub_wait_ack[idx].used == 0) {
+ c->list_pub_wait_ack[idx].node_state = IOTX_MC_NODE_STATE_NORMANL;
+ c->list_pub_wait_ack[idx].msg_id = msgId;
+ c->list_pub_wait_ack[idx].len = len;
+ iotx_time_start(&c->list_pub_wait_ack[idx].pub_start_time);
+ memcpy(c->list_pub_wait_ack[idx].buf, c->buf_send, len);
+ c->list_pub_wait_ack[idx].used = 1;
+ *node = &c->list_pub_wait_ack[idx];
+ return SUCCESS_RETURN;
+ }
+ }
+
+ mqtt_err("IOTX_MC_PUBWAIT_LIST_MAX_LEN is too short");
+
+ return FAIL_RETURN;
+#endif
+}
+
+static int iotx_mc_mask_pubInfo_from(iotx_mc_client_t *c, uint16_t msgId)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_pub_info_t *node = NULL;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ HAL_MutexLock(c->lock_list_pub);
+ list_for_each_entry(node, &c->list_pub_wait_ack, linked_list, iotx_mc_pub_info_t) {
+ if (node->msg_id == msgId) {
+ node->node_state = IOTX_MC_NODE_STATE_INVALID; /* mark as invalid node */
+ }
+ }
+ HAL_MutexUnlock(c->lock_list_pub);
+#else
+ int idx;
+
+ for (idx = 0; idx < IOTX_MC_PUBWAIT_LIST_MAX_LEN; idx++) {
+ if (c->list_pub_wait_ack[idx].used &&
+ c->list_pub_wait_ack[idx].msg_id == msgId) {
+ c->list_pub_wait_ack[idx].node_state = IOTX_MC_NODE_STATE_INVALID; /* mark as invalid node */
+ }
+ }
+#endif
+ return SUCCESS_RETURN;
+}
+
+static int MQTTRePublish(iotx_mc_client_t *c, char *buf, int len)
+{
+ iotx_time_t timer;
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+ HAL_MutexLock(c->lock_write_buf);
+
+ if (iotx_mc_send_packet(c, buf, len, &timer) != SUCCESS_RETURN) {
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+
+ HAL_MutexUnlock(c->lock_write_buf);
+ return SUCCESS_RETURN;
+}
+
+static int MQTTPubInfoProc(iotx_mc_client_t *pClient)
+{
+ int rc = 0;
+ iotx_mc_state_t state = IOTX_MC_STATE_INVALID;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_pub_info_t *node = NULL, *next_node = NULL;
+#else
+ int idx;
+#endif
+
+ if (!pClient) {
+ return FAIL_RETURN;
+ }
+
+ HAL_MutexLock(pClient->lock_list_pub);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next_node, &pClient->list_pub_wait_ack, linked_list, iotx_mc_pub_info_t) {
+ /* remove invalid node */
+ if (IOTX_MC_NODE_STATE_INVALID == node->node_state) {
+ list_del(&node->linked_list);
+ mqtt_free(node);
+ continue;
+ }
+
+ state = iotx_mc_get_client_state(pClient);
+ if (state != IOTX_MC_STATE_CONNECTED) {
+ continue;
+ }
+
+ /* check the request if timeout or not */
+ if (utils_time_spend(&node->pub_start_time) <= (pClient->request_timeout_ms * 2)) {
+ continue;
+ }
+
+ /* If wait ACK timeout, republish */
+ rc = MQTTRePublish(pClient, (char *)node->buf, node->len);
+ iotx_time_start(&node->pub_start_time);
+
+ if (MQTT_NETWORK_ERROR == rc) {
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED);
+ break;
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_PUBWAIT_LIST_MAX_LEN; idx++) {
+ if (pClient->list_pub_wait_ack[idx].used == 0) {
+ continue;
+ }
+
+ if (IOTX_MC_NODE_STATE_INVALID == pClient->list_pub_wait_ack[idx].node_state) {
+ memset(&pClient->list_pub_wait_ack[idx], 0, sizeof(iotx_mc_pub_info_t));
+ continue;
+ }
+
+ state = iotx_mc_get_client_state(pClient);
+ if (state != IOTX_MC_STATE_CONNECTED) {
+ continue;
+ }
+
+ /* check the request if timeout or not */
+ if (utils_time_spend(&pClient->list_pub_wait_ack[idx].pub_start_time) <= (pClient->request_timeout_ms * 2)) {
+ continue;
+ }
+
+ /* If wait ACK timeout, republish */
+ rc = MQTTRePublish(pClient, (char *)pClient->list_pub_wait_ack[idx].buf, pClient->list_pub_wait_ack[idx].len);
+ iotx_time_start(&pClient->list_pub_wait_ack[idx].pub_start_time);
+
+ if (MQTT_NETWORK_ERROR == rc) {
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED);
+ break;
+ }
+ }
+#endif
+ HAL_MutexUnlock(pClient->lock_list_pub);
+
+ return SUCCESS_RETURN;
+}
+
+/* handle PUBACK packet received from remote MQTT broker */
+static int iotx_mc_handle_recv_PUBACK(iotx_mc_client_t *c)
+{
+ unsigned short mypacketid;
+ unsigned char dup = 0;
+ unsigned char type = 0;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ if (MQTTDeserialize_ack(&type, &dup, &mypacketid, (unsigned char *)c->buf_read, c->buf_size_read) != 1) {
+ return MQTT_PUBLISH_ACK_PACKET_ERROR;
+ }
+
+ (void)iotx_mc_mask_pubInfo_from(c, mypacketid);
+
+ /* call callback function to notify that PUBLISH is successful */
+ if (NULL != c->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+ msg.event_type = IOTX_MQTT_EVENT_PUBLISH_SUCCESS;
+ msg.msg = (void *)(uintptr_t)mypacketid;
+ _handle_event(&c->handle_event, c, &msg);
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif
+
+static void _iotx_mqtt_event_handle_sub(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
+{
+ iotx_mc_client_t *client;
+ uintptr_t packet_id;
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_sub_sync_node_t *node = NULL;
+ mqtt_sub_sync_node_t *next = NULL;
+#else
+ int idx;
+#endif
+
+ if (pclient == NULL || msg == NULL) {
+ return;
+ }
+
+ client = (iotx_mc_client_t *)pclient;
+ packet_id = (uintptr_t) msg->msg;
+
+ mqtt_debug("packet_id = %lu, event_type=%d", packet_id, msg->event_type);
+
+ HAL_MutexLock(client->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next, &client->list_sub_sync_ack, linked_list, mqtt_sub_sync_node_t) {
+ if (node->packet_id == packet_id) {
+ node->ack_type = msg->event_type;
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) {
+ if (client->list_sub_sync_ack[idx].used &&
+ client->list_sub_sync_ack[idx].packet_id == packet_id) {
+ client->list_sub_sync_ack[idx].ack_type = msg->event_type;
+ }
+ }
+#endif
+ HAL_MutexUnlock(client->lock_generic);
+}
+
+static int iotx_mc_handle_recv_SUBACK(iotx_mc_client_t *c)
+{
+ unsigned short mypacketid;
+ iotx_mqtt_event_msg_t msg;
+ int i = 0, count = 0, fail_flag = -1, j = 0;
+ int grantedQoS[MUTLI_SUBSCIRBE_MAX];
+ int rc;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ rc = MQTTDeserialize_suback(&mypacketid, MUTLI_SUBSCIRBE_MAX, &count, grantedQoS, (unsigned char *)c->buf_read,
+ c->buf_size_read);
+
+ if (rc < 0) {
+ mqtt_err("Sub ack packet error, rc = MQTTDeserialize_suback() = %d", rc);
+ return MQTT_SUBSCRIBE_ACK_PACKET_ERROR;
+ }
+
+ mqtt_debug("%20s : %d", "Return Value", rc);
+ mqtt_debug("%20s : %d", "Packet ID", mypacketid);
+ mqtt_debug("%20s : %d", "Count", count);
+ for (i = 0; i < count; ++i) {
+ mqtt_debug("%16s[%02d] : %d", "Granted QoS", i, grantedQoS[i]);
+ }
+
+ for (j = 0; j < count; j++) {
+ fail_flag = 0;
+ /* In negative case, grantedQoS will be 0xFFFF FF80, which means -128 */
+ if ((uint8_t)grantedQoS[j] == 0x80) {
+ fail_flag = 1;
+ mqtt_err("MQTT SUBSCRIBE failed, ack code is 0x80");
+ }
+ }
+
+ /* call callback function to notify that SUBSCRIBE is successful */
+ msg.msg = (void *)(uintptr_t)mypacketid;
+ if (fail_flag == 1) {
+ msg.event_type = IOTX_MQTT_EVENT_SUBCRIBE_NACK;
+ } else {
+ msg.event_type = IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS;
+ }
+
+ _iotx_mqtt_event_handle_sub(c->handle_event.pcontext, c, &msg);
+
+ if (NULL != c->handle_event.h_fp) {
+ _handle_event(&c->handle_event, c, &msg);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#if WITH_MQTT_ZIP_TOPIC
+#define MQTT_ZIP_PATH_DEFAULT_LEN (32)
+
+static int iotx_mc_get_zip_topic(const char *path, int len, char outbuf[], int outlen)
+{
+ unsigned char comp_data[MQTT_ZIP_PATH_DEFAULT_LEN] = {0};
+ if (!path || !len || !outbuf || !outlen) {
+ return -1;
+ }
+
+ utils_sha256((unsigned char *)path, (size_t)len, comp_data);
+
+ memcpy(outbuf, comp_data, outlen > MQTT_ZIP_PATH_DEFAULT_LEN ? MQTT_ZIP_PATH_DEFAULT_LEN : outlen);
+ return 0;
+}
+#endif
+
+static char iotx_mc_is_topic_matched(char *topicFilter, MQTTString *topicName)
+{
+ char *curf;
+ char *curn;
+ char *curn_end;
+
+ if (!topicFilter || !topicName) {
+ return 0;
+ }
+
+ curf = topicFilter;
+ curn = topicName->lenstring.data;
+ curn_end = curn + topicName->lenstring.len;
+
+ while (*curf && curn < curn_end) {
+ if (*curn == '/' && *curf != '/') {
+ break;
+ }
+
+ if (*curf != '+' && *curf != '#' && *curf != *curn) {
+ break;
+ }
+
+ if (*curf == '+') {
+ /* skip until we meet the next separator, or end of string */
+ char *nextpos = curn + 1;
+ while (nextpos < curn_end && *nextpos != '/') {
+ nextpos = ++curn + 1;
+ }
+ } else if (*curf == '#') {
+ curn = curn_end - 1; /* skip until end of string */
+ }
+ curf++;
+ curn++;
+ }
+
+ return (curn == curn_end) && (*curf == '\0');
+}
+
+static void iotx_mc_deliver_message(iotx_mc_client_t *c, MQTTString *topicName, iotx_mqtt_topic_info_pt topic_msg)
+{
+ int flag_matched = 0;
+ MQTTString *compare_topic = NULL;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *node = NULL;
+#else
+ int idx = 0;
+#endif
+
+#if WITH_MQTT_ZIP_TOPIC
+ MQTTString md5_topic;
+ char md5_topic_data[MQTT_ZIP_PATH_DEFAULT_LEN] = {0};
+ char *net_topic;
+ uint32_t net_topic_len;
+#endif
+
+ if (!c || !topicName || !topic_msg) {
+ return;
+ }
+
+ topic_msg->ptopic = topicName->lenstring.data;
+ topic_msg->topic_len = topicName->lenstring.len;
+
+#if WITH_MQTT_ZIP_TOPIC
+ if (topicName->cstring) {
+ net_topic = topicName->cstring;
+ net_topic_len = strlen(topicName->cstring);
+ } else {
+ net_topic = topicName->lenstring.data;
+ net_topic_len = topicName->lenstring.len;
+ }
+ md5_topic.cstring = NULL;
+ md5_topic.lenstring.data = md5_topic_data;
+ md5_topic.lenstring.len = MQTT_ZIP_PATH_DEFAULT_LEN;
+ iotx_mc_get_zip_topic(net_topic, net_topic_len, md5_topic_data, MQTT_ZIP_PATH_DEFAULT_LEN);
+ compare_topic = &md5_topic;
+#else
+ compare_topic = topicName;
+#endif
+
+ /* we have to find the right message handler - indexed by topic */
+ HAL_MutexLock(c->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry(node, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) {
+ if (MQTTPacket_equals(compare_topic, (char *)node->topic_filter)
+ || iotx_mc_is_topic_matched((char *)node->topic_filter, topicName)) {
+ mqtt_debug("topic be matched");
+
+ HAL_MutexUnlock(c->lock_generic);
+ if (NULL != node->handle.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+ msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED;
+ msg.msg = (void *)topic_msg;
+ _handle_event(&node->handle, c, &msg);
+ flag_matched = 1;
+ }
+ HAL_MutexLock(c->lock_generic);
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if ((c->list_sub_handle[idx].used == 1) &&
+ (MQTTPacket_equals(compare_topic, (char *)c->list_sub_handle[idx].topic_filter)
+ || iotx_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, topicName))) {
+ mqtt_debug("topic be matched");
+
+ HAL_MutexUnlock(c->lock_generic);
+ if (NULL != c->list_sub_handle[idx].handle.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+ msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED;
+ msg.msg = (void *)topic_msg;
+ _handle_event(&c->list_sub_handle[idx].handle, c, &msg);
+ flag_matched = 1;
+ }
+ HAL_MutexLock(c->lock_generic);
+ }
+ }
+#endif
+ HAL_MutexUnlock(c->lock_generic);
+
+ if (0 == flag_matched) {
+ mqtt_info("NO matching any topic, call default handle function");
+
+ if (NULL != c->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+
+ msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED;
+ msg.msg = topic_msg;
+ _handle_event(&c->handle_event, c, &msg);
+ }
+ }
+}
+
+static int MQTTPuback(iotx_mc_client_t *c, unsigned int msgId, enum msgTypes type)
+{
+ int rc = 0;
+ int len = 0;
+ iotx_time_t timer;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+ HAL_MutexLock(c->lock_write_buf);
+ if (type == PUBACK) {
+
+ if (_alloc_send_buffer(c, 0) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+ return FAIL_RETURN;
+ }
+
+ len = MQTTSerialize_ack((unsigned char *)c->buf_send, c->buf_size_send, PUBACK, 0, msgId);
+#if WITH_MQTT_QOS2_PACKET
+ } else if (type == PUBREC) {
+ if (_alloc_send_buffer(c, 0) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+ return FAIL_RETURN;
+ }
+ len = MQTTSerialize_ack((unsigned char *)c->buf_send, c->buf_size_send, PUBREC, 0, msgId);
+ } else if (type == PUBREL) {
+ if (_alloc_send_buffer(c, 0) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+ return FAIL_RETURN;
+ }
+ len = MQTTSerialize_ack((unsigned char *)c->buf_send, c->buf_size_send, PUBREL, 0, msgId);
+#endif /* #if WITH_MQTT_QOS2_PACKET */
+ } else {
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_PUBLISH_ACK_TYPE_ERROR;
+ }
+
+ if (len <= 0) {
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_PUBLISH_ACK_PACKET_ERROR;
+ }
+
+ rc = iotx_mc_send_packet(c, c->buf_send, len, &timer);
+ if (rc != SUCCESS_RETURN) {
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_handle_recv_PUBLISH(iotx_mc_client_t *c)
+{
+ int result = 0;
+ MQTTString topicName;
+ iotx_mqtt_topic_info_t topic_msg;
+ int qos = 0;
+ uint32_t payload_len = 0;
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+ const char *json_payload = NULL;
+#endif
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t));
+ memset(&topicName, 0x0, sizeof(MQTTString));
+
+ if (1 != MQTTDeserialize_publish((unsigned char *)&topic_msg.dup,
+ (int *)&qos,
+ (unsigned char *)&topic_msg.retain,
+ (unsigned short *)&topic_msg.packet_id,
+ &topicName,
+ (unsigned char **)&topic_msg.payload,
+ (int *)&payload_len,
+ (unsigned char *)c->buf_read,
+ c->buf_size_read)) {
+ return MQTT_PUBLISH_PACKET_ERROR;
+ }
+ topic_msg.qos = (unsigned char)qos;
+ topic_msg.payload_len = payload_len;
+
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+
+ json_payload = (const char *)topic_msg.payload;
+ mqtt_info("Downstream Topic: '%.*s'", topicName.lenstring.len, topicName.lenstring.data);
+ mqtt_info("Downstream Payload:");
+ iotx_facility_json_print(json_payload, LOG_INFO_LEVEL, '<');
+
+#endif /* #ifdef INFRA_LOG */
+
+ mqtt_debug("%20s : %08d", "Packet Ident", topic_msg.packet_id);
+ mqtt_debug("%20s : %d", "Topic Length", topicName.lenstring.len);
+ mqtt_debug("%20s : %.*s",
+ "Topic Name",
+ topicName.lenstring.len,
+ topicName.lenstring.data);
+ mqtt_debug("%20s : %u / %d", "Payload Len/Room",
+ (unsigned int)topic_msg.payload_len,
+ (int)(c->buf_read + c->buf_size_read - topic_msg.payload));
+ mqtt_debug("%20s : %lu", "Receive Buflen", c->buf_size_read);
+
+#if defined(INSPECT_MQTT_FLOW)
+ mqtt_debug("%20s : %p", "Payload Buffer", topic_msg.payload);
+ mqtt_debug("%20s : %p", "Receive Buffer", c->buf_read);
+#ifdef INFRA_LOG
+ HEXDUMP_DEBUG(topic_msg.payload, topic_msg.payload_len);
+#endif
+#endif
+#ifdef LOG_REPORT_TO_CLOUD
+ get_msgid(topicName.lenstring.data, 1);
+#endif
+
+ topic_msg.ptopic = NULL;
+ topic_msg.topic_len = 0;
+
+ mqtt_debug("delivering msg ...");
+
+#if WITH_MQTT_FLOW_CTRL
+ /* flowControl for specific topic */
+ static uint64_t time_prev = 0;
+ uint64_t time_curr = 0;
+ char *filterStr = "{\"method\":\"thing.service.property.set\"";
+ int filterLen = strlen(filterStr);
+
+ if (0 == memcmp(topic_msg.payload, filterStr, filterLen)) {
+ time_curr = HAL_UptimeMs();
+ if (time_curr < time_prev) {
+ time_curr = time_prev;
+ }
+ if ((time_curr - time_prev) <= (uint64_t)50) {
+ mqtt_info("MQTT over threshould");
+ return SUCCESS_RETURN;
+ } else {
+ time_prev = time_curr;
+ }
+ }
+#endif
+
+ iotx_mc_deliver_message(c, &topicName, &topic_msg);
+
+ if (topic_msg.qos == IOTX_MQTT_QOS0) {
+ return SUCCESS_RETURN;
+ } else if (topic_msg.qos == IOTX_MQTT_QOS1) {
+ result = MQTTPuback(c, topic_msg.packet_id, PUBACK);
+ } else if (topic_msg.qos == IOTX_MQTT_QOS2) {
+ result = MQTTPuback(c, topic_msg.packet_id, PUBREC);
+ } else {
+ mqtt_err("Invalid QOS, QOSvalue = %d", topic_msg.qos);
+ return MQTT_PUBLISH_QOS_ERROR;
+ }
+
+ return result;
+}
+
+static int iotx_mc_handle_recv_UNSUBACK(iotx_mc_client_t *c)
+{
+ unsigned short mypacketid = 0; /* should be the same as the packetid above */
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ if (MQTTDeserialize_unsuback(&mypacketid, (unsigned char *)c->buf_read, c->buf_size_read) != 1) {
+ return MQTT_UNSUBSCRIBE_ACK_PACKET_ERROR;
+ }
+
+ if (NULL != c->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+ msg.event_type = IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS;
+ msg.msg = (void *)(uintptr_t)mypacketid;
+ _handle_event(&c->handle_event, c, &msg);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_cycle(iotx_mc_client_t *c, iotx_time_t *timer)
+{
+ unsigned int packetType;
+ iotx_mc_state_t state;
+ int rc = SUCCESS_RETURN;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ state = iotx_mc_get_client_state(c);
+ if (state != IOTX_MC_STATE_CONNECTED) {
+ mqtt_debug("state = %d", state);
+ return MQTT_STATE_ERROR;
+ }
+
+ if (IOTX_MC_KEEPALIVE_PROBE_MAX < c->keepalive_probes) {
+ iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ c->keepalive_probes = 0;
+ mqtt_debug("keepalive_probes more than %u, disconnected\n", IOTX_MC_KEEPALIVE_PROBE_MAX);
+ }
+
+ /* read the socket, see what work is due */
+ rc = iotx_mc_read_packet(c, timer, &packetType);
+ if (rc != SUCCESS_RETURN) {
+ HAL_MutexLock(c->lock_read_buf);
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+ if (rc == MQTT_NETWORK_ERROR) {
+ iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+ mqtt_err("readPacket error,result = %d", rc);
+ return MQTT_NETWORK_ERROR;
+ }
+
+ if (MQTT_CPT_RESERVED == packetType) {
+ /* mqtt_debug("wait data timeout"); */
+ HAL_MutexLock(c->lock_read_buf);
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return SUCCESS_RETURN;
+ }
+
+ /* clear ping mark when any data received from MQTT broker */
+ HAL_MutexLock(c->lock_generic);
+ c->ping_mark = 0;
+ c->keepalive_probes = 0;
+ HAL_MutexUnlock(c->lock_generic);
+ HAL_MutexLock(c->lock_read_buf);
+ switch (packetType) {
+ case CONNACK: {
+ mqtt_debug("CONNACK");
+ break;
+ }
+#if !WITH_MQTT_ONLY_QOS0
+ case PUBACK: {
+ mqtt_debug("PUBACK");
+ rc = iotx_mc_handle_recv_PUBACK(c);
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("recvPubackProc error,result = %d", rc);
+ }
+
+ break;
+ }
+#endif
+ case SUBACK: {
+ mqtt_debug("SUBACK");
+ rc = iotx_mc_handle_recv_SUBACK(c);
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("recvSubAckProc error,result = %d", rc);
+ }
+ break;
+ }
+ case PUBLISH: {
+ mqtt_debug("PUBLISH");
+ /* HEXDUMP_DEBUG(c->buf_read, 32); */
+
+ rc = iotx_mc_handle_recv_PUBLISH(c);
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("recvPublishProc error,result = %d", rc);
+ }
+ break;
+ }
+ case UNSUBACK: {
+ mqtt_debug("UNSUBACK");
+ rc = iotx_mc_handle_recv_UNSUBACK(c);
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("recvUnsubAckProc error,result = %d", rc);
+ }
+ break;
+ }
+ case PINGRESP: {
+ rc = SUCCESS_RETURN;
+ mqtt_info("receive ping response!");
+ break;
+ }
+ default:
+ mqtt_err("INVALID TYPE");
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return FAIL_RETURN;
+ }
+ _reset_recv_buffer(c);
+ HAL_MutexUnlock(c->lock_read_buf);
+ return rc;
+}
+
+void _mqtt_cycle(void *client)
+{
+ int rc = SUCCESS_RETURN;
+ iotx_time_t time;
+ iotx_mc_client_t *pClient = (iotx_mc_client_t *)client;
+
+ iotx_time_init(&time);
+ utils_time_countdown_ms(&time, pClient->cycle_timeout_ms);
+
+ do {
+ unsigned int left_t;
+
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("error occur rc=%d", rc);
+ }
+
+ HAL_MutexLock(pClient->lock_yield);
+
+ /* acquire package in cycle, such as PINGRESP or PUBLISH */
+ rc = iotx_mc_cycle(pClient, &time);
+ if (SUCCESS_RETURN == rc) {
+#ifndef ASYNC_PROTOCOL_STACK
+#if !WITH_MQTT_ONLY_QOS0
+ /* check list of wait publish ACK to remove node that is ACKED or timeout */
+ MQTTPubInfoProc(pClient);
+#endif
+#endif
+ }
+ HAL_MutexUnlock(pClient->lock_yield);
+
+ left_t = iotx_time_left(&time);
+ if (left_t < 10) {
+ HAL_SleepMs(left_t);
+ } else {
+ HAL_SleepMs(10);
+ }
+ } while (!utils_time_is_expired(&time));
+}
+
+static int MQTTKeepalive(iotx_mc_client_t *pClient)
+{
+ int len = 0;
+ int rc = 0;
+ /* there is no ping outstanding - send ping packet */
+ iotx_time_t timer;
+
+ if (!pClient) {
+ return FAIL_RETURN;
+ }
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, 1000);
+
+ HAL_MutexLock(pClient->lock_write_buf);
+ rc = _alloc_send_buffer(pClient, 0);
+ if (rc < 0) {
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return FAIL_RETURN;
+ }
+
+ len = MQTTSerialize_pingreq((unsigned char *)pClient->buf_send, pClient->buf_size_send);
+ mqtt_debug("len = MQTTSerialize_pingreq() = %d", len);
+
+ if (len <= 0) {
+ mqtt_err("Serialize ping request is error");
+ _reset_send_buffer(pClient);
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return MQTT_PING_PACKET_ERROR;
+ }
+
+ rc = iotx_mc_send_packet(pClient, pClient->buf_send, len, &timer);
+ if (SUCCESS_RETURN != rc) {
+ /* ping outstanding, then close socket unsubscribe topic and handle callback function */
+ mqtt_err("ping outstanding is error,result = %d", rc);
+
+ _reset_send_buffer(pClient);
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+ _reset_send_buffer(pClient);
+ HAL_MutexUnlock(pClient->lock_write_buf);
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_keepalive_sub(iotx_mc_client_t *pClient)
+{
+
+ int rc = SUCCESS_RETURN;
+
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+
+ /* if in disabled state, without having to send ping packets */
+ if (!wrapper_mqtt_check_state(pClient)) {
+ return SUCCESS_RETURN;
+ }
+
+ /* if there is no ping_timer timeout, then return success */
+ if (!utils_time_is_expired(&pClient->next_ping_time)) {
+ return SUCCESS_RETURN;
+ }
+
+ /* update to next time sending MQTT keep-alive */
+ utils_time_countdown_ms(&pClient->next_ping_time, pClient->connect_data.keepAliveInterval * 1000);
+
+ rc = MQTTKeepalive(pClient);
+ if (SUCCESS_RETURN != rc) {
+ if (rc == MQTT_NETWORK_ERROR) {
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED);
+ }
+ mqtt_err("ping outstanding is error,result = %d", rc);
+ return rc;
+ }
+
+ mqtt_info("send MQTT ping...");
+
+ HAL_MutexLock(pClient->lock_generic);
+ pClient->ping_mark = 1;
+ pClient->keepalive_probes++;
+ HAL_MutexUnlock(pClient->lock_generic);
+
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_attempt_reconnect(iotx_mc_client_t *pClient)
+{
+ int rc;
+ if (pClient == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ pClient->ipstack.disconnect(&pClient->ipstack);
+
+ mqtt_info("reconnect params: MQTTVersion=%d, clientID=%s, keepAliveInterval=%d, username=%s",
+ pClient->connect_data.MQTTVersion,
+ pClient->connect_data.clientID.cstring,
+ pClient->connect_data.keepAliveInterval,
+ pClient->connect_data.username.cstring);
+
+ /* Ignoring return code. failures expected if network is disconnected */
+ rc = wrapper_mqtt_connect(pClient);
+
+ if (SUCCESS_RETURN != rc && MQTT_CONNECT_BLOCK != rc) {
+ mqtt_err("run iotx_mqtt_connect() error!");
+ }
+
+ return rc;
+}
+
+static int iotx_mc_handle_reconnect(iotx_mc_client_t *pClient)
+{
+ int rc = FAIL_RETURN;
+ uint32_t interval_ms = 0;
+
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+ mqtt_info("Waiting to reconnect...");
+ if (!utils_time_is_expired(&(pClient->reconnect_param.reconnect_next_time))) {
+ /* Timer has not expired. Not time to attempt reconnect yet. Return attempting reconnect */
+ HAL_SleepMs(100);
+ return FAIL_RETURN;
+ }
+
+ mqtt_info("start to reconnect");
+ /*
+ rc = _conn_info_dynamic_reload(pClient);
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("update connect info err");
+ return -1;
+ }
+ */
+ rc = iotx_mc_attempt_reconnect(pClient);
+ if (SUCCESS_RETURN == rc) {
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECTED);
+ /*
+ _conn_info_dynamic_reload_clear(pClient);
+ */
+ return SUCCESS_RETURN;
+ } else if (MQTT_CONNECT_BLOCK == rc) {
+ return rc;
+ } else {
+ /* if reconnect network failed, then increase currentReconnectWaitInterval */
+ /* e.g. init currentReconnectWaitInterval=1s, reconnect failed, then 2s..4s..8s */
+ if (IOTX_MC_RECONNECT_INTERVAL_MAX_MS > pClient->reconnect_param.reconnect_time_interval_ms) {
+ pClient->reconnect_param.reconnect_time_interval_ms *= 2;
+ } else {
+ pClient->reconnect_param.reconnect_time_interval_ms = IOTX_MC_RECONNECT_INTERVAL_MAX_MS;
+ }
+ }
+ /*
+ _conn_info_dynamic_reload_clear(pClient);
+ */
+ interval_ms = pClient->reconnect_param.reconnect_time_interval_ms;
+ if (IOTX_MC_RECONNECT_INTERVAL_MAX_MS < interval_ms) {
+ interval_ms = IOTX_MC_RECONNECT_INTERVAL_MAX_MS;
+ }
+ utils_time_countdown_ms(&(pClient->reconnect_param.reconnect_next_time), interval_ms);
+
+ mqtt_err("mqtt reconnect failed rc = %d", rc);
+
+ return rc;
+}
+
+static void iotx_mc_reconnect_callback(iotx_mc_client_t *pClient)
+{
+
+ /* handle callback function */
+ if (NULL != pClient->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+ msg.event_type = IOTX_MQTT_EVENT_RECONNECT;
+ msg.msg = NULL;
+
+ pClient->handle_event.h_fp(pClient->handle_event.pcontext,
+ pClient,
+ &msg);
+ }
+}
+
+static void iotx_mc_disconnect_callback(iotx_mc_client_t *pClient)
+{
+
+ if (NULL != pClient->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t msg;
+ msg.event_type = IOTX_MQTT_EVENT_DISCONNECT;
+ msg.msg = NULL;
+
+ pClient->handle_event.h_fp(pClient->handle_event.pcontext,
+ pClient,
+ &msg);
+ }
+}
+
+static void iotx_mc_keepalive(iotx_mc_client_t *pClient)
+{
+ int rc = 0;
+ iotx_mc_state_t currentState;
+
+ if (!pClient) {
+ return;
+ }
+
+ /* Periodic sending ping packet to detect whether the network is connected */
+ iotx_mc_keepalive_sub(pClient);
+
+ currentState = iotx_mc_get_client_state(pClient);
+ do {
+ /* if Exceeds the maximum delay time, then return reconnect timeout */
+ if (IOTX_MC_STATE_DISCONNECTED_RECONNECTING == currentState ||
+ IOTX_MC_STATE_CONNECT_BLOCK == currentState) {
+ /* Reconnection is successful, Resume regularly ping packets */
+ HAL_MutexLock(pClient->lock_generic);
+ pClient->ping_mark = 0;
+ HAL_MutexUnlock(pClient->lock_generic);
+ rc = iotx_mc_handle_reconnect(pClient);
+ if (SUCCESS_RETURN != rc) {
+ mqtt_err("reconnect network fail, rc = %d", rc);
+ } else if (MQTT_CONNECT_BLOCK == rc) {
+ mqtt_debug("now using async protocol stack, wait network connected...");
+ } else {
+ mqtt_info("network is reconnected!");
+ iotx_mc_reconnect_callback(pClient);
+ pClient->reconnect_param.reconnect_time_interval_ms = IOTX_MC_RECONNECT_INTERVAL_MIN_MS;
+ }
+
+ break;
+ }
+
+ /* If network suddenly interrupted, stop pinging packet, try to reconnect network immediately */
+ if (IOTX_MC_STATE_DISCONNECTED == currentState) {
+ mqtt_err("network is disconnected!");
+ iotx_mc_disconnect_callback(pClient);
+
+ pClient->reconnect_param.reconnect_time_interval_ms = IOTX_MC_RECONNECT_INTERVAL_MIN_MS;
+ utils_time_countdown_ms(&(pClient->reconnect_param.reconnect_next_time),
+ pClient->reconnect_param.reconnect_time_interval_ms);
+
+ pClient->ipstack.disconnect(&pClient->ipstack);
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED_RECONNECTING);
+ break;
+ }
+
+ } while (0);
+}
+
+static int iotx_mc_check_handle_is_identical_ex(iotx_mc_topic_handle_t *messageHandlers1,
+ iotx_mc_topic_handle_t *messageHandler2)
+{
+ int topicNameLen = 0;
+
+ if (!messageHandlers1 || !messageHandler2) {
+ return 1;
+ }
+
+ if (!(messageHandlers1->topic_filter) || !(messageHandler2->topic_filter)) {
+ return 1;
+ }
+
+#if !(WITH_MQTT_ZIP_TOPIC)
+ topicNameLen = strlen(messageHandlers1->topic_filter);
+
+ if (topicNameLen != strlen(messageHandler2->topic_filter)) {
+ return 1;
+ }
+
+ if (0 != strncmp(messageHandlers1->topic_filter, messageHandler2->topic_filter, topicNameLen)) {
+ return 1;
+ }
+#else
+
+ if (messageHandlers1->topic_type != messageHandler2->topic_type) {
+ return 1;
+ }
+
+ if (messageHandlers1->topic_type == TOPIC_NAME_TYPE) {
+ int i;
+ for (i = 0; i < MQTT_ZIP_PATH_DEFAULT_LEN; i++) {
+ if (messageHandler2->topic_filter[i] != messageHandlers1->topic_filter[i]) {
+ return 1;
+ }
+ }
+ } else {
+ topicNameLen = strlen(messageHandlers1->topic_filter);
+
+ if (topicNameLen != strlen(messageHandler2->topic_filter)) {
+ return 1;
+ }
+
+ if (0 != strncmp(messageHandlers1->topic_filter, messageHandler2->topic_filter, topicNameLen)) {
+ return 1;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+static int iotx_mc_check_handle_is_identical(iotx_mc_topic_handle_t *messageHandlers1,
+ iotx_mc_topic_handle_t *messageHandler2)
+{
+ if (iotx_mc_check_handle_is_identical_ex(messageHandlers1, messageHandler2) != 0) {
+ return 1;
+ }
+
+ if (messageHandlers1->handle.h_fp != messageHandler2->handle.h_fp) {
+ return 1;
+ }
+
+ /* context must be identical also */
+ if (messageHandlers1->handle.pcontext != messageHandler2->handle.pcontext) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int MQTTSubscribe(iotx_mc_client_t *c, const char *topicFilter, iotx_mqtt_qos_t qos, unsigned int msgId,
+ iotx_mqtt_event_handle_func_fpt messageHandler, void *pcontext)
+{
+ int len = 0;
+ iotx_time_t timer;
+ MQTTString topic = MQTTString_initializer;
+ /*iotx_mc_topic_handle_t handler = {topicFilter, {messageHandler, pcontext}};*/
+ iotx_mc_topic_handle_t *handler = NULL;
+#ifndef PLATFORM_HAS_DYNMEM
+ int idx = 0;
+#endif
+
+ if (!c || !topicFilter || !messageHandler) {
+ return FAIL_RETURN;
+ }
+#if !( WITH_MQTT_DYN_BUF)
+ if (!c->buf_send) {
+ return FAIL_RETURN;
+ }
+#endif
+
+ topic.cstring = (char *)topicFilter;
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+#ifdef PLATFORM_HAS_DYNMEM
+ handler = mqtt_malloc(sizeof(iotx_mc_topic_handle_t));
+ if (NULL == handler) {
+ return FAIL_RETURN;
+ }
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+ INIT_LIST_HEAD(&handler->linked_list);
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if (c->list_sub_handle[idx].used == 0) {
+ handler = &c->list_sub_handle[idx];
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+ c->list_sub_handle[idx].used = 1;
+ break;
+ }
+ }
+
+ if (handler == NULL) {
+ return MQTT_SUBHANDLE_LIST_LEN_TOO_SHORT;
+ }
+#endif
+
+#if !(WITH_MQTT_ZIP_TOPIC)
+#ifdef PLATFORM_HAS_DYNMEM
+ handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1);
+ if (NULL == handler->topic_filter) {
+ mqtt_free(handler);
+ return FAIL_RETURN;
+ }
+ memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1);
+#else
+ if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+
+ memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN);
+#endif
+ memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1);
+#else
+ if (strstr(topicFilter, "/+") != NULL || strstr(topicFilter, "/#") != NULL) {
+#ifdef PLATFORM_HAS_DYNMEM
+ handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1);
+ if (NULL == handler->topic_filter) {
+ mqtt_free(handler);
+ return FAIL_RETURN;
+ }
+ memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1);
+#else
+ if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+ memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN);
+#endif
+ handler->topic_type = TOPIC_FILTER_TYPE;
+ memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1);
+ } else {
+#ifdef PLATFORM_HAS_DYNMEM
+ handler->topic_filter = mqtt_malloc(MQTT_ZIP_PATH_DEFAULT_LEN);
+ if (NULL == handler->topic_filter) {
+ mqtt_free(handler);
+ return FAIL_RETURN;
+ }
+ memset((char *)handler->topic_filter, 0, MQTT_ZIP_PATH_DEFAULT_LEN);
+#else
+ if (MQTT_ZIP_PATH_DEFAULT_LEN >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+ memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN);
+#endif
+ handler->topic_type = TOPIC_NAME_TYPE;
+ if (iotx_mc_get_zip_topic(topicFilter, strlen(topicFilter), (char *)handler->topic_filter,
+ MQTT_ZIP_PATH_DEFAULT_LEN) != 0) {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+#endif
+ return FAIL_RETURN;
+ }
+ }
+#endif
+ handler->handle.h_fp = messageHandler;
+ handler->handle.pcontext = pcontext;
+
+#ifdef SUB_PERSISTENCE_ENABLED
+ if (qos == IOTX_MQTT_QOS3_SUB_LOCAL) {
+ uint8_t dup = 0;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *node;
+#endif
+ HAL_MutexLock(c->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG)
+#if WITH_MQTT_ZIP_TOPIC
+ HEXDUMP_DEBUG(handler->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN);
+#else
+ mqtt_warning("handler->topic: %s", handler->topic_filter);
+#endif
+#endif
+ list_for_each_entry(node, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) {
+ /* If subscribe the same topic and callback function, then ignore */
+#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG)
+#if WITH_MQTT_ZIP_TOPIC
+ HEXDUMP_DEBUG(node->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN);
+#else
+ mqtt_warning("node->topic: %s", node->topic_filter);
+#endif
+#endif
+ if (0 == iotx_mc_check_handle_is_identical(node, handler)) {
+ mqtt_warning("dup sub,topic = %s", topicFilter);
+ dup = 1;
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ /* If subscribe the same topic and callback function, then ignore */
+ if (&c->list_sub_handle[idx] != handler &&
+ 0 == iotx_mc_check_handle_is_identical(&c->list_sub_handle[idx], handler)) {
+ mqtt_warning("dup sub,topic = %s", topicFilter);
+ dup = 1;
+ }
+ }
+#endif
+ if (dup == 0) {
+#ifdef PLATFORM_HAS_DYNMEM
+ list_add_tail(&handler->linked_list, &c->list_sub_handle);
+#endif
+ } else {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+#endif
+ }
+ HAL_MutexUnlock(c->lock_generic);
+ return SUCCESS_RETURN;
+ }
+#endif
+
+ HAL_MutexLock(c->lock_write_buf);
+
+ if (_alloc_send_buffer(c, strlen(topicFilter)) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+#endif
+ return FAIL_RETURN;
+ }
+
+ len = MQTTSerialize_subscribe((unsigned char *)c->buf_send, c->buf_size_send, 0, (unsigned short)msgId, 1, &topic,
+ (int *)&qos);
+ if (len <= 0) {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+#endif
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_SUBSCRIBE_PACKET_ERROR;
+ }
+
+ mqtt_debug("%20s : %08d", "Packet Ident", msgId);
+ mqtt_debug("%20s : %s", "Topic", topicFilter);
+ mqtt_debug("%20s : %d", "QoS", (int)qos);
+ mqtt_debug("%20s : %d", "Packet Length", len);
+#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG)
+ HEXDUMP_DEBUG(c->buf_send, len);
+#endif
+
+ if ((iotx_mc_send_packet(c, c->buf_send, len, &timer)) != SUCCESS_RETURN) { /* send the subscribe packet */
+ /* If send failed, remove it */
+ mqtt_err("run sendPacket error!");
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+#endif
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+
+ {
+ uint8_t dup = 0;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *node;
+#endif
+ HAL_MutexLock(c->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG)
+#if WITH_MQTT_ZIP_TOPIC
+ HEXDUMP_DEBUG(handler->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN);
+#else
+ mqtt_warning("handler->topic: %s", handler->topic_filter);
+#endif
+#endif
+ list_for_each_entry(node, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) {
+ /* If subscribe the same topic and callback function, then ignore */
+#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG)
+#if WITH_MQTT_ZIP_TOPIC
+ HEXDUMP_DEBUG(node->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN);
+#else
+ mqtt_warning("node->topic: %s", node->topic_filter);
+#endif
+#endif
+ if (0 == iotx_mc_check_handle_is_identical(node, handler)) {
+ mqtt_warning("dup sub,topic = %s", topicFilter);
+ dup = 1;
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ /* If subscribe the same topic and callback function, then ignore */
+ if (&c->list_sub_handle[idx] != handler &&
+ 0 == iotx_mc_check_handle_is_identical(&c->list_sub_handle[idx], handler)) {
+ mqtt_warning("dup sub,topic = %s", topicFilter);
+ dup = 1;
+ }
+ }
+#endif
+ if (dup == 0) {
+#ifdef PLATFORM_HAS_DYNMEM
+ list_add_tail(&handler->linked_list, &c->list_sub_handle);
+#endif
+ } else {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+#endif
+ }
+ HAL_MutexUnlock(c->lock_generic);
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_get_next_packetid(iotx_mc_client_t *c)
+{
+ unsigned int id = 0;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ HAL_MutexLock(c->lock_generic);
+ c->packet_id = (c->packet_id == IOTX_MC_PACKET_ID_MAX) ? 1 : c->packet_id + 1;
+ id = c->packet_id;
+ HAL_MutexUnlock(c->lock_generic);
+
+ return id;
+}
+
+static int iotx_mc_check_rule(char *iterm, iotx_mc_topic_type_t type)
+{
+ int i = 0;
+ int len = 0;
+
+ if (NULL == iterm) {
+ mqtt_err("iterm is NULL");
+ return FAIL_RETURN;
+ }
+
+ len = strlen(iterm);
+
+ for (i = 0; i < len; i++) {
+ if (TOPIC_FILTER_TYPE == type) {
+ if ('+' == iterm[i] || '#' == iterm[i]) {
+ if (1 != len) {
+ mqtt_err("the character # and + is error");
+ return FAIL_RETURN;
+ }
+ }
+ } else {
+ if ('+' == iterm[i] || '#' == iterm[i]) {
+ mqtt_err("has character # and + is error");
+ return FAIL_RETURN;
+ }
+ }
+
+ if (iterm[i] < 32 || iterm[i] >= 127) {
+ return FAIL_RETURN;
+ }
+ }
+ return SUCCESS_RETURN;
+}
+
+static int iotx_mc_check_topic(const char *topicName, iotx_mc_topic_type_t type)
+{
+ int mask = 0;
+ char *delim = "/";
+ char *iterm = NULL;
+ char topicString[CONFIG_MQTT_TOPIC_MAXLEN];
+ if (NULL == topicName || '/' != topicName[0]) {
+ return FAIL_RETURN;
+ }
+
+ if (strlen(topicName) > CONFIG_MQTT_TOPIC_MAXLEN) {
+ mqtt_err("len of topicName exceeds %d", CONFIG_MQTT_TOPIC_MAXLEN);
+ return FAIL_RETURN;
+ }
+
+ memset(topicString, 0x0, CONFIG_MQTT_TOPIC_MAXLEN);
+ strncpy(topicString, topicName, CONFIG_MQTT_TOPIC_MAXLEN - 1);
+
+ iterm = infra_strtok(topicString, delim);
+
+ if (SUCCESS_RETURN != iotx_mc_check_rule(iterm, type)) {
+ mqtt_err("run iotx_check_rule error");
+ return FAIL_RETURN;
+ }
+
+ for (;;) {
+ iterm = infra_strtok(NULL, delim);
+
+ if (iterm == NULL) {
+ break;
+ }
+
+ /* The character '#' is not in the last */
+ if (1 == mask) {
+ mqtt_err("the character # is error");
+ return FAIL_RETURN;
+ }
+
+ if (SUCCESS_RETURN != iotx_mc_check_rule(iterm, type)) {
+ mqtt_err("run iotx_check_rule error");
+ return FAIL_RETURN;
+ }
+
+ if (iterm[0] == '#') {
+ mask = 1;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static inline int _is_in_yield_cb()
+{
+ return _in_yield_cb;
+}
+
+static int MQTTUnsubscribe(iotx_mc_client_t *c, const char *topicFilter, unsigned int msgId)
+{
+ MQTTString cur_topic;
+ iotx_time_t timer;
+ MQTTString topic = MQTTString_initializer;
+ int len = 0;
+ /*iotx_mc_topic_handle_t handler = {topicFilter, {NULL, NULL}};*/
+ iotx_mc_topic_handle_t *handler = NULL;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *node = NULL;
+ iotx_mc_topic_handle_t *next = NULL;
+#else
+ int idx = 0;
+ iotx_mc_topic_handle_t s_handler;
+#endif
+ if (!c || !topicFilter) {
+ return FAIL_RETURN;
+ }
+
+ topic.cstring = (char *)topicFilter;
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+#ifdef PLATFORM_HAS_DYNMEM
+ handler = mqtt_malloc(sizeof(iotx_mc_topic_handle_t));
+ if (NULL == handler) {
+ return FAIL_RETURN;
+ }
+#else
+ handler = &s_handler;
+#endif
+
+ memset(handler, 0, sizeof(iotx_mc_topic_handle_t));
+
+#if !(WITH_MQTT_ZIP_TOPIC)
+#ifdef PLATFORM_HAS_DYNMEM
+ handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1);
+ if (NULL == handler->topic_filter) {
+ mqtt_free(handler);
+ return FAIL_RETURN;
+ }
+ memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1);
+#else
+ if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+ memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN);
+#endif
+ memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1);
+#else
+ if (strstr(topicFilter, "/+") != NULL || strstr(topicFilter, "/#") != NULL) {
+#ifdef PLATFORM_HAS_DYNMEM
+ handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1);
+ if (NULL == handler->topic_filter) {
+ mqtt_free(handler);
+ return FAIL_RETURN;
+ }
+ memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1);
+#else
+ if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+ memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN);
+#endif
+ handler->topic_type = TOPIC_FILTER_TYPE;
+ memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1);
+ } else {
+#ifdef PLATFORM_HAS_DYNMEM
+ handler->topic_filter = mqtt_malloc(MQTT_ZIP_PATH_DEFAULT_LEN);
+ if (NULL == handler->topic_filter) {
+ mqtt_free(handler);
+ return FAIL_RETURN;
+ }
+ memset((char *)handler->topic_filter, 0, MQTT_ZIP_PATH_DEFAULT_LEN);
+#else
+ if (MQTT_ZIP_PATH_DEFAULT_LEN >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+ memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN);
+#endif
+ handler->topic_type = TOPIC_NAME_TYPE;
+ if (iotx_mc_get_zip_topic(topicFilter, strlen(topicFilter), (char *)handler->topic_filter,
+ MQTT_ZIP_PATH_DEFAULT_LEN) != 0) {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#endif
+ return FAIL_RETURN;
+ }
+ }
+#endif
+
+ HAL_MutexLock(c->lock_write_buf);
+
+ if (_alloc_send_buffer(c, strlen(topicFilter)) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#endif
+ return FAIL_RETURN;
+ }
+
+ if ((len = MQTTSerialize_unsubscribe((unsigned char *)c->buf_send, c->buf_size_send, 0, (unsigned short)msgId, 1,
+ &topic)) <= 0) {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#endif
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_UNSUBSCRIBE_PACKET_ERROR;
+ }
+
+ if ((iotx_mc_send_packet(c, c->buf_send, len, &timer)) != SUCCESS_RETURN) { /* send the subscribe packet */
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#endif
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return MQTT_NETWORK_ERROR;
+ }
+
+ cur_topic.cstring = NULL;
+ cur_topic.lenstring.data = (char *)handler->topic_filter;
+
+#if !(WITH_MQTT_ZIP_TOPIC)
+ cur_topic.lenstring.len = strlen(handler->topic_filter) + 1;
+#else
+ if (handler->topic_type == TOPIC_FILTER_TYPE) {
+ cur_topic.lenstring.len = strlen(handler->topic_filter) + 1;
+ } else {
+ cur_topic.lenstring.len = MQTT_ZIP_PATH_DEFAULT_LEN;
+ }
+#endif
+ /* we have to find the right message handler - indexed by topic */
+ HAL_MutexLock(c->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) {
+ if (MQTTPacket_equals(&cur_topic, (char *)node->topic_filter)
+ || iotx_mc_is_topic_matched((char *)node->topic_filter, &cur_topic)) {
+ mqtt_debug("topic be matched");
+ list_del(&node->linked_list);
+ mqtt_free(node->topic_filter);
+ mqtt_free(node);
+ }
+ }
+ mqtt_free(handler->topic_filter);
+ mqtt_free(handler);
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if ((c->list_sub_handle[idx].used == 1) &&
+ (MQTTPacket_equals(&cur_topic, (char *)c->list_sub_handle[idx].topic_filter) ||
+ iotx_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, &cur_topic))) {
+ mqtt_debug("topic be matched");
+ memset(&c->list_sub_handle[idx], 0, sizeof(iotx_mc_topic_handle_t));
+ }
+ }
+#endif
+ HAL_MutexUnlock(c->lock_generic);
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return SUCCESS_RETURN;
+}
+
+int MQTTPublish(iotx_mc_client_t *c, const char *topicName, iotx_mqtt_topic_info_pt topic_msg)
+
+{
+ iotx_time_t timer;
+ MQTTString topic = MQTTString_initializer;
+ int len = 0;
+#if !WITH_MQTT_ONLY_QOS0
+ iotx_mc_pub_info_t *node = NULL;
+#endif
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+ const char *json_payload = NULL;
+#endif
+
+ if (!c || !topicName || !topic_msg) {
+ return FAIL_RETURN;
+ }
+
+ topic.cstring = (char *)topicName;
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+ HAL_MutexLock(c->lock_list_pub);
+ HAL_MutexLock(c->lock_write_buf);
+
+ if (_alloc_send_buffer(c, strlen(topicName) + topic_msg->payload_len) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+ HAL_MutexUnlock(c->lock_list_pub);
+ return FAIL_RETURN;
+ }
+
+ len = MQTTSerialize_publish((unsigned char *)c->buf_send,
+ c->buf_size_send,
+ 0,
+ topic_msg->qos,
+ topic_msg->retain,
+ topic_msg->packet_id,
+ topic,
+ (unsigned char *)topic_msg->payload,
+ topic_msg->payload_len);
+ if (len <= 0) {
+ mqtt_err("MQTTSerialize_publish is error, len=%d, buf_size_send=%u, payloadlen=%u",
+ len,
+ c->buf_size_send,
+ topic_msg->payload_len);
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ HAL_MutexUnlock(c->lock_list_pub);
+ return MQTT_PUBLISH_PACKET_ERROR;
+ }
+
+#if !WITH_MQTT_ONLY_QOS0
+ node = NULL;
+ /* If the QOS >1, push the information into list of wait publish ACK */
+ if (topic_msg->qos > IOTX_MQTT_QOS0) {
+ /* push into list */
+ if (SUCCESS_RETURN != iotx_mc_push_pubInfo_to(c, len, topic_msg->packet_id, &node)) {
+ mqtt_err("push publish into to pubInfolist failed!");
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ HAL_MutexUnlock(c->lock_list_pub);
+ return MQTT_PUSH_TO_LIST_ERROR;
+ }
+ }
+#endif
+ /* send the publish packet */
+ if (iotx_mc_send_packet(c, c->buf_send, len, &timer) != SUCCESS_RETURN) {
+#if !WITH_MQTT_ONLY_QOS0
+ if (topic_msg->qos > IOTX_MQTT_QOS0) {
+ /* If not even successfully sent to IP stack, meaningless to wait QOS1 ack, give up waiting */
+#ifdef PLATFORM_HAS_DYNMEM
+ list_del(&node->linked_list);
+ mqtt_free(node);
+#else
+ memset(node, 0, sizeof(iotx_mc_pub_info_t));
+#endif
+ }
+#endif
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ HAL_MutexUnlock(c->lock_list_pub);
+ return MQTT_NETWORK_ERROR;
+ }
+
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+ json_payload = (const char *)topic_msg->payload;
+
+ mqtt_info("Upstream Topic: '%s'", topicName);
+ mqtt_info("Upstream Payload:");
+ iotx_facility_json_print(json_payload, LOG_INFO_LEVEL, '>');
+
+#endif /* #ifdef INFRA_LOG */
+
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ HAL_MutexUnlock(c->lock_list_pub);
+
+ return SUCCESS_RETURN;
+}
+
+static int MQTTDisconnect(iotx_mc_client_t *c)
+{
+ int rc = FAIL_RETURN;
+ int len = 0;
+ iotx_time_t timer; /* we might wait for incomplete incoming publishes to complete */
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ HAL_MutexLock(c->lock_write_buf);
+
+ if (_alloc_send_buffer(c, 0) < 0) {
+ HAL_MutexUnlock(c->lock_write_buf);
+ return FAIL_RETURN;
+ }
+
+ len = MQTTSerialize_disconnect((unsigned char *)c->buf_send, c->buf_size_send);
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, c->request_timeout_ms);
+
+ if (len > 0) {
+ rc = iotx_mc_send_packet(c, c->buf_send, len, &timer); /* send the disconnect packet */
+ }
+ _reset_send_buffer(c);
+ HAL_MutexUnlock(c->lock_write_buf);
+ return rc;
+}
+
+static int iotx_mc_disconnect(iotx_mc_client_t *pClient)
+{
+ int rc = -1;
+
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (wrapper_mqtt_check_state(pClient)) {
+ rc = MQTTDisconnect(pClient);
+ mqtt_debug("rc = MQTTDisconnect() = %d", rc);
+ rc = rc;
+ }
+
+ /* close tcp/ip socket or free tls resources */
+ pClient->ipstack.disconnect(&pClient->ipstack);
+
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_INITIALIZED);
+
+ mqtt_info("mqtt disconnect!");
+ return SUCCESS_RETURN;
+}
+
+/************************ Public Interface ************************/
+void *wrapper_mqtt_init(iotx_mqtt_param_t *mqtt_params)
+{
+ int err;
+ iotx_mc_client_t *pclient = NULL;
+#ifndef PLATFORM_HAS_DYNMEM
+ int idx;
+#endif
+
+#ifdef PLATFORM_HAS_DYNMEM
+ pclient = (iotx_mc_client_t *)mqtt_malloc(sizeof(iotx_mc_client_t));
+ if (NULL == pclient) {
+ mqtt_err("not enough memory.");
+ return NULL;
+ }
+ memset(pclient, 0, sizeof(iotx_mc_client_t));
+#else
+ for (idx = 0; idx < IOTX_MC_CLIENT_MAX_COUNT; idx++) {
+ if (g_iotx_mc_client[idx].used == 0) {
+ g_iotx_mc_client[idx].used = 1;
+ pclient = &g_iotx_mc_client[idx];
+ break;
+ }
+ }
+
+ if (NULL == pclient) {
+ mqtt_err("IOTX_MC_CLIENT_MAX_COUNT too short: %d", IOTX_MC_CLIENT_MAX_COUNT);
+ return NULL;
+ }
+#endif
+
+ err = iotx_mc_init(pclient, mqtt_params);
+
+ if (SUCCESS_RETURN != err) {
+ mqtt_err("iotx_mc_init failed");
+ iotx_mc_release(pclient);
+ return NULL;
+ }
+
+ return pclient;
+}
+
+int wrapper_mqtt_connect(void *client)
+{
+ int rc = FAIL_RETURN;
+ int retry_max = 3;
+ int retry_cnt = 1;
+ int retry_interval = 1000;
+ iotx_mc_client_t *pClient = (iotx_mc_client_t *)client;
+
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+
+ /* Establish TCP or TLS connection */
+ do {
+ mqtt_debug("calling TCP or TLS connect HAL for [%d/%d] iteration", retry_cnt, retry_max);
+
+ rc = pClient->ipstack.connect(&pClient->ipstack);
+ if (SUCCESS_RETURN != rc) {
+ pClient->ipstack.disconnect(&pClient->ipstack);
+ mqtt_err("TCP or TLS Connection failed");
+
+ if (ERROR_CERTIFICATE_EXPIRED == rc) {
+ mqtt_err("certificate is expired! rc = %d", rc);
+ rc = ERROR_CERT_VERIFY_FAIL;
+ HAL_SleepMs(retry_interval);
+ continue;
+ } else {
+ rc = MQTT_NETWORK_CONNECT_ERROR;
+ HAL_SleepMs(retry_interval);
+ continue;
+ }
+ } else {
+ mqtt_debug("rc = pClient->ipstack.connect() = %d, success @ [%d/%d] iteration", rc, retry_cnt, retry_max);
+ break;
+ }
+ } while (++retry_cnt <= retry_max);
+
+#ifdef ASYNC_PROTOCOL_STACK
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECT_BLOCK);
+ rc = MQTT_CONNECT_BLOCK;
+#else
+ rc = _mqtt_connect(pClient);
+#endif
+ return rc;
+}
+
+int wrapper_mqtt_release(void **c)
+{
+ iotx_mc_client_t *pClient;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *node = NULL, *next = NULL;
+#endif
+ if (NULL == c) {
+ return NULL_VALUE_ERROR;
+ }
+
+ pClient = (iotx_mc_client_t *)*c;
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+ /* iotx_delete_thread(pClient); */
+ HAL_SleepMs(100);
+
+ iotx_mc_disconnect(pClient);
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_INVALID);
+ HAL_SleepMs(100);
+
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next, &pClient->list_sub_handle, linked_list, iotx_mc_topic_handle_t) {
+ list_del(&node->linked_list);
+ mqtt_free(node->topic_filter);
+ mqtt_free(node);
+ }
+#else
+ memset(pClient->list_sub_handle, 0, sizeof(iotx_mc_topic_handle_t) * IOTX_MC_SUBHANDLE_LIST_MAX_LEN);
+#endif
+ HAL_MutexDestroy(pClient->lock_generic);
+ HAL_MutexDestroy(pClient->lock_list_pub);
+ HAL_MutexDestroy(pClient->lock_write_buf);
+ HAL_MutexDestroy(pClient->lock_yield);
+ HAL_MutexDestroy(pClient->lock_read_buf);
+
+#if !WITH_MQTT_ONLY_QOS0
+ iotx_mc_pub_wait_list_deinit(pClient);
+#endif
+#ifdef PLATFORM_HAS_DYNMEM
+ if (pClient->buf_send != NULL) {
+ mqtt_free(pClient->buf_send);
+ pClient->buf_send = NULL;
+ }
+ if (pClient->buf_read != NULL) {
+ mqtt_free(pClient->buf_read);
+ pClient->buf_read = NULL;
+ }
+ mqtt_free(pClient);
+#else
+ memset(pClient, 0, sizeof(iotx_mc_client_t));
+#endif
+ *c = NULL;
+ mqtt_info("mqtt release!");
+ return SUCCESS_RETURN;
+}
+
+int wrapper_mqtt_yield(void *client, int timeout_ms)
+{
+ iotx_mc_client_t *pClient = (iotx_mc_client_t *)client;
+
+ if (pClient == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (timeout_ms < 0) {
+ mqtt_err("Invalid argument, timeout_ms = %d", timeout_ms);
+ return -1;
+ }
+ if (timeout_ms == 0) {
+ timeout_ms = 10;
+ }
+
+ HAL_MutexLock(pClient->lock_yield);
+ pClient->cycle_timeout_ms = timeout_ms;
+ /* Keep MQTT alive or reconnect if connection abort */
+ iotx_mc_keepalive(pClient);
+ HAL_MutexUnlock(pClient->lock_yield);
+
+#ifndef ASYNC_PROTOCOL_STACK
+ _mqtt_cycle(client);
+#else
+ if (pClient->client_state == IOTX_MC_STATE_CONNECTED) {
+#if !WITH_MQTT_ONLY_QOS0
+ /* check list of wait publish ACK to remove node that is ACKED or timeout */
+ MQTTPubInfoProc(pClient);
+#endif
+ }
+ HAL_SleepMs(timeout_ms);
+#endif
+
+ return 0;
+}
+
+
+/* check MQTT client is in normal state */
+/* 0, in abnormal state; 1, in normal state */
+int wrapper_mqtt_check_state(void *client)
+{
+ if (!client) {
+ return 0;
+ }
+
+ if (iotx_mc_get_client_state((iotx_mc_client_t *)client) == IOTX_MC_STATE_CONNECTED) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int wrapper_mqtt_subscribe(void *client,
+ const char *topicFilter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext)
+{
+ int rc = FAIL_RETURN;
+ unsigned int msgId;
+ iotx_mc_client_t *c;
+
+ if (NULL == client || NULL == topicFilter || strlen(topicFilter) == 0 || !topic_handle_func) {
+ mqtt_err(" paras error");
+ return NULL_VALUE_ERROR;
+ }
+
+ c = (iotx_mc_client_t *)client;
+
+ msgId = iotx_mc_get_next_packetid(c);
+
+ if (!wrapper_mqtt_check_state(c)) {
+ mqtt_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c));
+ return MQTT_STATE_ERROR;
+ }
+
+ if (0 != iotx_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) {
+ mqtt_err("topic format is error,topicFilter = %s", topicFilter);
+ return MQTT_TOPIC_FORMAT_ERROR;
+ }
+
+ mqtt_debug("PERFORM subscribe to '%s' (msgId=%d)", topicFilter, msgId);
+ rc = MQTTSubscribe(c, topicFilter, qos, msgId, topic_handle_func, pcontext);
+ if (rc != SUCCESS_RETURN) {
+ if (rc == MQTT_NETWORK_ERROR) {
+ iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+
+ mqtt_err("run MQTTSubscribe error, rc = %d", rc);
+ return rc;
+ }
+
+ mqtt_info("mqtt subscribe packet sent,topic = %s!", topicFilter);
+ return msgId;
+}
+
+int wrapper_mqtt_subscribe_sync(void *c,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext,
+ int timeout_ms)
+{
+ int subed;
+ int ret;
+ iotx_time_t timer;
+ iotx_mc_client_t *client = (iotx_mc_client_t *)c;
+ int cnt = 0;
+ mqtt_sub_sync_node_t *node = NULL;
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_sub_sync_node_t *next = NULL;
+#else
+ int idx = 0;
+#endif
+ if (client == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+#ifdef SUB_PERSISTENCE_ENABLED
+ if (qos > IOTX_MQTT_QOS3_SUB_LOCAL) {
+ mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d",
+ qos,
+ IOTX_MQTT_QOS0, IOTX_MQTT_QOS3_SUB_LOCAL, IOTX_MQTT_QOS0);
+ qos = IOTX_MQTT_QOS0;
+ }
+#else
+ if (qos > IOTX_MQTT_QOS2) {
+ mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d",
+ qos,
+ IOTX_MQTT_QOS0, IOTX_MQTT_QOS2, IOTX_MQTT_QOS0);
+ qos = IOTX_MQTT_QOS0;
+ }
+#endif
+
+ iotx_time_init(&timer);
+ utils_time_countdown_ms(&timer, timeout_ms);
+
+ ret = -1;
+ subed = 0;
+ cnt = 0;
+ cnt = cnt;
+ do {
+#ifdef PLATFORM_HAS_DYNMEM
+ mqtt_sub_sync_node_t *node = NULL;
+ mqtt_sub_sync_node_t *next = NULL;
+#else
+ int idx = 0;
+#endif
+ if (ret < 0) {
+ ret = wrapper_mqtt_subscribe(client, topic_filter, qos, topic_handle_func, pcontext);
+ if (_is_in_yield_cb() != 0 || qos == IOTX_MQTT_QOS3_SUB_LOCAL) {
+ return ret;
+ }
+ }
+
+ if (!subed && ret >= 0) {
+ mqtt_sub_sync_node_t *node = NULL;
+#ifndef PLATFORM_HAS_DYNMEM
+ int idx = 0;
+#endif
+#ifdef PLATFORM_HAS_DYNMEM
+ node = (mqtt_sub_sync_node_t *)mqtt_malloc(sizeof(mqtt_sub_sync_node_t));
+#else
+ for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) {
+ if (client->list_sub_sync_ack[idx].used == 0) {
+ memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t));
+ client->list_sub_sync_ack[idx].used = 1;
+ node = &client->list_sub_sync_ack[idx];
+ break;
+ }
+ }
+#endif
+ if (node != NULL) {
+ mqtt_debug("packet_id = %d", ret);
+ node->packet_id = ret;
+ node->ack_type = IOTX_MQTT_EVENT_UNDEF;
+#ifdef PLATFORM_HAS_DYNMEM
+ HAL_MutexLock(client->lock_generic);
+ list_add_tail(&node->linked_list, &client->list_sub_sync_ack);
+ HAL_MutexUnlock(client->lock_generic);
+#endif
+ subed = 1;
+ }
+
+ }
+ wrapper_mqtt_yield(client, 100);
+
+ HAL_MutexLock(client->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next, &client->list_sub_sync_ack, linked_list, mqtt_sub_sync_node_t) {
+ if (node->packet_id == ret) {
+ mqtt_debug("node->ack_type=%d cnt=%d", node->ack_type, cnt++);
+ if (node->ack_type == IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS) {
+ list_del(&node->linked_list);
+ mqtt_free(node);
+ mqtt_debug("success!!");
+ HAL_MutexUnlock(client->lock_generic);
+ return ret;
+ } else if (node->ack_type == IOTX_MQTT_EVENT_SUBCRIBE_NACK) {
+ list_del(&node->linked_list);
+ mqtt_free(node);
+ ret = -1; /* resub */
+ subed = 0;
+ } else if (node->ack_type == IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT) {
+ list_del(&node->linked_list);
+ mqtt_free(node);
+ ret = -1; /* resub */
+ subed = 0;
+ }
+ }
+ break;
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) {
+ if (client->list_sub_sync_ack[idx].used == 0) {
+ continue;
+ }
+
+ if (client->list_sub_sync_ack[idx].packet_id == ret) {
+ mqtt_debug("client->list_sub_sync_ack[%d].ack_type=%d cnt=%d", idx, client->list_sub_sync_ack[idx].ack_type, cnt++);
+ if (client->list_sub_sync_ack[idx].ack_type == IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS) {
+ memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t));
+ mqtt_debug("success!!");
+ HAL_MutexUnlock(client->lock_generic);
+ return ret;
+ } else if (client->list_sub_sync_ack[idx].ack_type == IOTX_MQTT_EVENT_SUBCRIBE_NACK) {
+ memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t));
+ ret = -1; /* resub */
+ subed = 0;
+ } else if (client->list_sub_sync_ack[idx].ack_type == IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT) {
+ memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t));
+ ret = -1; /* resub */
+ subed = 0;
+ }
+ }
+ break;
+ }
+#endif
+ HAL_MutexUnlock(client->lock_generic);
+ } while (!utils_time_is_expired(&timer));
+ mqtt_warning("sync subscribe time out!!");
+
+ HAL_MutexLock(client->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next, &client->list_sub_sync_ack, linked_list, mqtt_sub_sync_node_t) {
+ if (node->packet_id == ret) {
+ list_del(&node->linked_list);
+ mqtt_free(node);
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) {
+ if (client->list_sub_sync_ack[idx].used && node->packet_id == ret) {
+ memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t));
+ }
+ }
+#endif
+ HAL_MutexUnlock(client->lock_generic);
+
+ return -1;
+}
+
+int wrapper_mqtt_unsubscribe(void *client, const char *topicFilter)
+{
+ int rc = FAIL_RETURN;
+ iotx_mc_client_t *c = (iotx_mc_client_t *)client;
+ unsigned int msgId;
+
+ if (NULL == c || NULL == topicFilter) {
+ return NULL_VALUE_ERROR;
+ }
+ msgId = iotx_mc_get_next_packetid(c);
+
+ if (0 != iotx_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) {
+ mqtt_err("topic format is error,topicFilter = %s", topicFilter);
+ return MQTT_TOPIC_FORMAT_ERROR;
+ }
+
+ if (!wrapper_mqtt_check_state(c)) {
+ mqtt_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c));
+ return MQTT_STATE_ERROR;
+ }
+
+ rc = MQTTUnsubscribe(c, topicFilter, msgId);
+ if (rc != SUCCESS_RETURN) {
+ if (rc == MQTT_NETWORK_ERROR) { /* send the subscribe packet */
+ iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+
+ mqtt_err("run MQTTUnsubscribe error!, rc = %d", rc);
+ return rc;
+ }
+
+ mqtt_info("mqtt unsubscribe packet sent,topic = %s!", topicFilter);
+ return (int)msgId;
+}
+
+int wrapper_mqtt_publish(void *client, const char *topicName, iotx_mqtt_topic_info_pt topic_msg)
+{
+ uint16_t msg_id = 0;
+ int rc = FAIL_RETURN;
+ iotx_mc_client_t *c = (iotx_mc_client_t *)client;
+ if (c == NULL || topicName == NULL || topic_msg == NULL || topic_msg->payload == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (0 != iotx_mc_check_topic(topicName, TOPIC_NAME_TYPE)) {
+ mqtt_err("topic format is error,topicFilter = %s", topicName);
+ return MQTT_TOPIC_FORMAT_ERROR;
+ }
+
+ if (!wrapper_mqtt_check_state(c)) {
+ mqtt_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c));
+ return MQTT_STATE_ERROR;
+ }
+
+#if !WITH_MQTT_ONLY_QOS0
+ if (topic_msg->qos == IOTX_MQTT_QOS1 || topic_msg->qos == IOTX_MQTT_QOS2) {
+ msg_id = iotx_mc_get_next_packetid(c);
+ topic_msg->packet_id = msg_id;
+ }
+ if (topic_msg->qos == IOTX_MQTT_QOS2) {
+ mqtt_err("MQTTPublish return error,MQTT_QOS2 is now not supported.");
+ return MQTT_PUBLISH_QOS_ERROR;
+ }
+#else
+ topic_msg->qos = IOTX_MQTT_QOS0;
+#endif
+
+#if defined(INSPECT_MQTT_FLOW) && defined(INFRA_LOG)
+ HEXDUMP_DEBUG(topicName, strlen(topicName));
+ HEXDUMP_DEBUG(topic_msg->payload, topic_msg->payload_len);
+#endif
+
+ rc = MQTTPublish(c, topicName, topic_msg);
+ if (rc != SUCCESS_RETURN) { /* send the subscribe packet */
+ if (rc == MQTT_NETWORK_ERROR) {
+ iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+ mqtt_err("MQTTPublish is error, rc = %d", rc);
+ return rc;
+ }
+
+ return (int)msg_id;
+}
+
+#ifdef ASYNC_PROTOCOL_STACK
+int wrapper_mqtt_nwk_event_handler(void *client, iotx_mqtt_nwk_event_t event, iotx_mqtt_nwk_param_t *param)
+{
+ int rc = FAIL_RETURN;
+ iotx_mc_client_t *pClient = (iotx_mc_client_t *)client;
+ if (client == NULL || event >= IOTX_MQTT_SOC_MAX) {
+ return NULL_VALUE_ERROR;
+ }
+
+ switch (event) {
+ case IOTX_MQTT_SOC_CONNECTED: {
+ rc = _mqtt_connect(pClient);
+ if (rc == SUCCESS_RETURN) {
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECTED);
+ }
+ }
+ break;
+ case IOTX_MQTT_SOC_CLOSE: {
+ iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED);
+ }
+ break;
+ case IOTX_MQTT_SOC_READ: {
+ HAL_MutexLock(pClient->lock_yield);
+ _mqtt_cycle(pClient);
+ HAL_MutexUnlock(pClient->lock_yield);
+ rc = SUCCESS_RETURN;
+ }
+ break;
+ case IOTX_MQTT_SOC_WRITE: {
+
+ }
+ break;
+ default: {
+ mqtt_err("unknown event: %d", event);
+ }
+ break;
+ }
+
+ return rc;
+}
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_client.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_client.h
new file mode 100644
index 00000000..09011c43
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_client.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __IOTX_MQTT_H__
+#define __IOTX_MQTT_H__
+
+#include "infra_types.h"
+#include "infra_list.h"
+#include "infra_timer.h"
+#include "iotx_mqtt_config.h"
+#include "mqtt_api.h"
+
+#include "MQTTPacket.h"
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define mqtt_malloc(size) LITE_malloc(size, MEM_MAGIC, "mqtt")
+ #define mqtt_free(ptr) LITE_free(ptr)
+#else
+ #define mqtt_malloc(size) HAL_Malloc(size)
+ #define mqtt_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#define MQTT_DYNBUF_SEND_MARGIN (64)
+
+#define MQTT_DYNBUF_RECV_MARGIN (8)
+
+typedef enum {
+ IOTX_MC_CONNECTION_ACCEPTED = 0,
+ IOTX_MC_CONNECTION_REFUSED_UNACCEPTABLE_PROTOCOL_VERSION = 1,
+ IOTX_MC_CONNECTION_REFUSED_IDENTIFIER_REJECTED = 2,
+ IOTX_MC_CONNECTION_REFUSED_SERVER_UNAVAILABLE = 3,
+ IOTX_MC_CONNECTION_REFUSED_BAD_USERDATA = 4,
+ IOTX_MC_CONNECTION_REFUSED_NOT_AUTHORIZED = 5
+} iotx_mc_connect_ack_code_t;
+
+/* State of MQTT client */
+typedef enum {
+ IOTX_MC_STATE_INVALID = 0, /* MQTT in invalid state */
+ IOTX_MC_STATE_INITIALIZED = 1, /* MQTT in initializing state */
+ IOTX_MC_STATE_CONNECTED = 2, /* MQTT in connected state */
+ IOTX_MC_STATE_DISCONNECTED = 3, /* MQTT in disconnected state */
+ IOTX_MC_STATE_DISCONNECTED_RECONNECTING = 4, /* MQTT in reconnecting state */
+ IOTX_MC_STATE_CONNECT_BLOCK = 5 /* MQTT in connecting state when using async protocol stack */
+} iotx_mc_state_t;
+
+typedef enum MQTT_NODE_STATE {
+ IOTX_MC_NODE_STATE_NORMANL = 0,
+ IOTX_MC_NODE_STATE_INVALID,
+} iotx_mc_node_t;
+
+typedef enum {
+ TOPIC_NAME_TYPE = 0,
+ TOPIC_FILTER_TYPE
+} iotx_mc_topic_type_t;
+
+/* Handle structure of subscribed topic */
+typedef struct iotx_mc_topic_handle_s {
+ iotx_mc_topic_type_t topic_type;
+ iotx_mqtt_event_handle_t handle;
+#ifdef PLATFORM_HAS_DYNMEM
+ const char *topic_filter;
+ struct list_head linked_list;
+#else
+ const char topic_filter[CONFIG_MQTT_TOPIC_MAXLEN];
+ int used;
+#endif
+} iotx_mc_topic_handle_t;
+
+#if !WITH_MQTT_ONLY_QOS0
+/* Information structure of published topic */
+typedef struct REPUBLISH_INFO {
+ iotx_time_t pub_start_time; /* start time of publish request */
+ iotx_mc_node_t node_state; /* state of this node */
+ uint16_t msg_id; /* packet id of publish */
+ uint32_t len; /* length of publish message */
+#ifdef PLATFORM_HAS_DYNMEM
+ unsigned char *buf; /* publish message */
+ struct list_head linked_list;
+#else
+ unsigned char buf[IOTX_MC_TX_MAX_LEN]; /* publish message */
+ int used;
+#endif
+} iotx_mc_pub_info_t, *iotx_mc_pub_info_pt;
+#endif
+/* Reconnected parameter of MQTT client */
+typedef struct {
+ iotx_time_t reconnect_next_time; /* the next time point of reconnect */
+ uint32_t reconnect_time_interval_ms; /* time interval of this reconnect */
+} iotx_mc_reconnect_param_t;
+
+typedef struct {
+ uintptr_t packet_id;
+ uint8_t ack_type;
+ iotx_mqtt_event_handle_func_fpt sub_state_cb;
+#ifdef PLATFORM_HAS_DYNMEM
+ struct list_head linked_list;
+#else
+ int used;
+#endif
+} mqtt_sub_sync_node_t;
+
+/* structure of MQTT client */
+typedef struct Client {
+ void *lock_generic; /* generic lock */
+ uint32_t packet_id; /* packet id */
+ uint32_t request_timeout_ms; /* request timeout in millisecond */
+ uint32_t cycle_timeout_ms;
+ uint32_t buf_size_send; /* send buffer size in byte */
+#ifdef PLATFORM_HAS_DYNMEM
+#if WITH_MQTT_DYN_BUF
+ uint32_t buf_size_send_max; /* send buffer size max limit in byte */
+ uint32_t buf_size_read_max; /* recv buffer size max limit in byte */
+#endif
+#endif
+ uint32_t buf_size_read; /* read buffer size in byte */
+ uint8_t keepalive_probes; /* keepalive probes */
+#ifdef PLATFORM_HAS_DYNMEM
+ char *buf_send; /* pointer of send buffer */
+ char *buf_read; /* pointer of read buffer */
+#else
+ char buf_send[IOTX_MC_TX_MAX_LEN];
+ char buf_read[IOTX_MC_RX_MAX_LEN];
+#endif
+#ifdef PLATFORM_HAS_DYNMEM
+ struct list_head list_sub_handle; /* list of subscribe handle */
+#else
+ iotx_mc_topic_handle_t list_sub_handle[IOTX_MC_SUBHANDLE_LIST_MAX_LEN];
+#endif
+ utils_network_t ipstack; /* network parameter */
+ iotx_time_t next_ping_time; /* next ping time */
+ int ping_mark; /* flag of ping */
+ iotx_mc_state_t client_state; /* state of MQTT client */
+ iotx_mc_reconnect_param_t reconnect_param; /* reconnect parameter */
+ MQTTPacket_connectData connect_data; /* connection parameter */
+#if !WITH_MQTT_ONLY_QOS0
+#ifdef PLATFORM_HAS_DYNMEM
+ struct list_head list_pub_wait_ack; /* list of wait publish ack */
+#else
+ iotx_mc_pub_info_t list_pub_wait_ack[IOTX_MC_PUBWAIT_LIST_MAX_LEN];
+#endif
+#endif
+#ifdef PLATFORM_HAS_DYNMEM
+ struct list_head list_sub_sync_ack;
+#else
+ mqtt_sub_sync_node_t list_sub_sync_ack[IOTX_MC_SUBSYNC_LIST_MAX_LEN];
+#endif
+ void *lock_list_pub; /* lock for list of QoS1 pub */
+ void *lock_write_buf; /* lock of write */
+ void *lock_read_buf; /* lock of write */
+ void *lock_yield;
+ iotx_mqtt_event_handle_t handle_event; /* event handle */
+#ifndef PLATFORM_HAS_DYNMEM
+ int used;
+#endif
+} iotx_mc_client_t, *iotx_mc_client_pt;
+
+/* Information structure of mutli-subscribe */
+typedef struct {
+ const char *topicFilter;
+ iotx_mqtt_qos_t qos;
+ iotx_mqtt_event_handle_func_fpt messageHandler;
+} iotx_mutli_sub_info_t, *iotx_mutli_sub_info_pt;
+
+
+#endif /* __IOTX_MQTT_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_config.h
new file mode 100644
index 00000000..3e3d60d1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/iotx_mqtt_config.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef IOTX_MQTT_CONFIG_H__
+#define IOTX_MQTT_CONFIG_H__
+
+#ifndef WITH_MQTT_DYN_BUF
+ #define WITH_MQTT_DYN_BUF (1)
+#endif
+
+#ifndef WITH_MQTT_QOS2_PACKET
+ #define WITH_MQTT_QOS2_PACKET (0)
+#endif
+
+#ifndef WITH_MQTT_FLOW_CTRL
+ #define WITH_MQTT_FLOW_CTRL (0)
+#endif
+
+#ifndef WITH_MQTT_ONLY_QOS0
+ #define WITH_MQTT_ONLY_QOS0 (0)
+#endif
+
+#ifndef WITH_MQTT_DYN_CONNINFO
+ #define WITH_MQTT_DYN_CONNINFO (1)
+#endif
+
+#ifndef WITH_MQTT_ZIP_TOPIC
+ #define WITH_MQTT_ZIP_TOPIC (0)
+#endif
+
+/* maximum republish elements in list */
+#define IOTX_MC_REPUB_NUM_MAX (20)
+
+/* MQTT client version number */
+#define IOTX_MC_MQTT_VERSION (4)
+
+/* maximum MQTT packet-id */
+#define IOTX_MC_PACKET_ID_MAX (65535)
+
+/* maximum number of simultaneously invoke subscribe request */
+#define IOTX_MC_SUB_REQUEST_NUM_MAX (256)
+
+/* Minimum interval of MQTT reconnect in millisecond */
+#define IOTX_MC_RECONNECT_INTERVAL_MIN_MS (1000)
+
+/* Maximum interval of MQTT reconnect in millisecond */
+#define IOTX_MC_RECONNECT_INTERVAL_MAX_MS (16000)
+
+/* Max times of keepalive which has been send and did not received response package */
+#define IOTX_MC_KEEPALIVE_PROBE_MAX (1)
+
+
+/* Linked List Params When PLATFORM_HAS_DYNMEN Disabled */
+#ifndef PLATFORM_HAS_DYNMEN
+
+ /* mqtt pub wait list max length, for QoS 1 */
+ #ifndef IOTX_MC_PUBWAIT_LIST_MAX_LEN
+ #define IOTX_MC_PUBWAIT_LIST_MAX_LEN (5)
+ #endif
+
+ /* mqtt sub sync list max length */
+ #ifndef IOTX_MC_SUBSYNC_LIST_MAX_LEN
+ #define IOTX_MC_SUBSYNC_LIST_MAX_LEN (5)
+ #endif
+
+ /* mqtt sub handle list max length */
+ #ifndef IOTX_MC_SUBHANDLE_LIST_MAX_LEN
+ #define IOTX_MC_SUBHANDLE_LIST_MAX_LEN (5)
+ #endif
+
+ /* mqtt client max count */
+ #ifndef IOTX_MC_CLIENT_MAX_COUNT
+ #define IOTX_MC_CLIENT_MAX_COUNT (1)
+ #endif
+
+ #ifndef IOTX_MC_TX_MAX_LEN
+ #define IOTX_MC_TX_MAX_LEN (512)
+ #endif
+
+ #ifndef IOTX_MC_RX_MAX_LEN
+ #define IOTX_MC_RX_MAX_LEN (512)
+ #endif
+
+#endif /* PLATFORM_HAS_DYNMEM */
+
+#endif /* IOTX_MQTT_CONFIG_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_api.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_api.c
new file mode 100644
index 00000000..9947c393
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_api.c
@@ -0,0 +1,809 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_string.h"
+#include "infra_list.h"
+#include "infra_report.h"
+#include "infra_sha256.h"
+#include "infra_compat.h"
+
+#include "dev_sign_api.h"
+#include "mqtt_api.h"
+#include "mqtt_wrapper.h"
+#include "infra_redirect_region.h"
+
+#ifdef PLATFORM_HAS_DYNMEM
+ #ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define mqtt_api_malloc(size) LITE_malloc(size, MEM_MAGIC, "mqtt-api")
+ #define mqtt_api_free(ptr) LITE_free(ptr)
+ #else
+ #define mqtt_api_malloc(size) HAL_Malloc(size)
+ #define mqtt_api_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+ #endif
+
+#else
+ static iotx_mqtt_param_t g_iotx_mqtt_param;
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define mqtt_emerg(...) log_emerg("MQTT", __VA_ARGS__)
+ #define mqtt_crit(...) log_crit("MQTT", __VA_ARGS__)
+ #define mqtt_err(...) log_err("MQTT", __VA_ARGS__)
+ #define mqtt_warning(...) log_warning("MQTT", __VA_ARGS__)
+ #define mqtt_info(...) log_info("MQTT", __VA_ARGS__)
+ #define mqtt_debug(...) log_debug("MQTT", __VA_ARGS__)
+#else
+ #define mqtt_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+static void *g_mqtt_client = NULL;
+iotx_sign_mqtt_t g_default_sign;
+
+/* Handle structure of subscribed topic */
+typedef struct {
+#ifdef PLATFORM_HAS_DYNMEM
+ char *topic_filter;
+#else
+ char topic_filter[CONFIG_MQTT_TOPIC_MAXLEN];
+#endif
+ iotx_mqtt_event_handle_func_fpt handle;
+ void *user_data;
+ iotx_mqtt_qos_t qos;
+#ifdef PLATFORM_HAS_DYNMEM
+ struct list_head linked_list;
+#else
+ int used;
+#endif
+} iotx_mc_offline_subs_t;
+
+typedef struct {
+ int init;
+ void *mutex;
+#ifdef PLATFORM_HAS_DYNMEM
+ struct list_head offline_sub_list;
+#else
+ iotx_mc_offline_subs_t offline_sub_list[CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM];
+#endif
+
+} offline_sub_list_t;
+
+static offline_sub_list_t g_mqtt_offline_subs_list = {0};
+
+static int _offline_subs_list_init(void)
+{
+ if (g_mqtt_offline_subs_list.init) {
+ return SUCCESS_RETURN;
+ }
+
+ memset(&g_mqtt_offline_subs_list, 0, sizeof(offline_sub_list_t));
+ g_mqtt_offline_subs_list.init = 1;
+
+#ifdef PLATFORM_HAS_DYNMEM
+ INIT_LIST_HEAD(&g_mqtt_offline_subs_list.offline_sub_list);
+#endif
+
+ g_mqtt_offline_subs_list.mutex = HAL_MutexCreate();
+
+ return SUCCESS_RETURN;
+}
+
+static int _offline_subs_list_deinit(void)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_offline_subs_t *node = NULL, *next_node = NULL;
+ list_for_each_entry_safe(node, next_node, &g_mqtt_offline_subs_list.offline_sub_list, linked_list,
+ iotx_mc_offline_subs_t) {
+ list_del(&node->linked_list);
+ mqtt_api_free(node->topic_filter);
+ mqtt_api_free(node);
+ }
+#endif
+
+ if (g_mqtt_offline_subs_list.mutex) {
+ HAL_MutexDestroy(g_mqtt_offline_subs_list.mutex);
+ }
+ memset(&g_mqtt_offline_subs_list, 0, sizeof(offline_sub_list_t));
+
+ return 0;
+}
+
+static int iotx_mqtt_offline_subscribe(const char *topic_filter, iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func, void *pcontext)
+{
+ int ret;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_offline_subs_t *sub_info = NULL;
+#else
+ int idx = 0;
+#endif
+
+ if (topic_filter == NULL || topic_handle_func == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ _offline_subs_list_init();
+
+#ifdef PLATFORM_HAS_DYNMEM
+ HAL_MutexLock(g_mqtt_offline_subs_list.mutex);
+ list_for_each_entry(sub_info, &g_mqtt_offline_subs_list.offline_sub_list, linked_list, iotx_mc_offline_subs_t) {
+ if ((strlen(sub_info->topic_filter) == strlen(topic_filter)) &&
+ memcmp(sub_info->topic_filter, topic_filter, strlen(topic_filter)) == 0) {
+ sub_info->qos = qos;
+ sub_info->handle = topic_handle_func;
+ sub_info->user_data = pcontext;
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ return SUCCESS_RETURN;
+ }
+ }
+
+ sub_info = mqtt_api_malloc(sizeof(iotx_mc_offline_subs_t));
+ if (sub_info == NULL) {
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ return ERROR_MALLOC;
+ }
+
+ memset(sub_info, 0, sizeof(iotx_mc_offline_subs_t));
+ sub_info->topic_filter = mqtt_api_malloc(strlen(topic_filter) + 1);
+ if (sub_info->topic_filter == NULL) {
+ mqtt_api_free(sub_info);
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ return ERROR_MALLOC;
+ }
+ memset(sub_info->topic_filter, 0, strlen(topic_filter) + 1);
+ strncpy(sub_info->topic_filter, topic_filter, strlen(topic_filter));
+ sub_info->qos = qos;
+ sub_info->handle = topic_handle_func;
+ sub_info->user_data = pcontext;
+ INIT_LIST_HEAD(&sub_info->linked_list);
+
+ list_add_tail(&sub_info->linked_list, &g_mqtt_offline_subs_list.offline_sub_list);
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ ret = SUCCESS_RETURN;
+#else
+ if (strlen(topic_filter) >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ return MQTT_TOPIC_LEN_TOO_SHORT;
+ }
+
+ HAL_MutexLock(g_mqtt_offline_subs_list.mutex);
+ for (idx = 0; idx < CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM; idx++) {
+ if (g_mqtt_offline_subs_list.offline_sub_list[idx].used &&
+ (strlen(g_mqtt_offline_subs_list.offline_sub_list[idx].topic_filter) == strlen(topic_filter)) &&
+ memcmp(g_mqtt_offline_subs_list.offline_sub_list[idx].topic_filter, topic_filter, strlen(topic_filter)) == 0) {
+ g_mqtt_offline_subs_list.offline_sub_list[idx].qos = qos;
+ g_mqtt_offline_subs_list.offline_sub_list[idx].handle = topic_handle_func;
+ g_mqtt_offline_subs_list.offline_sub_list[idx].user_data = pcontext;
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ return SUCCESS_RETURN;
+ }
+ }
+ for (idx = 0; idx < CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM; idx++) {
+ if (g_mqtt_offline_subs_list.offline_sub_list[idx].used == 0) {
+ memset(&g_mqtt_offline_subs_list.offline_sub_list[idx], 0, sizeof(iotx_mc_offline_subs_t));
+ memcpy(g_mqtt_offline_subs_list.offline_sub_list[idx].topic_filter, topic_filter, strlen(topic_filter));
+ g_mqtt_offline_subs_list.offline_sub_list[idx].qos = qos;
+ g_mqtt_offline_subs_list.offline_sub_list[idx].handle = topic_handle_func;
+ g_mqtt_offline_subs_list.offline_sub_list[idx].user_data = pcontext;
+ g_mqtt_offline_subs_list.offline_sub_list[idx].used = 1;
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ return SUCCESS_RETURN;
+ }
+ }
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+ ret = MQTT_OFFLINE_LIST_LEN_TOO_SHORT;
+#endif
+
+ return ret;
+}
+
+static int iotx_mqtt_deal_offline_subs(void *client)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_offline_subs_t *node = NULL, *next_node = NULL;
+#else
+ int idx;
+#endif
+ if (g_mqtt_offline_subs_list.init == 0) {
+ return SUCCESS_RETURN;
+ }
+
+ HAL_MutexLock(g_mqtt_offline_subs_list.mutex);
+#ifdef PLATFORM_HAS_DYNMEM
+ list_for_each_entry_safe(node, next_node, &g_mqtt_offline_subs_list.offline_sub_list, linked_list,
+ iotx_mc_offline_subs_t) {
+ list_del(&node->linked_list);
+ wrapper_mqtt_subscribe(client, node->topic_filter, node->qos, node->handle, node->user_data);
+ mqtt_api_free(node->topic_filter);
+ mqtt_api_free(node);
+ }
+#else
+ for (idx = 0; idx < CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM; idx++) {
+ if (g_mqtt_offline_subs_list.offline_sub_list[idx].used) {
+ wrapper_mqtt_subscribe(client, g_mqtt_offline_subs_list.offline_sub_list[idx].topic_filter,
+ g_mqtt_offline_subs_list.offline_sub_list[idx].qos,
+ g_mqtt_offline_subs_list.offline_sub_list[idx].handle,
+ g_mqtt_offline_subs_list.offline_sub_list[idx].user_data);
+ g_mqtt_offline_subs_list.offline_sub_list[idx].used = 0;
+ }
+ }
+#endif
+ HAL_MutexUnlock(g_mqtt_offline_subs_list.mutex);
+
+ _offline_subs_list_deinit();
+
+ return SUCCESS_RETURN;
+}
+
+static void iotx_mqtt_report_funcs(void *pclient)
+{
+ int err;
+
+ iotx_mqtt_deal_offline_subs(pclient);
+
+#ifndef ATHOST_MQTT_REPORT_DISBALED
+ iotx_set_report_func(IOT_MQTT_Publish_Simple);
+ /* report module id */
+ err = iotx_report_mid(pclient);
+ if (SUCCESS_RETURN != err) {
+#ifdef DEBUG_REPORT_MID_DEVINFO_FIRMWARE
+ mqtt_err("failed to report mid");
+#endif
+ }
+
+ /* report device info */
+ err = iotx_report_devinfo(pclient);
+ if (SUCCESS_RETURN != err) {
+#ifdef DEBUG_REPORT_MID_DEVINFO_FIRMWARE
+ mqtt_err("failed to report devinfo");
+#endif
+ }
+
+ /* report firmware version */
+#if !defined(BUILD_AOS) && !defined(MUTE_VERSION_REPORT)
+ err = iotx_report_firmware_version(pclient);
+
+ if (SUCCESS_RETURN != err) {
+#ifdef DEBUG_REPORT_MID_DEVINFO_FIRMWARE
+ mqtt_err("failed to report firmware version");
+#endif
+ }
+#endif
+
+#endif
+}
+
+#ifdef DYNAMIC_REGISTER
+#include "dynreg_api.h"
+int HAL_SetDeviceSecret(char *device_secret);
+int HAL_GetProductSecret(char *product_secret);
+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);
+
+#define DYNAMIC_REG_KV_PREFIX "DYNAMIC_REG_"
+#define DYNAMIC_REG_KV_PREFIX_LEN 12
+
+static int _iotx_dynamic_register(iotx_http_region_types_t region, iotx_dev_meta_info_t *meta_info)
+{
+ char device_secret_kv[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+ int device_secret_len = IOTX_DEVICE_SECRET_LEN;
+ char kv_key[IOTX_DEVICE_NAME_LEN + DYNAMIC_REG_KV_PREFIX_LEN] = DYNAMIC_REG_KV_PREFIX;
+ int res = FAIL_RETURN;
+
+ memcpy(kv_key + strlen(kv_key), meta_info->device_name, strlen(meta_info->device_name));
+
+ /* Check if Device Secret exist in KV */
+ if (HAL_Kv_Get(kv_key, device_secret_kv, &device_secret_len) == 0) {
+ mqtt_info("Get DeviceSecret from KV succeed");
+
+ *(device_secret_kv + device_secret_len) = 0;
+ HAL_SetDeviceSecret(device_secret_kv);
+ memset(meta_info->device_secret, 0, IOTX_DEVICE_SECRET_LEN + 1);
+ memcpy(meta_info->device_secret, device_secret_kv, strlen(device_secret_kv));
+ } else {
+ char product_secret[IOTX_PRODUCT_SECRET_LEN + 1] = {0};
+
+ /* KV not exit, goto dynamic register */
+ mqtt_info("DeviceSecret KV not exist, Now We Need Dynamic Register...");
+
+ res = IOT_Dynamic_Register(region, meta_info);
+ if (res != SUCCESS_RETURN) {
+ mqtt_err("Dynamic Register Failed");
+ return FAIL_RETURN;
+ }
+
+ device_secret_len = strlen(meta_info->device_secret);
+ if (HAL_Kv_Set(kv_key, meta_info->device_secret, device_secret_len, 1) != 0) {
+ mqtt_err("Save Device Secret to KV Failed");
+ return FAIL_RETURN;
+ }
+
+ HAL_SetDeviceSecret(meta_info->device_secret);
+ }
+
+ return SUCCESS_RETURN;
+}
+#endif /* #ifdef DYNAMIC_REGISTER */
+
+#ifdef MQTT_PRE_AUTH
+#include "infra_preauth.h"
+extern int _sign_get_clientid(char *clientid_string, const char *device_id);
+extern int _iotx_generate_sign_string(const char *device_id, const char *device_name, const char *product_key,
+ const char *device_secret, char *sign_string);
+
+static int _iotx_preauth(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *meta,
+ iotx_sign_mqtt_t *preauth_out)
+{
+ uint16_t length = 0;
+ char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char sign_string[65] = {0};
+ int res;
+
+ memset(preauth_out, 0, sizeof(iotx_sign_mqtt_t));
+
+ /* setup device_id */
+ memcpy(device_id, meta->product_key, strlen(meta->product_key));
+ memcpy(device_id + strlen(device_id), ".", strlen("."));
+ memcpy(device_id + strlen(device_id), meta->device_name, strlen(meta->device_name));
+
+ /* setup clientid */
+ if (_sign_get_clientid(preauth_out->clientid, device_id) != SUCCESS_RETURN) {
+ return ERROR_DEV_SIGN_CLIENT_ID_TOO_SHORT;
+ }
+
+ /* setup sign_string */
+ res = _iotx_generate_sign_string(device_id, meta->device_name, meta->product_key, meta->device_secret, sign_string);
+ if (res < SUCCESS_RETURN) {
+ return res;
+ }
+
+ return preauth_get_connection_info(region, meta, sign_string, device_id, preauth_out);
+}
+#endif /* #ifdef MQTT_PRE_AUTH */
+
+/************************ Public Interface ************************/
+void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams)
+{
+ void *pclient;
+ iotx_dev_meta_info_t meta_info;
+ iotx_mqtt_param_t mqtt_params;
+ int region = 0;
+ int dynamic = 0;
+ int ret;
+ void *callback;
+
+ if (g_mqtt_client != NULL) {
+ mqtt_err("Already exist default MQTT connection, won't proceed another one");
+ return g_mqtt_client;
+ }
+
+ /* get region */
+ IOT_Ioctl(IOTX_IOCTL_GET_REGION, (void *)®ion);
+
+ /* get dynamic option */
+ IOT_Ioctl(IOTX_IOCTL_GET_DYNAMIC_REGISTER, (void *)&dynamic);
+
+ /* get meta_info from hal */
+ memset(&meta_info, 0, sizeof(iotx_dev_meta_info_t));
+ HAL_GetProductKey(meta_info.product_key);
+ HAL_GetDeviceName(meta_info.device_name);
+
+ if (meta_info.product_key[0] == '\0' || meta_info.product_key[IOTX_PRODUCT_KEY_LEN] != '\0') {
+ mqtt_err("Invalid product key, abort!");
+ return NULL;
+ }
+ if (meta_info.device_name[0] == '\0' || meta_info.device_name[IOTX_DEVICE_NAME_LEN] != '\0') {
+ mqtt_err("Invalid device name, abort!");
+ return NULL;
+ }
+
+#ifdef DYNAMIC_REGISTER /* get device secret through https dynamic register */
+ if (dynamic) {
+ HAL_GetProductSecret(meta_info.product_secret);
+ if (meta_info.product_secret[0] == '\0' || meta_info.product_secret[IOTX_PRODUCT_SECRET_LEN] != '\0') {
+ mqtt_err("Product Secret doesn't exist");
+ return NULL;
+ }
+
+ ret = _iotx_dynamic_register(region, &meta_info);
+ if (ret < SUCCESS_RETURN) {
+ mqtt_err("ret = _iotx_dynamic_register() = %d, abort", ret);
+ return NULL;
+ }
+ } else {
+ HAL_GetDeviceSecret(meta_info.device_secret);
+ if (meta_info.device_secret[0] == '\0' || meta_info.device_secret[IOTX_DEVICE_SECRET_LEN] != '\0') {
+ mqtt_err("Invalid device secret, abort!");
+ return NULL;
+ }
+ }
+#else /* get device secret from hal */
+ HAL_GetDeviceSecret(meta_info.device_secret);
+ if (meta_info.device_secret[0] == '\0' || meta_info.device_secret[IOTX_DEVICE_SECRET_LEN] != '\0') {
+ mqtt_err("Invalid device secret, abort!");
+ return NULL;
+ }
+#endif /* #ifdef DYNAMIC_REGISTER */
+
+#ifdef MQTT_PRE_AUTH /* preauth mode through https */
+ ret = _iotx_preauth(region, &meta_info, (iotx_sign_mqtt_t *)&g_default_sign); /* type convert */
+ if (ret < SUCCESS_RETURN) {
+ mqtt_err("ret = _iotx_preauth() = %d, abort", ret);
+ return NULL;
+ }
+#else /* direct mode */
+ ret = IOT_Sign_MQTT(region, &meta_info, &g_default_sign);
+ if (ret < SUCCESS_RETURN) {
+ mqtt_err("ret = IOT_Sign_MQTT() = %d, abort", ret);
+ return NULL;
+ }
+#endif /* #ifdef MQTT_PRE_AUTH */
+
+ /* Initialize MQTT parameter */
+ memset(&mqtt_params, 0x0, sizeof(iotx_mqtt_param_t));
+
+#ifdef SUPPORT_TLS
+ {
+ extern const char *iotx_ca_crt;
+ mqtt_params.pub_key = iotx_ca_crt;
+ }
+#endif
+ mqtt_params.request_timeout_ms = CONFIG_MQTT_REQUEST_TIMEOUT;
+ mqtt_params.clean_session = 0;
+ mqtt_params.keepalive_interval_ms = CONFIG_MQTT_KEEPALIVE_INTERVAL * 1000;
+ mqtt_params.read_buf_size = CONFIG_MQTT_MESSAGE_MAXLEN;
+ mqtt_params.write_buf_size = CONFIG_MQTT_MESSAGE_MAXLEN;
+ mqtt_params.handle_event.h_fp = NULL;
+ mqtt_params.handle_event.pcontext = NULL;
+
+ /* optional configuration */
+ if (pInitParams != NULL) {
+ if (pInitParams->host && strlen(pInitParams->host)) {
+ mqtt_params.host = pInitParams->host;
+ } else {
+ mqtt_warning("Using default hostname: '%s'", g_default_sign.hostname);
+ mqtt_params.host = g_default_sign.hostname;
+ }
+
+ if (pInitParams->port) {
+ mqtt_params.port = pInitParams->port;
+ } else {
+ mqtt_warning("Using default port: [%d]", g_default_sign.port);
+ mqtt_params.port = g_default_sign.port;
+ }
+
+ if (pInitParams->client_id && strlen(pInitParams->client_id)) {
+ mqtt_params.client_id = pInitParams->client_id;
+ } else {
+ mqtt_warning("Using default client_id: %s", g_default_sign.clientid);
+ mqtt_params.client_id = g_default_sign.clientid;
+ }
+
+ if (pInitParams->username && strlen(pInitParams->username)) {
+ mqtt_params.username = pInitParams->username;
+ } else {
+ mqtt_warning("Using default username: %s", g_default_sign.username);
+ mqtt_params.username = g_default_sign.username;
+ }
+
+ if (pInitParams->password && strlen(pInitParams->password)) {
+ mqtt_params.password = pInitParams->password;
+ } else {
+#if 1
+ mqtt_warning("Using default password: %s", "******");
+#else
+ mqtt_warning("Using default password: %s", g_default_sign.password);
+#endif
+ mqtt_params.password = g_default_sign.password;
+ }
+
+ if (pInitParams->request_timeout_ms < CONFIG_MQTT_REQ_TIMEOUT_MIN ||
+ pInitParams->request_timeout_ms > CONFIG_MQTT_REQ_TIMEOUT_MAX) {
+ mqtt_warning("Using default request_timeout_ms: %d, configured value(%d) out of [%d, %d]",
+ mqtt_params.request_timeout_ms,
+ pInitParams->request_timeout_ms,
+ CONFIG_MQTT_REQ_TIMEOUT_MIN,
+ CONFIG_MQTT_REQ_TIMEOUT_MAX);
+ } else {
+ mqtt_params.request_timeout_ms = pInitParams->request_timeout_ms;
+ }
+
+ if (pInitParams->clean_session == 0 || pInitParams->clean_session == 1) {
+ mqtt_params.clean_session = pInitParams->clean_session;
+ }
+
+ if (pInitParams->keepalive_interval_ms < CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN * 1000 ||
+ pInitParams->keepalive_interval_ms > CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX * 1000) {
+ mqtt_warning("Using default keepalive_interval_ms: %d, configured value(%d) out of [%d, %d]",
+ mqtt_params.keepalive_interval_ms,
+ pInitParams->keepalive_interval_ms,
+ CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN * 1000,
+ CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX * 1000);
+ } else {
+ mqtt_params.keepalive_interval_ms = pInitParams->keepalive_interval_ms;
+ }
+
+ if (!pInitParams->read_buf_size) {
+ mqtt_warning("Using default read_buf_size: %d", mqtt_params.read_buf_size);
+ } else {
+ mqtt_params.read_buf_size = pInitParams->read_buf_size;
+ }
+
+ if (!pInitParams->write_buf_size) {
+ mqtt_warning("Using default write_buf_size: %d", mqtt_params.write_buf_size);
+ } else {
+ mqtt_params.write_buf_size = pInitParams->write_buf_size;
+ }
+
+ if (pInitParams->handle_event.h_fp != NULL) {
+ mqtt_params.handle_event.h_fp = pInitParams->handle_event.h_fp;
+ }
+
+ if (pInitParams->handle_event.pcontext != NULL) {
+ mqtt_params.handle_event.pcontext = pInitParams->handle_event.pcontext;
+ }
+ } else {
+ mqtt_warning("Using default port: [%d]", g_default_sign.port);
+ mqtt_params.port = g_default_sign.port;
+
+ mqtt_warning("Using default hostname: '%s'", g_default_sign.hostname);
+ mqtt_params.host = g_default_sign.hostname;
+
+ mqtt_warning("Using default client_id: %s", g_default_sign.clientid);
+ mqtt_params.client_id = g_default_sign.clientid;
+
+ mqtt_warning("Using default username: %s", g_default_sign.username);
+ mqtt_params.username = g_default_sign.username;
+
+#if 1
+ mqtt_warning("Using default password: %s", "******");
+#else
+ mqtt_warning("Using default password: %s", g_default_sign.password);
+#endif
+ mqtt_params.password = g_default_sign.password;
+ }
+
+ pclient = wrapper_mqtt_init(&mqtt_params);
+ if (pclient == NULL) {
+ mqtt_err("wrapper_mqtt_init error");
+ return NULL;
+ }
+
+ ret = wrapper_mqtt_connect(pclient);
+ if (SUCCESS_RETURN != ret) {
+ if (MQTT_CONNECT_BLOCK != ret) {
+ mqtt_err("wrapper_mqtt_connect failed");
+ wrapper_mqtt_release(&pclient);
+ return NULL;
+ }
+ }
+
+#ifndef ASYNC_PROTOCOL_STACK
+ iotx_mqtt_report_funcs(pclient);
+#endif
+
+ g_mqtt_client = pclient;
+
+ /* Mqtt Connect Callback */
+ callback = iotx_event_callback(ITE_MQTT_CONNECT_SUCC);
+ if (callback) {
+ ((int (*)(void))callback)();
+ }
+
+ ret = iotx_redirect_region_subscribe();
+ if (ret < 0) {
+ mqtt_err("failed to subscribe mqtt redirect resgion topic.");;
+ }
+
+ return pclient;
+}
+
+int IOT_MQTT_Destroy(void **phandler)
+{
+ void *client;
+ if (phandler != NULL) {
+ client = *phandler;
+ *phandler = NULL;
+ } else {
+ client = g_mqtt_client;
+ }
+
+ if (client == NULL) {
+ mqtt_err("handler is null");
+ return NULL_VALUE_ERROR;
+ }
+
+ wrapper_mqtt_release(&client);
+ g_mqtt_client = NULL;
+
+ return SUCCESS_RETURN;
+}
+
+int IOT_MQTT_Yield(void *handle, int timeout_ms)
+{
+ void *pClient = (handle ? handle : g_mqtt_client);
+ return wrapper_mqtt_yield(pClient, timeout_ms);
+}
+
+/* check whether MQTT connection is established or not */
+int IOT_MQTT_CheckStateNormal(void *handle)
+{
+ void *pClient = (handle ? handle : g_mqtt_client);
+ if (pClient == NULL) {
+ mqtt_err("handler is null");
+ return NULL_VALUE_ERROR;
+ }
+
+ return wrapper_mqtt_check_state(pClient);
+}
+
+int IOT_MQTT_Subscribe(void *handle,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext)
+{
+ void *client = handle ? handle : g_mqtt_client;
+
+ if (client == NULL) { /* do offline subscribe */
+ return iotx_mqtt_offline_subscribe(topic_filter, qos, topic_handle_func, pcontext);
+ }
+
+ if (topic_filter == NULL || strlen(topic_filter) == 0 || topic_handle_func == NULL) {
+ mqtt_err("params err");
+ return NULL_VALUE_ERROR;
+ }
+
+#ifdef SUB_PERSISTENCE_ENABLED
+ if (qos > IOTX_MQTT_QOS3_SUB_LOCAL) {
+ mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d",
+ qos,
+ IOTX_MQTT_QOS0, IOTX_MQTT_QOS3_SUB_LOCAL, IOTX_MQTT_QOS0);
+ qos = IOTX_MQTT_QOS0;
+ }
+#else
+ if (qos > IOTX_MQTT_QOS2) {
+ mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d",
+ qos,
+ IOTX_MQTT_QOS0, IOTX_MQTT_QOS2, IOTX_MQTT_QOS0);
+ qos = IOTX_MQTT_QOS0;
+ }
+#endif
+
+ return wrapper_mqtt_subscribe(client, topic_filter, qos, topic_handle_func, pcontext);
+}
+
+#define SUBSCRIBE_SYNC_TIMEOUT_MAX 10000
+int IOT_MQTT_Subscribe_Sync(void *handle,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext,
+ int timeout_ms)
+{
+ void *client = handle ? handle : g_mqtt_client;
+
+ if (client == NULL) { /* do offline subscribe */
+ return iotx_mqtt_offline_subscribe(topic_filter, qos, topic_handle_func, pcontext);
+ }
+ if (timeout_ms > SUBSCRIBE_SYNC_TIMEOUT_MAX) {
+ timeout_ms = SUBSCRIBE_SYNC_TIMEOUT_MAX;
+ }
+
+ if (topic_filter == NULL || strlen(topic_filter) == 0 || topic_handle_func == NULL) {
+ mqtt_err("params err");
+ return NULL_VALUE_ERROR;
+ }
+
+#ifdef SUB_PERSISTENCE_ENABLED
+ if (qos > IOTX_MQTT_QOS3_SUB_LOCAL) {
+ mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d",
+ qos,
+ IOTX_MQTT_QOS0, IOTX_MQTT_QOS3_SUB_LOCAL, IOTX_MQTT_QOS0);
+ qos = IOTX_MQTT_QOS0;
+ }
+#else
+ if (qos > IOTX_MQTT_QOS2) {
+ mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d",
+ qos,
+ IOTX_MQTT_QOS0, IOTX_MQTT_QOS2, IOTX_MQTT_QOS0);
+ qos = IOTX_MQTT_QOS0;
+ }
+#endif
+
+ return wrapper_mqtt_subscribe_sync(client, topic_filter, qos, topic_handle_func, pcontext, timeout_ms);
+}
+
+int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter)
+{
+ void *client = handle ? handle : g_mqtt_client;
+
+
+ if (client == NULL || topic_filter == NULL || strlen(topic_filter) == 0) {
+ mqtt_err("params err");
+ return NULL_VALUE_ERROR;
+ }
+
+ return wrapper_mqtt_unsubscribe(client, topic_filter);
+}
+
+int IOT_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg)
+{
+ void *client = handle ? handle : g_mqtt_client;
+ int rc = -1;
+
+ if (client == NULL || topic_name == NULL || strlen(topic_name) == 0) {
+ mqtt_err("params err");
+ return NULL_VALUE_ERROR;
+ }
+
+ rc = wrapper_mqtt_publish(client, topic_name, topic_msg);
+ return rc;
+}
+
+int IOT_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len)
+{
+ iotx_mqtt_topic_info_t mqtt_msg;
+ void *client = handle ? handle : g_mqtt_client;
+ int rc = -1;
+
+ if (client == NULL || topic_name == NULL || strlen(topic_name) == 0) {
+ mqtt_err("params err");
+ return NULL_VALUE_ERROR;
+ }
+
+ memset(&mqtt_msg, 0x0, sizeof(iotx_mqtt_topic_info_t));
+
+ mqtt_msg.qos = qos;
+ mqtt_msg.retain = 0;
+ mqtt_msg.dup = 0;
+ mqtt_msg.payload = (void *)data;
+ mqtt_msg.payload_len = len;
+
+ rc = wrapper_mqtt_publish(client, topic_name, &mqtt_msg);
+
+ if (rc < 0) {
+ mqtt_err("IOT_MQTT_Publish failed\n");
+ return -1;
+ }
+
+ return rc;
+}
+
+int IOT_MQTT_Nwk_Event_Handler(void *handle, iotx_mqtt_nwk_event_t event, iotx_mqtt_nwk_param_t *param)
+{
+#ifdef ASYNC_PROTOCOL_STACK
+ void *client = handle ? handle : g_mqtt_client;
+ int rc = -1;
+
+ if (client == NULL || event >= IOTX_MQTT_SOC_MAX || param == NULL) {
+ mqtt_err("params err");
+ return NULL_VALUE_ERROR;
+ }
+
+ rc = wrapper_mqtt_nwk_event_handler(client, event, param);
+
+ if (rc < 0) {
+ mqtt_err("IOT_MQTT_Nwk_Event_Handler failed\n");
+ return -1;
+ }
+
+ switch (event) {
+ case IOTX_MQTT_SOC_CONNECTED: {
+ iotx_mqtt_report_funcs(client);
+ }
+ break;
+ default: {
+ }
+ break;
+ }
+
+ return rc;
+#else
+ return -1;
+#endif
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_api.h
new file mode 100644
index 00000000..45204167
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_api.h
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOT_EXPORT_MQTT_H_
+#define _IOT_EXPORT_MQTT_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+#define MUTLI_SUBSCIRBE_MAX (5)
+
+/* From mqtt_client.h */
+typedef enum {
+ IOTX_MQTT_QOS0 = 0,
+ IOTX_MQTT_QOS1,
+ IOTX_MQTT_QOS2,
+ IOTX_MQTT_QOS3_SUB_LOCAL
+} iotx_mqtt_qos_t;
+
+typedef enum {
+
+ /* Undefined event */
+ IOTX_MQTT_EVENT_UNDEF = 0,
+
+ /* MQTT disconnect event */
+ IOTX_MQTT_EVENT_DISCONNECT = 1,
+
+ /* MQTT reconnect event */
+ IOTX_MQTT_EVENT_RECONNECT = 2,
+
+ /* A ACK to the specific subscribe which specify by packet-id be received */
+ IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS = 3,
+
+ /* No ACK to the specific subscribe which specify by packet-id be received in timeout period */
+ IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT = 4,
+
+ /* A failed ACK to the specific subscribe which specify by packet-id be received*/
+ IOTX_MQTT_EVENT_SUBCRIBE_NACK = 5,
+
+ /* A ACK to the specific unsubscribe which specify by packet-id be received */
+ IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6,
+
+ /* No ACK to the specific unsubscribe which specify by packet-id be received in timeout period */
+ IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7,
+
+ /* A failed ACK to the specific unsubscribe which specify by packet-id be received*/
+ IOTX_MQTT_EVENT_UNSUBCRIBE_NACK = 8,
+
+ /* A ACK to the specific publish which specify by packet-id be received */
+ IOTX_MQTT_EVENT_PUBLISH_SUCCESS = 9,
+
+ /* No ACK to the specific publish which specify by packet-id be received in timeout period */
+ IOTX_MQTT_EVENT_PUBLISH_TIMEOUT = 10,
+
+ /* A failed ACK to the specific publish which specify by packet-id be received*/
+ IOTX_MQTT_EVENT_PUBLISH_NACK = 11,
+
+ /* MQTT packet published from MQTT remote broker be received */
+ IOTX_MQTT_EVENT_PUBLISH_RECEIVED = 12,
+
+ /* MQTT packet buffer overflow which the remaining space less than to receive byte */
+ IOTX_MQTT_EVENT_BUFFER_OVERFLOW = 13,
+} iotx_mqtt_event_type_t;
+
+/* topic information */
+typedef struct {
+ uint16_t packet_id;
+ uint8_t qos;
+ uint8_t dup;
+ uint8_t retain;
+ uint16_t topic_len;
+ uint32_t payload_len;
+ const char *ptopic;
+ const char *payload;
+} iotx_mqtt_topic_info_t, *iotx_mqtt_topic_info_pt;
+
+
+typedef struct {
+
+ /* Specify the event type */
+ iotx_mqtt_event_type_t event_type;
+
+ /*
+ * Specify the detail event information. @msg means different to different event types:
+ *
+ * 1) IOTX_MQTT_EVENT_UNKNOWN,
+ * IOTX_MQTT_EVENT_DISCONNECT,
+ * IOTX_MQTT_EVENT_RECONNECT :
+ * Its data type is string and the value is detail information.
+ *
+ * 2) IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS,
+ * IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT,
+ * IOTX_MQTT_EVENT_SUBCRIBE_NACK,
+ * IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS,
+ * IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT,
+ * IOTX_MQTT_EVENT_UNSUBCRIBE_NACK
+ * IOTX_MQTT_EVENT_PUBLISH_SUCCESS,
+ * IOTX_MQTT_EVENT_PUBLISH_TIMEOUT,
+ * IOTX_MQTT_EVENT_PUBLISH_NACK :
+ * Its data type is @uint32_t and the value is MQTT packet identifier.
+ *
+ * 3) IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
+ * Its data type is @iotx_mqtt_topic_info_pt and see detail at the declare of this type.
+ *
+ * */
+ void *msg;
+} iotx_mqtt_event_msg_t, *iotx_mqtt_event_msg_pt;
+
+
+/**
+ * @brief It define a datatype of function pointer.
+ * This type of function will be called when a related event occur.
+ *
+ * @param pcontext : The program context.
+ * @param pclient : The MQTT client.
+ * @param msg : The event message.
+ *
+ * @return none
+ */
+typedef void (*iotx_mqtt_event_handle_func_fpt)(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg);
+
+
+/* The structure of MQTT event handle */
+typedef struct {
+ iotx_mqtt_event_handle_func_fpt h_fp;
+ void *pcontext;
+} iotx_mqtt_event_handle_t, *iotx_mqtt_event_handle_pt;
+
+
+/* The structure of MQTT initial parameter */
+typedef struct {
+
+ uint16_t port; /* Specify MQTT broker port */
+ const char *host; /* Specify MQTT broker host */
+ const char *client_id; /* Specify MQTT connection client id*/
+ const char *username; /* Specify MQTT user name */
+ const char *password; /* Specify MQTT password */
+
+ /* Specify MQTT transport channel and key.
+ * If the value is NULL, it means that use TCP channel,
+ * If the value is NOT NULL, it means that use SSL/TLS channel and
+ * @pub_key point to the CA certification */
+
+ const char *pub_key;
+
+ uint8_t clean_session; /* Specify MQTT clean session or not*/
+ uint32_t request_timeout_ms; /* Specify timeout of a MQTT request in millisecond */
+ uint32_t keepalive_interval_ms; /* Specify MQTT keep-alive interval in millisecond */
+ uint32_t write_buf_size; /* Specify size of write-buffer in byte */
+ uint32_t read_buf_size; /* Specify size of read-buffer in byte */
+
+ iotx_mqtt_event_handle_t handle_event; /* Specify MQTT event handle */
+
+} iotx_mqtt_param_t, *iotx_mqtt_param_pt;
+
+typedef enum {
+ IOTX_MQTT_SOC_CONNECTED,
+ IOTX_MQTT_SOC_CLOSE,
+ IOTX_MQTT_SOC_READ,
+ IOTX_MQTT_SOC_WRITE,
+ IOTX_MQTT_SOC_MAX
+} iotx_mqtt_nwk_event_t;
+
+typedef struct {
+ uintptr_t fd;
+} iotx_mqtt_nwk_param_t;
+
+/** @defgroup group_api api
+ * @{
+ */
+
+/** @defgroup group_api_mqtt mqtt
+ * @{
+ */
+
+/**
+ * @brief Construct the MQTT client
+ * This function initialize the data structures, establish MQTT connection.
+ *
+ * @param [in] pInitParams: specify the MQTT client parameter.
+ *
+ * @retval NULL : Construct failed.
+ * @retval NOT_NULL : The handle of MQTT client.
+ * @see None.
+ */
+void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams);
+
+
+/**
+ * @brief Deconstruct the MQTT client
+ * This function disconnect MQTT connection and release the related resource.
+ *
+ * @param [in] phandle: pointer of handle, specify the MQTT client.
+ *
+ * @retval 0 : Deconstruct success.
+ * @retval -1 : Deconstruct failed.
+ * @see None.
+ */
+int IOT_MQTT_Destroy(void **phandle);
+
+
+/**
+ * @brief Handle MQTT packet from remote server and process timeout request
+ * which include the MQTT subscribe, unsubscribe, publish(QOS >= 1), reconnect, etc..
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] timeout_ms: specify the timeout in millisecond in this loop.
+ *
+ * @return status.
+ * @see None.
+ */
+int IOT_MQTT_Yield(void *handle, int timeout_ms);
+
+/**
+ * @brief check whether MQTT connection is established or not.
+ *
+ * @param [in] handle: specify the MQTT client.
+ *
+ * @retval true : MQTT in normal state.
+ * @retval false : MQTT in abnormal state.
+ * @see None.
+ */
+int IOT_MQTT_CheckStateNormal(void *handle);
+
+
+/**
+ * @brief Subscribe MQTT topic.
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] topic_filter: specify the topic filter.
+ * @param [in] qos: specify the MQTT Requested QoS.
+ * @param [in] topic_handle_func: specify the topic handle callback-function.
+ * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back.
+ *
+ * @retval -1 : Subscribe failed.
+ * @retval >=0 : Subscribe successful.
+ The value is a unique ID of this request.
+ The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'.
+ * @see None.
+ */
+int IOT_MQTT_Subscribe(void *handle,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext);
+
+/**
+ * @brief Subscribe MQTT topic and wait suback.
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] topic_filter: specify the topic filter.
+ * @param [in] qos: specify the MQTT Requested QoS.
+ * @param [in] topic_handle_func: specify the topic handle callback-function.
+ * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back.
+ * @param [in] timeout_ms: time in ms to wait.
+ *
+ * @retval -1 : Subscribe failed.
+ * @retval >=0 : Subscribe successful.
+ The value is a unique ID of this request.
+ The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'.
+ * @see None.
+ */
+int IOT_MQTT_Subscribe_Sync(void *handle,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext,
+ int timeout_ms);
+
+
+/**
+ * @brief Unsubscribe MQTT topic.
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] topic_filter: specify the topic filter.
+ *
+ * @retval -1 : Unsubscribe failed.
+ * @retval >=0 : Unsubscribe successful.
+ The value is a unique ID of this request.
+ The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'.
+ * @see None.
+ */
+int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter);
+
+
+/**
+ * @brief Publish message to specific topic.
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] topic_name: specify the topic name.
+ * @param [in] topic_msg: specify the topic message.
+ *
+ * @retval -1 : Publish failed.
+ * @retval 0 : Publish successful, where QoS is 0.
+ * @retval >0 : Publish successful, where QoS is >= 0.
+ The value is a unique ID of this request.
+ The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'.
+ * @see None.
+ */
+int IOT_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg);
+/**
+ * @brief Publish message to specific topic.
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] topic_name: specify the topic name.
+ * @param [in] qos: specify the MQTT Requested QoS.
+ * @param [in] data: specify the topic message payload.
+ * @param [in] len: specify the topic message payload len.
+ *
+ * @retval -1 : Publish failed.
+ * @retval 0 : Publish successful, where QoS is 0.
+ * @retval >0 : Publish successful, where QoS is >= 0.
+ The value is a unique ID of this request.
+ The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'.
+ * @see None.
+ */
+int IOT_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len);
+/* From mqtt_client.h */
+/** @} */ /* end of api_mqtt */
+
+/** @} */ /* end of api */
+
+/**
+ * @brief Only used in async network stack and FEATURE_ASYNC_PROTOCOL_STACK must be selected
+ *
+ * @param [in] handle: specify the MQTT client.
+ * @param [in] event: specify the network event.
+ * @param [in] param: specify the network params.
+ *
+ * @retval -1 : Handle failed.
+ * @retval 0 : Handle successful.
+ *
+ */
+int IOT_MQTT_Nwk_Event_Handler(void *handle, iotx_mqtt_nwk_event_t event, iotx_mqtt_nwk_param_t *param);
+
+/* MQTT Configurations
+ *
+ * These switches will affect mqtt_api.c and IOT_MQTT_XXX() functions' behaviour
+ *
+ */
+
+/* Default message length in bytes when PLATFORM_HAS_DYNMEM is not set */
+#define CONFIG_MQTT_MESSAGE_MAXLEN (1024)
+
+/* Default maximum length of topic name in byte when PLATFORM_HAS_DYNMEM is not set */
+#ifdef PLATFORM_HAS_DYNMEM
+#define CONFIG_MQTT_TOPIC_MAXLEN (128)
+#else
+#define CONFIG_MQTT_TOPIC_MAXLEN (50)
+#endif
+
+/* Default keepalive interval of MQTT request in second */
+#define CONFIG_MQTT_KEEPALIVE_INTERVAL (60)
+
+
+/* Default offline subscribe list max length when PLATFORM_HAS_DYNMEM is not set */
+#ifndef CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM
+#define CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM (5)
+#endif
+
+/* Default timeout interval of MQTT request in millisecond */
+#define CONFIG_MQTT_REQUEST_TIMEOUT (2000)
+
+/* Minimum timeout interval of MQTT request in millisecond */
+#define CONFIG_MQTT_REQ_TIMEOUT_MIN (500)
+
+/* Maximum timeout interval of MQTT request in millisecond */
+#define CONFIG_MQTT_REQ_TIMEOUT_MAX (5000)
+
+/* Minimum keepalive interval of MQTT request in second */
+#define CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN (30)
+
+/* Maximum keepalive interval of MQTT request in second */
+#define CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX (180)
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_internal.h
new file mode 100644
index 00000000..92522504
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_internal.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __IOTX_MQTT_INTERNAL_H__
+#define __IOTX_MQTT_INTERNAL_H__
+
+#include
+#include
+#include
+#include
+
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "infra_string.h"
+#include "infra_list.h"
+#include "infra_log.h"
+#include "infra_report.h"
+#include "infra_net.h"
+#include "infra_sha256.h"
+
+#include "dev_sign_api.h"
+#include "mqtt_wrapper.h"
+#include "iotx_mqtt_config.h"
+#include "iotx_mqtt_client.h"
+
+#include "MQTTPacket.h"
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define mqtt_emerg(...) log_emerg("MQTT", __VA_ARGS__)
+ #define mqtt_crit(...) log_crit("MQTT", __VA_ARGS__)
+ #define mqtt_err(...) log_err("MQTT", __VA_ARGS__)
+ #define mqtt_warning(...) log_warning("MQTT", __VA_ARGS__)
+ #define mqtt_info(...) log_info("MQTT", __VA_ARGS__)
+ #define mqtt_debug(...) log_debug("MQTT", __VA_ARGS__)
+#else
+ #define mqtt_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+ #define mqtt_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+#endif /* __IOTX_MQTT_INTERNAL_H__ */
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_wrapper.h
new file mode 100644
index 00000000..08a68acb
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/mqtt/mqtt_wrapper.h
@@ -0,0 +1,65 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+
+#include "mqtt_api.h"
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+void HAL_Printf(const char *fmt, ...);
+uint64_t HAL_UptimeMs(void);
+void HAL_SleepMs(uint32_t ms);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+
+int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1]);
+int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1]);
+int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
+int HAL_GetFirmwareVersion(char *version);
+
+#ifdef DYNAMIC_REGISTER
+int HAL_SetDeviceSecret(char *device_secret);
+int HAL_GetProductSecret(char product_secret[IOTX_PRODUCT_SECRET_LEN + 1]);
+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);
+#endif
+
+#ifdef SUPPORT_TLS
+ uintptr_t HAL_SSL_Establish(const char *host, uint16_t port, const char *ca_crt, uint32_t ca_crt_len);
+ int32_t HAL_SSL_Destroy(uintptr_t handle);
+ int HAL_SSL_Write(uintptr_t handle, const char *buf, int len, int timeout_ms);
+ int HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms);
+#else
+ int HAL_SSLHooks_set(ssl_hooks_t *hooks);
+ uintptr_t HAL_TCP_Establish(const char *host, uint16_t port);
+ int HAL_TCP_Destroy(uintptr_t fd);
+ int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms);
+ int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms);
+#endif
+
+/* mqtt protocol wrapper */
+void *wrapper_mqtt_init(iotx_mqtt_param_t *mqtt_params);
+int wrapper_mqtt_connect(void *client);
+int wrapper_mqtt_yield(void *client, int timeout_ms);
+int wrapper_mqtt_check_state(void *client);
+int wrapper_mqtt_subscribe(void *client,
+ const char *topicFilter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext);
+int wrapper_mqtt_subscribe_sync(void *client,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext,
+ int timeout_ms);
+int wrapper_mqtt_unsubscribe(void *client, const char *topicFilter);
+int wrapper_mqtt_publish(void *client, const char *topicName, iotx_mqtt_topic_info_pt topic_msg);
+int wrapper_mqtt_release(void **pclient);
+int wrapper_mqtt_nwk_event_handler(void *client, iotx_mqtt_nwk_event_t event, iotx_mqtt_nwk_param_t *param);
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota.c
new file mode 100644
index 00000000..f130a310
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota.c
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_ota_internal.h"
+
+#if (OTA_SIGNAL_CHANNEL) == 1
+ #include "ota_mqtt.c"
+#elif (OTA_SIGNAL_CHANNEL) == 2
+ #include "ota_coap.c"
+#else
+ #error "NOT support yet!"
+#endif
+
+
+typedef struct {
+ const char *product_key; /* point to product key */
+ const char *device_name; /* point to device name */
+
+ uint32_t id; /* message id */
+ IOT_OTA_State_t state; /* OTA state */
+ IOT_OTA_Type_t type; /* OTA Type */
+ uint32_t size_last_fetched; /* size of last downloaded */
+ uint32_t size_fetched; /* size of already downloaded */
+ uint32_t size_file; /* size of file */
+ char *purl; /* point to URL */
+ char *version; /* point to string */
+ char md5sum[33]; /* MD5 string */
+
+ void *md5; /* MD5 handle */
+ void *sha256; /* Sha256 handle */
+ void *ch_signal; /* channel handle of signal exchanged with OTA server */
+ void *ch_fetch; /* channel handle of download */
+
+ /* cota */
+ char *configId;
+ uint32_t configSize;
+ char *sign;
+ char *signMethod;
+ char *cota_url;
+ char *getType;
+
+ char *digestsign; /* security ota*/
+ int err; /* last error code */
+
+ ota_fetch_cb_fpt fetch_cb; /* fetch_callback */
+ void *user_data; /* fetch_callback's user_data */
+
+ cota_fetch_cb_fpt fetch_cota_cb;
+ void *cota_user_data;
+
+} OTA_Struct_t, *OTA_Struct_pt;
+
+
+/* check whether the progress state is valid or not */
+/* return: true, valid progress state; false, invalid progress state. */
+static int ota_check_progress(IOT_OTA_Progress_t progress)
+{
+ return ((progress >= IOT_OTAP_BURN_FAILED)
+ && (progress <= IOT_OTAP_FETCH_PERCENTAGE_MAX));
+}
+
+
+int iotx_ota_set_fetch_callback(void *pt, ota_fetch_cb_fpt fetch_cb, void *user_data)
+{
+ OTA_Struct_pt ota_pt = (OTA_Struct_pt)pt;
+
+ if (NULL == ota_pt || NULL == fetch_cb) {
+ return -1;
+ }
+
+ ota_pt->fetch_cb = fetch_cb;
+ ota_pt->user_data = user_data;
+ return 0;
+}
+
+
+int iotx_ota_set_cota_fetch_callback(void *pt, cota_fetch_cb_fpt fetch_cb, void *user_data)
+{
+ OTA_Struct_pt ota_pt = (OTA_Struct_pt)pt;
+
+ if (NULL == ota_pt || NULL == fetch_cb) {
+ return -1;
+ }
+
+ ota_pt->fetch_cota_cb = fetch_cb;
+ ota_pt->cota_user_data = user_data;
+ return 0;
+}
+
+#ifdef SUPPORT_SECURITY_OTA
+static int ota_security_ota_check(void *pcontext)
+{
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) pcontext;
+ if (h_ota->digestsign) {
+ printf("enter security check\n");
+ HAL_Firmware_Need_Check_Security_Ota(1);
+ return HAL_OTA_Security_check(h_ota->digestsign, h_ota->sign, h_ota->signMethod);
+ } else {
+ HAL_Firmware_Need_Check_Security_Ota(0);
+ }
+
+ return 0;
+}
+#endif
+
+static int ota_callback(void *pcontext, const char *msg, uint32_t msg_len, iotx_ota_topic_types_t type)
+{
+ const char *pvalue;
+ uint32_t val_len;
+
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) pcontext;
+
+ if (h_ota->state == IOT_OTAS_FETCHING) {
+ OTA_LOG_INFO("In downloading state");
+ return -1;
+ }
+
+ switch (type) {
+ case IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST:
+ case IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE: {
+ pvalue = otalib_JsonValueOf(msg, msg_len, "message", &val_len);
+ if (NULL == pvalue) {
+ OTA_LOG_ERROR("invalid json doc of OTA ");
+ return -1;
+ }
+
+ /* check whether is positive message */
+ if (!((strlen("success") == val_len) && (0 == strncmp(pvalue, "success", val_len)))) {
+ OTA_LOG_ERROR("fail state of json doc of OTA");
+ return -1;
+ }
+
+ /* get value of 'data' key */
+ pvalue = otalib_JsonValueOf(msg, msg_len, "data", &val_len);
+ if (NULL == pvalue) {
+ OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
+ return -1;
+ }
+
+ if (NULL != h_ota->digestsign) {
+ OTA_FREE(h_ota->digestsign);
+ h_ota->digestsign = NULL;
+ }
+
+ if (0 != otalib_GetFotaParams(pvalue, val_len, &h_ota->version, &h_ota->size_file,
+ &h_ota->sign, &h_ota->signMethod, &h_ota->purl, &h_ota->digestsign)) {
+ OTA_LOG_ERROR("Get firmware parameter failed");
+ return -1;
+ }
+#ifdef SUPPORT_SECURITY_OTA
+ if (0 != ota_security_ota_check(pcontext)) {
+ OTA_LOG_ERROR("Check ota security failed");
+ IOT_OTA_ReportProgress(pcontext, IOT_OTAP_CHECK_FALIED, NULL);
+ return -1;
+ }
+#endif
+ h_ota->size_fetched = 0;
+ if (NULL != h_ota->md5) {
+ otalib_MD5Deinit(h_ota->md5);
+ }
+ h_ota->md5 = otalib_MD5Init();
+
+ if (NULL != h_ota->sha256) {
+ otalib_Sha256Deinit(h_ota->sha256);
+ }
+ h_ota->sha256 = otalib_Sha256Init();
+
+ if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->purl))) {
+ OTA_LOG_ERROR("Initialize fetch module failed");
+ return -1;
+ }
+
+ h_ota->type = IOT_OTAT_FOTA;
+ h_ota->state = IOT_OTAS_FETCHING;
+
+ if (h_ota->fetch_cb) {
+ h_ota->fetch_cb(h_ota->user_data, 0, h_ota->size_file, h_ota->purl, h_ota->version);
+ }
+ }
+ break;
+
+ case IOTX_OTA_TOPIC_TYPE_CONFIG_GET: {
+ pvalue = otalib_JsonValueOf(msg, msg_len, "code", &val_len);
+ if (NULL == pvalue) {
+ OTA_LOG_ERROR("invalid json doc of OTA ");
+ return -1;
+ }
+
+ /* check whether is positive message */
+ if (!((strlen("200") == val_len) && (0 == strncmp(pvalue, "200", val_len)))) {
+ OTA_LOG_ERROR("fail state of json doc of OTA");
+ return -1;
+ }
+
+ /* get value of 'data' key */
+ pvalue = otalib_JsonValueOf(msg, msg_len, "data", &val_len);
+ if (NULL == pvalue) {
+ OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
+ return -1;
+ }
+
+ if (0 != otalib_GetConfigParams(pvalue, val_len, &h_ota->configId, &h_ota->configSize,
+ &h_ota->sign, &h_ota->signMethod, &h_ota->cota_url, &h_ota->getType)) {
+ OTA_LOG_ERROR("Get firmware parameter failed");
+ return -1;
+ }
+
+ h_ota->size_file = h_ota->configSize;
+ h_ota->size_fetched = 0;
+ if (NULL != h_ota->md5) {
+ otalib_MD5Deinit(h_ota->md5);
+ }
+ h_ota->md5 = otalib_MD5Init();
+
+ if (NULL != h_ota->sha256) {
+ otalib_Sha256Deinit(h_ota->sha256);
+ }
+ h_ota->sha256 = otalib_Sha256Init();
+
+ if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->cota_url))) {
+ OTA_LOG_ERROR("Initialize fetch module failed");
+ return -1;
+ }
+
+ h_ota->type = IOT_OTAT_COTA;
+ h_ota->state = IOT_OTAS_FETCHING;
+
+ if (h_ota->fetch_cota_cb) {
+ h_ota->fetch_cota_cb(h_ota->user_data, 0, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
+ h_ota->cota_url, h_ota->getType);
+ }
+ }
+ break;
+
+ case IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH: {
+ /* get value of 'params' key */
+ pvalue = otalib_JsonValueOf(msg, msg_len, "params", &val_len);
+ if (NULL == pvalue) {
+ OTA_LOG_ERROR("Not 'data' key in json doc of OTA");
+ return -1;
+ }
+
+ if (0 != otalib_GetConfigParams(pvalue, val_len, &h_ota->configId, &h_ota->configSize,
+ &h_ota->sign, &h_ota->signMethod, &h_ota->cota_url, &h_ota->getType)) {
+ OTA_LOG_ERROR("Get firmware parameter failed");
+ return -1;
+ }
+
+ h_ota->size_file = h_ota->configSize;
+ h_ota->size_fetched = 0;
+ if (NULL != h_ota->md5) {
+ otalib_MD5Deinit(h_ota->md5);
+ }
+ h_ota->md5 = otalib_MD5Init();
+
+ if (NULL != h_ota->sha256) {
+ otalib_Sha256Deinit(h_ota->sha256);
+ }
+ h_ota->sha256 = otalib_Sha256Init();
+
+ if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->cota_url))) {
+ OTA_LOG_ERROR("Initialize fetch module failed");
+ return -1;
+ }
+
+ h_ota->type = IOT_OTAT_COTA;
+ h_ota->state = IOT_OTAS_FETCHING;
+
+ if (h_ota->fetch_cota_cb) {
+ h_ota->fetch_cota_cb(h_ota->user_data, 0, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
+ h_ota->cota_url, h_ota->getType);
+ }
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+static int g_ota_is_initialized = 0;
+
+/* Initialize OTA module */
+void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal)
+{
+ OTA_Struct_pt h_ota = NULL;
+
+ if (1 == g_ota_is_initialized) {
+ OTA_LOG_ERROR("iot ota has been initialized");
+ return NULL;
+ }
+
+ if ((NULL == product_key) || (NULL == device_name)) {
+ OTA_LOG_ERROR("one or more parameters is invalid");
+ return NULL;
+ }
+
+ if (NULL == (h_ota = OTA_MALLOC(sizeof(OTA_Struct_t)))) {
+ OTA_LOG_ERROR("allocate failed");
+ return NULL;
+ }
+ memset(h_ota, 0, sizeof(OTA_Struct_t));
+ h_ota->type = IOT_OTAT_NONE;
+ h_ota->state = IOT_OTAS_UNINITED;
+
+ h_ota->ch_signal = osc_Init(product_key, device_name, ch_signal, ota_callback, h_ota);
+ if (NULL == h_ota->ch_signal) {
+ OTA_LOG_ERROR("initialize signal channel failed");
+ goto do_exit;
+ }
+
+ h_ota->md5 = otalib_MD5Init();
+ if (NULL == h_ota->md5) {
+ OTA_LOG_ERROR("initialize md5 failed");
+ goto do_exit;
+ }
+ h_ota->sha256 = otalib_Sha256Init();
+ if (NULL == h_ota->sha256) {
+ OTA_LOG_ERROR("initialize sha256 failed");
+ goto do_exit;
+ }
+
+ h_ota->product_key = product_key;
+ h_ota->device_name = device_name;
+ h_ota->state = IOT_OTAS_INITED;
+ g_ota_is_initialized = 1;
+ return h_ota;
+
+do_exit:
+
+ if (NULL != h_ota->ch_signal) {
+ osc_Deinit(h_ota->ch_signal);
+ }
+
+ if (NULL != h_ota->md5) {
+ otalib_MD5Deinit(h_ota->md5);
+ }
+
+ if (NULL != h_ota->sha256) {
+ otalib_Sha256Deinit(h_ota->sha256);
+ }
+
+ if (NULL != h_ota) {
+ OTA_FREE(h_ota);
+ }
+
+ return NULL;
+
+#undef AOM_INFO_MSG_LEN
+}
+
+
+/* deinitialize OTA module */
+int IOT_OTA_Deinit(void *handle)
+{
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if (NULL == h_ota) {
+ OTA_LOG_ERROR("handle is NULL");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+
+ g_ota_is_initialized = 0;
+
+ if (NULL != h_ota->ch_signal) {
+ osc_Deinit(h_ota->ch_signal);
+ }
+
+ if (NULL != h_ota->ch_fetch) {
+ ofc_Deinit(h_ota->ch_fetch);
+ }
+
+ if (NULL != h_ota->md5) {
+ otalib_MD5Deinit(h_ota->md5);
+ }
+
+ if (NULL != h_ota->sha256) {
+ otalib_Sha256Deinit(h_ota->sha256);
+ }
+
+ if (NULL != h_ota->purl) {
+ OTA_FREE(h_ota->purl);
+ }
+
+ if (NULL != h_ota->version) {
+ OTA_FREE(h_ota->version);
+ }
+
+ if (NULL != h_ota->configId) {
+ OTA_FREE(h_ota->configId);
+ }
+
+ if (NULL != h_ota->sign) {
+ OTA_FREE(h_ota->sign);
+ }
+
+ if (NULL != h_ota->signMethod) {
+ OTA_FREE(h_ota->signMethod);
+ }
+
+ if (NULL != h_ota->cota_url) {
+ OTA_FREE(h_ota->cota_url);
+ }
+
+ if (NULL != h_ota->getType) {
+ OTA_FREE(h_ota->getType);
+ }
+
+ if (NULL != h_ota->digestsign) {
+ OTA_FREE(h_ota->digestsign);
+ }
+
+ OTA_FREE(h_ota);
+ return 0;
+}
+
+
+#define OTA_VERSION_STR_LEN_MIN (1)
+#define OTA_VERSION_STR_LEN_MAX (32)
+
+int IOT_OTA_ReportVersion(void *handle, const char *version)
+{
+#define MSG_INFORM_LEN (128)
+
+ int ret, len;
+ char *msg_informed;
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if ((NULL == h_ota) || (NULL == version)) {
+ OTA_LOG_ERROR("one or more invalid parameter");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ len = strlen(version);
+ if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
+ OTA_LOG_ERROR("version string is invalid: must be [1, 32] chars");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+
+ if (NULL == (msg_informed = OTA_MALLOC(MSG_INFORM_LEN))) {
+ OTA_LOG_ERROR("allocate for msg_informed failed");
+ h_ota->err = IOT_OTAE_NOMEM;
+ return -1;
+ }
+
+ ret = otalib_GenInfoMsg(msg_informed, MSG_INFORM_LEN, h_ota->id, version);
+ if (ret != 0) {
+ OTA_LOG_ERROR("generate inform message failed");
+ h_ota->err = ret;
+ ret = -1;
+ goto do_exit;
+ }
+
+ ret = osc_ReportVersion(h_ota->ch_signal, msg_informed);
+ if (0 != ret) {
+ OTA_LOG_ERROR("Report version failed");
+ h_ota->err = ret;
+ ret = -1;
+ goto do_exit;
+ }
+ ret = 0;
+
+do_exit:
+ if (NULL != msg_informed) {
+ OTA_FREE(msg_informed);
+ }
+ return ret;
+
+#undef MSG_INFORM_LEN
+}
+
+int iotx_req_image(void *handle, const char *version)
+{
+#define MSG_REQUEST_LEN (128)
+
+ int ret, len;
+ char *msg_informed;
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if ((NULL == h_ota) || (NULL == version)) {
+ OTA_LOG_ERROR("one or more invalid parameter");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ len = strlen(version);
+ if ((len < OTA_VERSION_STR_LEN_MIN) || (len > OTA_VERSION_STR_LEN_MAX)) {
+ OTA_LOG_ERROR("version string is invalid: must be [1, 32] chars");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+
+ if (IOT_OTAS_FETCHING == h_ota->state) {
+ OTA_LOG_ERROR("ota is busying");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+
+ if (NULL == (msg_informed = OTA_MALLOC(MSG_REQUEST_LEN))) {
+ OTA_LOG_ERROR("allocate for msg_informed failed");
+ h_ota->err = IOT_OTAE_NOMEM;
+ return -1;
+ }
+
+ ret = otalib_GenInfoMsg(msg_informed, MSG_REQUEST_LEN, h_ota->id, version);
+ if (ret != 0) {
+ OTA_LOG_ERROR("generate request image message failed");
+ h_ota->err = ret;
+ ret = -1;
+ goto do_exit;
+ }
+
+ ret = osc_RequestImage(h_ota->ch_signal, msg_informed);
+ if (0 != ret) {
+ OTA_LOG_ERROR("Request image failed");
+ h_ota->err = ret;
+ ret = -1;
+ goto do_exit;
+ }
+ ret = 0;
+
+do_exit:
+ if (NULL != msg_informed) {
+ OTA_FREE(msg_informed);
+ }
+ return ret;
+
+#undef MSG_REQUEST_LEN
+}
+
+
+int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg)
+{
+#define MSG_REPORT_LEN (256)
+
+ int ret = -1;
+ char *msg_reported;
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if (NULL == handle) {
+ OTA_LOG_ERROR("handle is NULL");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+ if (!ota_check_progress(progress)) {
+ OTA_LOG_ERROR("progress is a invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+
+ if (NULL == (msg_reported = OTA_MALLOC(MSG_REPORT_LEN))) {
+ OTA_LOG_ERROR("allocate for msg_reported failed");
+ h_ota->err = IOT_OTAE_NOMEM;
+ return -1;
+ }
+
+ ret = otalib_GenReportMsg(msg_reported, MSG_REPORT_LEN, h_ota->id, progress, msg);
+ if (0 != ret) {
+ OTA_LOG_ERROR("generate reported message failed");
+ h_ota->err = ret;
+ goto do_exit;
+ }
+
+ ret = osc_ReportProgress(h_ota->ch_signal, msg_reported);
+ if (0 != ret) {
+ OTA_LOG_ERROR("Report progress failed");
+ h_ota->err = ret;
+ goto do_exit;
+ }
+
+ ret = 0;
+
+do_exit:
+ if (NULL != msg_reported) {
+ OTA_FREE(msg_reported);
+ }
+ return ret;
+
+#undef MSG_REPORT_LEN
+}
+
+int iotx_ota_get_config(void *handle, const char *configScope, const char *getType, const char *attributeKeys)
+{
+#define MSG_REPORT_LEN (256)
+
+ int ret = -1;
+ char *msg_get;
+ char topic[OTA_MQTT_TOPIC_LEN] = {0};
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+ iotx_mqtt_topic_info_t topic_info;
+
+ memset(&topic_info, 0, sizeof(iotx_mqtt_topic_info_t));
+
+ if (NULL == handle) {
+ OTA_LOG_ERROR("handle is NULL");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+
+ if (IOT_OTAS_FETCHING == h_ota->state) {
+ OTA_LOG_ERROR("ota is busying");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return -1;
+ }
+
+ if (NULL == (msg_get = OTA_MALLOC(MSG_REPORT_LEN))) {
+ OTA_LOG_ERROR("allocate for msg_reported failed");
+ h_ota->err = IOT_OTAE_NOMEM;
+ return -1;
+ }
+
+ if (0 > HAL_Snprintf(topic,
+ OTA_MQTT_TOPIC_LEN,
+ "/sys/%s/%s/thing/config/get",
+ h_ota->product_key,
+ h_ota->device_name)) {
+ goto do_exit;
+ };
+
+ if (0 > HAL_Snprintf(msg_get,
+ MSG_REPORT_LEN,
+ "{\"id\" : %d,\"version\":\"1.0\",\"params\":{\"configScope\":\"%s\",\"getType\":\"%s\",\"attributeKeys\":\"%s\"},\"method\":\"thing.config.get\"}",
+ h_ota->id,
+ configScope,
+ getType,
+ attributeKeys)) {
+ goto do_exit;
+ };
+ OTA_LOG_INFO(msg_get);
+ topic_info.qos = IOTX_MQTT_QOS0;
+ topic_info.payload = (void *)msg_get;
+ topic_info.payload_len = strlen(msg_get);
+
+ ret = osc_RequestConfig(h_ota->ch_signal, topic, &topic_info);
+ if (ret < 0) {
+ OTA_LOG_ERROR("publish failed");
+ return IOT_OTAE_OSC_FAILED;
+ }
+
+ ret = 0;
+
+do_exit:
+ if (NULL != msg_get) {
+ OTA_FREE(msg_get);
+ }
+ return ret;
+
+#undef MSG_REPORT_LEN
+}
+
+
+/* check whether is downloading */
+int IOT_OTA_IsFetching(void *handle)
+{
+ OTA_Struct_pt h_ota = (OTA_Struct_pt)handle;
+
+ if (NULL == handle) {
+ OTA_LOG_ERROR("handle is NULL");
+ return 0;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return 0;
+ }
+
+ return (IOT_OTAS_FETCHING == h_ota->state);
+}
+
+
+/* check whether fetch over */
+int IOT_OTA_IsFetchFinish(void *handle)
+{
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if (NULL == handle) {
+ OTA_LOG_ERROR("handle is NULL");
+ return 0;
+ }
+
+ if (IOT_OTAS_UNINITED == h_ota->state) {
+ OTA_LOG_ERROR("handle is uninitialized");
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return 0;
+ }
+
+ return (IOT_OTAS_FETCHED == h_ota->state);
+}
+
+
+int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
+{
+ int ret;
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if ((NULL == handle) || (NULL == buf) || (0 == buf_len)) {
+ OTA_LOG_ERROR("invalid parameter");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ if (IOT_OTAS_FETCHING != h_ota->state) {
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return IOT_OTAE_INVALID_STATE;
+ }
+
+ ret = ofc_Fetch(h_ota->ch_fetch, buf, buf_len, timeout_s);
+ if (ret < 0) {
+ OTA_LOG_ERROR("Fetch firmware failed");
+ h_ota->state = IOT_OTAS_FETCHED;
+ h_ota->type = IOT_OTAT_NONE;
+ h_ota->err = IOT_OTAE_FETCH_FAILED;
+
+ if (h_ota->fetch_cb && h_ota->purl) {
+ h_ota->fetch_cb(h_ota->user_data, 1, h_ota->size_file, h_ota->purl, h_ota->version);
+ /* remove */
+ h_ota->purl = NULL;
+ } else if (h_ota->fetch_cota_cb && h_ota->cota_url) {
+ h_ota->fetch_cota_cb(h_ota->user_data, 1, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
+ h_ota->cota_url, h_ota->getType);
+ /* remove */
+ h_ota->cota_url = NULL;
+ }
+ h_ota->size_fetched = 0;
+ return -1;
+ } else if (0 == h_ota->size_fetched) {
+ /* force report status in the first */
+ IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_PERCENTAGE_MIN, "Enter in downloading state");
+ }
+
+ otalib_MD5Update(h_ota->md5, buf, ret);
+ otalib_Sha256Update(h_ota->sha256, buf, ret);
+ h_ota->size_last_fetched = ret;
+ h_ota->size_fetched += ret;
+
+ if (h_ota->size_fetched >= h_ota->size_file) {
+ h_ota->type = IOT_OTAT_NONE;
+ h_ota->state = IOT_OTAS_FETCHED;
+ if (h_ota->fetch_cb && h_ota->purl) {
+ h_ota->fetch_cb(h_ota->user_data, 1, h_ota->size_file, h_ota->purl, h_ota->version);
+ /* remove */
+ h_ota->purl = NULL;
+ } else if (h_ota->fetch_cota_cb && h_ota->cota_url) {
+ h_ota->fetch_cota_cb(h_ota->user_data, 1, h_ota->configId, h_ota->configSize, h_ota->sign, h_ota->signMethod,
+ h_ota->cota_url, h_ota->getType);
+ /* remove */
+ h_ota->cota_url = NULL;
+ }
+ }
+
+ return ret;
+}
+
+
+int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len)
+{
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if ((NULL == handle) || (NULL == buf) || (0 == buf_len)) {
+ OTA_LOG_ERROR("invalid parameter");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ if (h_ota->state < IOT_OTAS_FETCHING) {
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ return IOT_OTAE_INVALID_STATE;
+ }
+
+ switch (type) {
+ case IOT_OTAG_COTA_CONFIG_ID: {
+ char **value = (char **)buf;
+ if (value == NULL || *value != NULL || h_ota->configId == NULL) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *value = OTA_API_MALLOC(strlen(h_ota->configId) + 1);
+ if (*value == NULL) {
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+ memset(*value, 0, strlen(h_ota->configId) + 1);
+ memcpy(*value, h_ota->configId, strlen(h_ota->configId));
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_COTA_CONFIG_SIZE: {
+ if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *((uint32_t *)buf) = h_ota->configSize;
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_COTA_SIGN: {
+ char **value = (char **)buf;
+ if (value == NULL || *value != NULL || h_ota->sign == NULL) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *value = OTA_API_MALLOC(strlen(h_ota->sign) + 1);
+ if (*value == NULL) {
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+ memset(*value, 0, strlen(h_ota->sign) + 1);
+ memcpy(*value, h_ota->sign, strlen(h_ota->sign));
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_COTA_SIGN_METHOD: {
+ char **value = (char **)buf;
+ if (value == NULL || *value != NULL || h_ota->signMethod == NULL) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *value = OTA_API_MALLOC(strlen(h_ota->signMethod) + 1);
+ if (*value == NULL) {
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+ memset(*value, 0, strlen(h_ota->signMethod) + 1);
+ memcpy(*value, h_ota->signMethod, strlen(h_ota->signMethod));
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_COTA_URL: {
+ char **value = (char **)buf;
+ if (value == NULL || *value != NULL || h_ota->cota_url == NULL) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *value = OTA_API_MALLOC(strlen(h_ota->cota_url) + 1);
+ if (*value == NULL) {
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+ memset(*value, 0, strlen(h_ota->cota_url) + 1);
+ memcpy(*value, h_ota->cota_url, strlen(h_ota->cota_url));
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_COTA_GETTYPE: {
+ char **value = (char **)buf;
+ if (value == NULL || *value != NULL || h_ota->getType == NULL) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *value = OTA_API_MALLOC(strlen(h_ota->getType) + 1);
+ if (*value == NULL) {
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+ memset(*value, 0, strlen(h_ota->getType) + 1);
+ memcpy(*value, h_ota->getType, strlen(h_ota->getType));
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_OTA_TYPE: {
+ if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *((uint32_t *)buf) = h_ota->type;
+ return 0;
+ }
+ }
+ break;
+ case IOT_OTAG_FETCHED_SIZE:
+ if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *((uint32_t *)buf) = h_ota->size_fetched;
+ return 0;
+ }
+
+ case IOT_OTAG_FILE_SIZE:
+ if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else {
+ *((uint32_t *)buf) = h_ota->size_file;
+ return 0;
+ };
+
+ case IOT_OTAG_VERSION: {
+ strncpy(buf, h_ota->version, buf_len);
+ ((char *)buf)[buf_len - 1] = '\0';
+ }
+ break;
+
+ case IOT_OTAG_MD5SUM:
+ strncpy(buf, h_ota->md5sum, buf_len);
+ ((char *)buf)[buf_len - 1] = '\0';
+ break;
+
+ case IOT_OTAG_CHECK_FIRMWARE:
+ if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else if (h_ota->state != IOT_OTAS_FETCHED) {
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ OTA_LOG_ERROR("Firmware can be checked in IOT_OTAS_FETCHED state only");
+ return -1;
+ } else {
+ char md5_str[33];
+ otalib_MD5Finalize(h_ota->md5, md5_str);
+ OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->md5sum, md5_str);
+ if (0 == strcmp(h_ota->md5sum, md5_str)) {
+ *((uint32_t *)buf) = 1;
+ } else {
+ *((uint32_t *)buf) = 0;
+ IOT_OTA_ReportProgress(h_ota, IOT_OTAP_CHECK_FALIED, NULL);
+ OTA_LOG_ERROR("image checksum compare failed");
+ }
+ return 0;
+ }
+ case IOT_OTAG_CHECK_CONFIG:
+ if ((4 != buf_len) || (0 != ((unsigned long)buf & 0x3))) {
+ OTA_LOG_ERROR("Invalid parameter");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ } else if (h_ota->state != IOT_OTAS_FETCHED) {
+ h_ota->err = IOT_OTAE_INVALID_STATE;
+ OTA_LOG_ERROR("Config can be checked in IOT_OTAS_FETCHED state only");
+ return -1;
+ } else {
+ if (0 == strncmp(h_ota->signMethod, "Md5", strlen(h_ota->signMethod))) {
+ char md5_str[33];
+ otalib_MD5Finalize(h_ota->md5, md5_str);
+ OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->sign, md5_str);
+ printf("MD5:origin=%s, now=%s\n", h_ota->sign, md5_str);
+ if (0 == strcmp(h_ota->sign, md5_str)) {
+ *((uint32_t *)buf) = 1;
+ } else {
+ *((uint32_t *)buf) = 0;
+ }
+ }
+ if (0 == strncmp(h_ota->signMethod, "SHA256", strlen(h_ota->signMethod))) {
+ char sha256_str[65];
+ otalib_Sha256Finalize(h_ota->sha256, sha256_str);
+ OTA_LOG_DEBUG("origin=%s, now=%s", h_ota->sign, sha256_str);
+ printf("SHA256:origin=%s, now=%s\n", h_ota->sign, sha256_str);
+ if (0 == strcmp(h_ota->sign, sha256_str)) {
+ *((uint32_t *)buf) = 1;
+ } else {
+ *((uint32_t *)buf) = 0;
+ }
+ }
+ return 0;
+ }
+ case IOT_OTAG_RESET_FETCHED_SIZE: {
+ h_ota->size_fetched = 0;
+ return 0;
+ }
+ default:
+ OTA_LOG_ERROR("invalid cmd type");
+ h_ota->err = IOT_OTAE_INVALID_PARAM;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* Get last error code */
+int IOT_OTA_GetLastError(void *handle)
+{
+ OTA_Struct_pt h_ota = (OTA_Struct_pt) handle;
+
+ if (NULL == handle) {
+ OTA_LOG_ERROR("handle is NULL");
+ return IOT_OTAE_INVALID_PARAM;
+ }
+
+ return h_ota->err;
+}
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota.h
new file mode 100644
index 00000000..816e31ea
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __IOTX_OTA_H__
+#define __IOTX_OTA_H__
+
+int iotx_ota_get_config(void *handle, const char *configScope, const char *getType,
+ const char *attributeKeys);
+
+int iotx_req_image(void *handle, const char *version);
+
+#endif /* #ifndef __IOTX_OTA_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota_config.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota_config.h
new file mode 100644
index 00000000..3536a436
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota_config.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __IOTX_OTA_CONFIG_H__
+#define __IOTX_OTA_CONFIG_H__
+
+#ifndef OTA_SIGNAL_CHANNEL
+ #define OTA_SIGNAL_CHANNEL (1)
+#endif
+
+#endif /* __IOTX_OTA_CONFIG_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota_internal.h
new file mode 100644
index 00000000..e08cfa3a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/iotx_ota_internal.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _IOTX_OTA_INTERNAL_H_
+#define _IOTX_OTA_INTERNAL_H_
+
+#include
+#include
+#include
+
+#include "infra_httpc.h"
+#include "infra_string.h"
+#include "infra_md5.h"
+#include "infra_sha256.h"
+#include "infra_json_parser.h"
+#include "ota_api.h"
+#include "iotx_ota_config.h"
+#include "ota_wrapper.h"
+
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#define OTA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "ota")
+#define OTA_FREE(ptr) LITE_free(ptr)
+#define OTA_API_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "ota.api")
+#define OTA_API_FREE(ptr) LITE_free(ptr)
+#else
+#define OTA_MALLOC(size) HAL_Malloc(size)
+#define OTA_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#define OTA_API_MALLOC(size) HAL_Malloc(size)
+#define OTA_API_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#define OTA_SNPRINTF HAL_Snprintf
+
+#ifdef INFRA_LOG
+#include "infra_log.h"
+#define OTA_LOG_CRIT(...) log_crit("ota", __VA_ARGS__)
+#define OTA_LOG_ERROR(...) log_err("ota", __VA_ARGS__)
+#define OTA_LOG_WRN(...) log_warning("ota", __VA_ARGS__)
+#define OTA_LOG_INFO(...) log_info("ota", __VA_ARGS__)
+#define OTA_LOG_DEBUG(...) log_debug("ota", __VA_ARGS__)
+#else
+#define OTA_LOG_CRIT(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define OTA_LOG_ERROR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define OTA_LOG_WRN(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define OTA_LOG_INFO(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define OTA_LOG_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#endif
+
+typedef enum {
+ IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST = 1,
+ IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE = 2,
+ IOTX_OTA_TOPIC_TYPE_CONFIG_GET = 3,
+ IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH = 4,
+ IOTX_OTA_TOPIC_TYPE_MAX
+} iotx_ota_topic_types_t;
+
+typedef int (*ota_cb_fpt)(void *pcontext, const char *msg, uint32_t msg_len, iotx_ota_topic_types_t type);
+/* is_fetch = 0; start fetch */
+/* is_fetch = 1; stop fetch */
+typedef void(*ota_fetch_cb_fpt)(void *user_data, int is_fetch, uint32_t size_file, char *purl, char *version);
+/* is_fetch = 0; start fetch */
+/* is_fetch = 1; stop fetch */
+typedef void(*cota_fetch_cb_fpt)(void *user_data, int is_fetch, char *configId, uint32_t configSize, char *sign, \
+ char *signMethod, char *url, char *getType);
+
+int iotx_ota_set_fetch_callback(void *pt, ota_fetch_cb_fpt fetch_cb, void *user_data);
+int iotx_ota_set_cota_fetch_callback(void *pt, cota_fetch_cb_fpt fetch_cb, void *user_data);
+
+const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len);
+void *otalib_MD5Init(void);
+void otalib_MD5Update(void *md5, const char *buf, size_t buf_len);
+void otalib_MD5Finalize(void *md5, char *output_str);
+void otalib_MD5Deinit(void *md5);
+void *otalib_Sha256Init(void);
+void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len);
+void otalib_Sha256Finalize(void *sha256, char *output_str);
+void otalib_Sha256Deinit(void *sha256);
+int otalib_GetFirmwareFixlenPara(const char *json_doc,
+ size_t json_doc_len,
+ const char *key,
+ char *dest,
+ size_t dest_len);
+int otalib_GetFirmwareVarlenPara(const char *json_doc,
+ size_t json_doc_len,
+ const char *key,
+ char **dest);
+int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5,
+ uint32_t *file_size);
+int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign,
+ char **signMethod, char **url, char **getType);
+int otalib_GetFotaParams(const char *json_doc, uint32_t json_len, char **version, uint32_t *file_size, char **sign,
+ char **signMethod, char **url, char **digestsign);
+int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version);
+int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail);
+
+void *ofc_Init(char *url);
+int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s);
+int ofc_Deinit(void *handle);
+#ifdef SUPPORT_SECURITY_OTA
+int HAL_OTA_Security_check(const char *digest, const char *sign, const char *signMethod);
+int HAL_Firmware_Check_Rsa_Key(char *buffer, uint32_t length);
+void HAL_Firmware_Need_Check_Security_Ota(uint8_t flag);
+#endif
+#endif /* _IOTX_OTA_INTERNAL_H_ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_api.h
new file mode 100644
index 00000000..0ff36ca8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_api.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __OTA_EXPORT_H__
+#define __OTA_EXPORT_H__
+
+#include "infra_types.h"
+#include "infra_defs.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define OTA_CH_SIGNAL_MQTT (0)
+#define OTA_CH_SIGNAL_COAP (1)
+#define OTA_CH_FETCH_HTTP (1)
+
+
+typedef enum {
+
+ IOT_OTAE_GENERAL = -1,
+ IOT_OTAE_INVALID_PARAM = -2,
+ IOT_OTAE_INVALID_STATE = -3,
+ IOT_OTAE_STR_TOO_LONG = -4,
+ IOT_OTAE_FETCH_FAILED = -5,
+ IOT_OTAE_NOMEM = -6,
+ IOT_OTAE_OSC_FAILED = -7,
+ IOT_OTAE_NONE = 0,
+
+} IOT_OTA_Err_t;
+
+
+/* State of OTA */
+typedef enum {
+ IOT_OTAS_UNINITED = 0, /* Uninitialized State */
+ IOT_OTAS_INITED, /* Initialized State */
+ IOT_OTAS_FETCHING, /* Fetching firmware */
+ IOT_OTAS_FETCHED /* Fetching firmware finish */
+} IOT_OTA_State_t;
+
+typedef enum {
+ IOT_OTAT_NONE,
+ IOT_OTAT_COTA,
+ IOT_OTAT_FOTA
+} IOT_OTA_Type_t;
+
+/* Progress of OTA */
+typedef enum {
+
+ /* Burn firmware file failed */
+ IOT_OTAP_BURN_FAILED = -4,
+
+ /* Check firmware file failed */
+ IOT_OTAP_CHECK_FALIED = -3,
+
+ /* Fetch firmware file failed */
+ IOT_OTAP_FETCH_FAILED = -2,
+
+ /* Initialized failed */
+ IOT_OTAP_GENERAL_FAILED = -1,
+
+
+ /* [0, 100], percentage of fetch progress */
+
+ /* The minimum percentage of fetch progress */
+ IOT_OTAP_FETCH_PERCENTAGE_MIN = 0,
+
+ /* The maximum percentage of fetch progress */
+ IOT_OTAP_FETCH_PERCENTAGE_MAX = 100
+
+} IOT_OTA_Progress_t;
+
+
+typedef enum {
+ IOT_OTAG_COTA_CONFIG_ID,
+ IOT_OTAG_COTA_CONFIG_SIZE,
+ IOT_OTAG_COTA_SIGN,
+ IOT_OTAG_COTA_SIGN_METHOD,
+ IOT_OTAG_COTA_URL,
+ IOT_OTAG_COTA_GETTYPE,
+ IOT_OTAG_OTA_TYPE,
+ IOT_OTAG_FETCHED_SIZE, /* option for get already fetched size */
+ IOT_OTAG_FILE_SIZE, /* size of file */
+ IOT_OTAG_MD5SUM, /* md5 in string format */
+ IOT_OTAG_VERSION, /* version in string format */
+ IOT_OTAG_CHECK_FIRMWARE, /* Check firmware is valid or not */
+ IOT_OTAG_CHECK_CONFIG, /* Check config file is valid or not */
+ IOT_OTAG_RESET_FETCHED_SIZE /* reset the size_fetched parameter to be 0 */
+} IOT_OTA_CmdType_t;
+
+/** @defgroup group_api api
+ * @{
+ */
+
+/** @defgroup group_api_ota ota
+ * @{
+ */
+
+/**
+ * @brief Initialize OTA module, and return handle.
+ * The MQTT client must be construct before calling this interface.
+ *
+ * @param [in] product_key: specify the product key.
+ * @param [in] device_name: specify the device name.
+ * @param [in] ch_signal: specify the signal channel.
+ *
+ * @retval 0 : Successful.
+ * @retval -1 : Failed.
+ * @see None.
+ */
+DLL_IOT_API void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal);
+
+
+/**
+ * @brief Deinitialize OTA module specified by the 'handle', and release the related resource.
+ * You must call this interface to release resource if reboot is not invoked after downloading.
+ *
+ * @param [in] handle: specify the OTA module.
+ *
+ * @retval 0 : Successful.
+ * @retval < 0 : Failed, the value is error code.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_Deinit(void *handle);
+
+
+/**
+ * @brief Report firmware version information to OTA server (optional).
+ * NOTE: please
+ *
+ * @param [in] handle: specify the OTA module.
+ * @param [in] version: specify the firmware version in string format.
+ *
+ * @retval 0 : Successful.
+ * @retval < 0 : Failed, the value is error code.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_ReportVersion(void *handle, const char *version);
+
+/**
+ * @brief Report detail progress to OTA server (optional).
+ * NOTE: please
+ *
+ * @param [in] handle: specify the OTA module.
+ * @param [in] progress: specify the progress defined by 'IOT_OTA_Progress_t'.
+ * @param [in] msg: detail progress information in string.
+ *
+ * @retval 0 : Successful.
+ * @retval < 0 : Failed, the value is error code.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg);
+
+
+/**
+ * @brief Check whether is on fetching state
+ *
+ * @param [in] handle: specify the OTA module.
+ *
+ * @retval 1 : Yes.
+ * @retval 0 : No.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_IsFetching(void *handle);
+
+
+/**
+ * @brief Check whether is on end-of-fetch state.
+ *
+ * @param [in] handle: specify the OTA module.
+ *
+ * @retval 1 : Yes.
+ * @retval 0 : False.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_IsFetchFinish(void *handle);
+
+
+/**
+ * @brief fetch firmware from remote server with specific timeout value.
+ * NOTE: If you want to download more faster, the bigger 'buf' should be given.
+ *
+ * @param [in] handle: specify the OTA module.
+ * @param [out] buf: specify the space for storing firmware data.
+ * @param [in] buf_len: specify the length of 'buf' in bytes.
+ * @param [in] timeout_s: specify the timeout value in second.
+ *
+ * @retval < 0 : Error occur..
+ * @retval 0 : No any data be downloaded in 'timeout_s' timeout period.
+ * @retval (0, len] : The length of data be downloaded in 'timeout_s' timeout period in bytes.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s);
+
+
+/**
+ * @brief Get OTA information specified by 'type'.
+ * By this interface, you can get information like state, size of file, md5 of file, etc.
+ *
+ * @param [in] handle: handle of the specific OTA
+ * @param [in] type: specify what information you want, see detail 'IOT_OTA_CmdType_t'
+ * @param [out] buf: specify buffer for data exchange
+ * @param [in] buf_len: specify the length of 'buf' in byte.
+ * @return
+ @verbatim
+ NOTE:
+ 1) When type is IOT_OTAG_FETCHED_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
+ 2) When type is IOT_OTAG_FILE_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
+ 3) When type is IOT_OTAG_MD5SUM, 'buf' should be a buffer, and 'buf_len' should be 33.
+ 4) When type is IOT_OTAG_VERSION, 'buf' should be a buffer, and 'buf_len' should be OTA_VERSION_LEN_MAX.
+ 5) When type is IOT_OTAG_CHECK_FIRMWARE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4.
+ 0, firmware is invalid; 1, firmware is valid.
+ @endverbatim
+ *
+ * @retval 0 : Successful.
+ * @retval < 0 : Failed, the value is error code.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len);
+
+
+/**
+ * @brief Get last error code.
+ *
+ * @param [in] handle: specify the OTA module.
+ *
+ * @return The error code.
+ * @see None.
+ */
+DLL_IOT_API int IOT_OTA_GetLastError(void *handle);
+
+/** @} */ /* end of api_ota */
+/** @} */ /* end of api */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __OTA_EXPORT_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_coap.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_coap.c
new file mode 100644
index 00000000..70ce80a6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_coap.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __OTA_COAP_C_H__
+#define __OTA_COAP_C_H__
+#if (OTA_SIGNAL_CHANNEL) == 2
+
+#include "iotx_ota_internal.h"
+
+/* OSC, OTA signal channel */
+
+/* Specify the maximum characters of version */
+#define OSC_COAP_URI_MAX_LEN (135) /* IoTx CoAP uri maximal length */
+
+
+typedef struct {
+ void *coap;
+ const char *product_key;
+ const char *device_name;
+ ota_cb_fpt cb;
+ void *context;
+} otacoap_Struct_t, *otacoap_Struct_pt;
+
+
+static otacoap_Struct_pt h_osc_coap = NULL;
+
+static void otacoap_response_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);
+ OTA_LOG_DEBUG("CoAP response code = %d", resp_code);
+ OTA_LOG_DEBUG("[CoAP msg_len=%d, msg=%s\r\n", len, p_payload);
+
+ if ((NULL != h_osc_coap) && (NULL != p_payload)) {
+ h_osc_coap->cb(h_osc_coap->context, (const char *)p_payload, (uint32_t)len);
+ }
+}
+
+
+/* Generate topic name according to @ota_topic_type, @product_key, @device_name */
+/* and then copy to @buf. */
+/* 0, successful; -1, failed */
+static int otacoap_GenTopicName(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_key,
+ const char *device_name)
+{
+ int ret;
+
+ ret = OTA_SNPRINTF(buf,
+ buf_len,
+ "/topic/ota/device/%s/%s/%s",
+ ota_topic_type,
+ product_key,
+ device_name);
+
+ if (ret >= buf_len) {
+ return -1;
+ }
+
+ if (ret < 0) {
+ OTA_LOG_ERROR("snprintf failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* report progress of OTA */
+static int otacoap_Publish(otacoap_Struct_pt handle, const char *topic_type, const char *msg)
+{
+ int ret;
+ char uri[IOTX_URI_MAX_LEN + 1] = {0};
+ iotx_message_t message;
+ message.p_payload = (unsigned char *)msg;
+ message.payload_len = (unsigned short)strlen(msg);
+ message.resp_callback = otacoap_response_handler;
+ message.msg_type = IOTX_MESSAGE_CON;
+ message.content_type = IOTX_CONTENT_TYPE_JSON;
+
+ /* topic name: /topic/ota/device/${topic_type}/${productKey}/${deviceName} */
+ ret = otacoap_GenTopicName(uri, OSC_COAP_URI_MAX_LEN, topic_type, handle->product_key, handle->device_name);
+ if (ret < 0) {
+ OTA_LOG_ERROR("generate topic name failed");
+ return -1;
+ }
+
+ if (IOTX_SUCCESS != (ret = IOT_CoAP_SendMessage(handle->coap, (char *)uri, &message))) {
+ OTA_LOG_ERROR("send CoAP msg failed%d", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+void *osc_Init(const char *product_key, const char *device_name, void *ch_signal, ota_cb_fpt cb, void *context)
+{
+ otacoap_Struct_pt h_osc = NULL;
+
+ if (NULL == (h_osc = OTA_MALLOC(sizeof(otacoap_Struct_t)))) {
+ OTA_LOG_ERROR("allocate for h_osc failed");
+ return NULL;
+ }
+
+ memset(h_osc, 0, sizeof(otacoap_Struct_t));
+
+ h_osc->coap = ch_signal;
+ h_osc->product_key = product_key;
+ h_osc->device_name = device_name;
+ h_osc->cb = cb;
+ h_osc->context = context;
+
+ h_osc_coap = h_osc;
+
+ return h_osc;
+}
+
+
+int osc_Deinit(void *handle)
+{
+ if (NULL != handle) {
+ OTA_FREE(handle);
+ }
+
+ return 0;
+}
+
+/* report progress of OTA */
+int osc_ReportProgress(void *handle, const char *msg)
+{
+ return otacoap_Publish(handle, "progress", msg);
+}
+
+
+/* report version of OTA firmware */
+int osc_ReportVersion(void *handle, const char *msg)
+{
+ static int state = 0;
+ int ret;
+
+ if (0 == state) { /* report version in initial state */
+ ret = otacoap_Publish(handle, "inform", msg);
+ if (0 != ret) {
+ return ret;
+ }
+ state = 1;
+ }
+
+ /* request new firmware after initial state */
+ return otacoap_Publish(handle, "request", msg);
+}
+
+#endif /* #if (OTA_SIGNAL_CHANNEL) == 2 */
+#endif
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_fetch.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_fetch.c
new file mode 100644
index 00000000..12dece8f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_fetch.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_ota_internal.h"
+
+/* ofc, OTA fetch channel */
+
+typedef struct {
+
+ const char *url;
+ httpclient_t http; /* http client */
+ httpclient_data_t http_data; /* http client data */
+
+} otahttp_Struct_t, *otahttp_Struct_pt;
+
+extern int httpclient_common(httpclient_t *client,
+ const char *url,
+ int port,
+ const char *ca_crt,
+ HTTPCLIENT_REQUEST_TYPE method,
+ uint32_t timeout_ms,
+ httpclient_data_t *client_data);
+
+void *ofc_Init(char *url)
+{
+ otahttp_Struct_pt h_odc;
+
+ if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t)))) {
+ OTA_LOG_ERROR("allocate for h_odc failed");
+ return NULL;
+ }
+
+ memset(h_odc, 0, sizeof(otahttp_Struct_t));
+
+ /* set http request-header parameter */
+ h_odc->http.header = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \
+ "Accept-Encoding: gzip, deflate\r\n";
+#if defined(SUPPORT_ITLS)
+ char *s_ptr = strstr(url, "://");
+ if (strlen("https") == (s_ptr - url) && (0 == strncmp(url, "https", strlen("https")))) {
+ strncpy(url + 1, url, strlen("http"));
+ url++;
+ }
+#endif
+ h_odc->url = url;
+
+ return h_odc;
+}
+
+
+extern const char *iotx_ca_crt;
+
+int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s)
+{
+ int diff;
+ otahttp_Struct_pt h_odc = (otahttp_Struct_pt)handle;
+
+ h_odc->http_data.response_buf = buf;
+ h_odc->http_data.response_buf_len = buf_len;
+ diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len;
+
+#if !defined(SUPPORT_TLS) || defined(SUPPORT_TCP)
+ if (0 != httpclient_common(&h_odc->http, h_odc->url, 80, 0, HTTPCLIENT_GET, timeout_s * 1000,
+ &h_odc->http_data)) {
+#else
+ if (0 != httpclient_common(&h_odc->http, h_odc->url, 443, iotx_ca_crt, HTTPCLIENT_GET, timeout_s * 1000,
+ &h_odc->http_data)) {
+#endif
+ OTA_LOG_ERROR("fetch firmware failed");
+ return -1;
+ }
+
+ return h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len - diff;
+}
+
+
+int ofc_Deinit(void *handle)
+{
+ if (NULL != handle) {
+ OTA_FREE(handle);
+ }
+
+ return 0;
+}
+
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_lib.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_lib.c
new file mode 100644
index 00000000..010f5929
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_lib.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_ota_internal.h"
+
+const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len)
+{
+ int length;
+ const char *val;
+ val = json_get_value_by_name((char *)json, json_len, (char *)key, &length, NULL);
+ if (NULL != val) {
+ *val_len = (uint32_t) length;
+ }
+ return val;
+}
+
+void *otalib_MD5Init(void)
+{
+ iot_md5_context *ctx = OTA_MALLOC(sizeof(iot_md5_context));
+ if (NULL == ctx) {
+ return NULL;
+ }
+
+ utils_md5_init(ctx);
+ utils_md5_starts(ctx);
+
+ return ctx;
+}
+
+void otalib_MD5Update(void *md5, const char *buf, size_t buf_len)
+{
+ utils_md5_update(md5, (unsigned char *)buf, buf_len);
+}
+
+void otalib_MD5Finalize(void *md5, char *output_str)
+{
+ int i;
+ unsigned char buf_out[16];
+ utils_md5_finish(md5, buf_out);
+
+ for (i = 0; i < 16; ++i) {
+ output_str[i * 2] = infra_hex2char(buf_out[i] >> 4);
+ output_str[i * 2 + 1] = infra_hex2char(buf_out[i]);
+ }
+ output_str[32] = '\0';
+}
+
+void otalib_MD5Deinit(void *md5)
+{
+ if (NULL != md5) {
+ OTA_FREE(md5);
+ }
+}
+
+void *otalib_Sha256Init(void)
+{
+ iot_sha256_context *ctx = OTA_MALLOC(sizeof(iot_sha256_context));
+ if (NULL == ctx) {
+ return NULL;
+ }
+
+ utils_sha256_init(ctx);
+ utils_sha256_starts(ctx);
+
+ return ctx;
+}
+
+void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len)
+{
+ utils_sha256_update(sha256, (unsigned char *)buf, buf_len);
+}
+
+void otalib_Sha256Finalize(void *sha256, char *output_str)
+{
+ int i;
+ unsigned char buf_out[32];
+ utils_sha256_finish(sha256, buf_out);
+
+ for (i = 0; i < 32; ++i) {
+ output_str[i * 2] = infra_hex2char(buf_out[i] >> 4);
+ output_str[i * 2 + 1] = infra_hex2char(buf_out[i]);
+ }
+ output_str[64] = '\0';
+}
+
+void otalib_Sha256Deinit(void *sha256)
+{
+ utils_sha256_free(sha256);
+ if (NULL != sha256) {
+ OTA_FREE(sha256);
+ }
+}
+/* Get the specific @key value, and copy to @dest */
+/* 0, successful; -1, failed */
+int otalib_GetFirmwareFixlenPara(const char *json_doc,
+ size_t json_doc_len,
+ const char *key,
+ char *dest,
+ size_t dest_len)
+{
+ const char *pvalue;
+ uint32_t val_len;
+
+ if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len))) {
+ OTA_LOG_ERROR("Not '%s' key in json doc of OTA", key);
+ return -1;
+ }
+
+ if (val_len > dest_len) {
+ OTA_LOG_ERROR("value length of the key is too long");
+ return -1;
+ }
+
+ memcpy(dest, pvalue, val_len);
+
+ return 0;
+}
+
+
+/* Get variant length parameter of firmware, and copy to @dest */
+/* 0, successful; -1, failed */
+int otalib_GetFirmwareVarlenPara(const char *json_doc,
+ size_t json_doc_len,
+ const char *key,
+ char **dest)
+{
+ const char *pvalue;
+ uint32_t val_len;
+
+ if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len))) {
+ OTA_LOG_ERROR("Not %s key in json doc of OTA", key);
+ return -1;
+ }
+
+ if (NULL == (*dest = OTA_MALLOC(val_len + 1))) {
+ OTA_LOG_ERROR("allocate for dest failed");
+ return -1;
+ }
+
+ memcpy(*dest, pvalue, val_len);
+ (*dest)[val_len] = '\0';
+
+ return 0;
+}
+
+int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5,
+ uint32_t *file_size)
+{
+#define OTA_FILESIZE_STR_LEN (16)
+ char file_size_str[OTA_FILESIZE_STR_LEN + 1];
+
+ /* get version */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "version", version)) {
+ OTA_LOG_ERROR("get value of version key failed");
+ return -1;
+ }
+
+ /* get URL */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) {
+ OTA_LOG_ERROR("get value of url key failed");
+ return -1;
+ }
+
+ /* get md5 */
+ if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "md5", md5, 32)) {
+ OTA_LOG_ERROR("get value of md5 key failed");
+ return -1;
+ }
+
+ /* get file size */
+ if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "size", file_size_str, OTA_FILESIZE_STR_LEN)) {
+ OTA_LOG_ERROR("get value of size key failed");
+ return -1;
+ }
+ file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
+ *file_size = atoi(file_size_str);
+
+ return 0;
+
+#undef OTA_FILESIZE_STR_LEN
+}
+
+int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign,
+ char **signMethod, char **url, char **getType)
+{
+#define OTA_FILESIZE_STR_LEN (16)
+ char file_size_str[OTA_FILESIZE_STR_LEN + 1];
+
+ /* get configId */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "configId", configId)) {
+ OTA_LOG_ERROR("get value of configId key failed");
+ return -1;
+ }
+
+ /* get configSize */
+ if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "configSize", file_size_str, OTA_FILESIZE_STR_LEN)) {
+ OTA_LOG_ERROR("get value of size key failed");
+ return -1;
+ }
+ file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
+ *configSize = atoi(file_size_str);
+
+ /* get sign */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "sign", sign)) {
+ OTA_LOG_ERROR("get value of sign key failed");
+ return -1;
+ }
+
+ /* get signMethod */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "signMethod", signMethod)) {
+ OTA_LOG_ERROR("get value of signMethod key failed");
+ return -1;
+ }
+
+ /* get url */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) {
+ OTA_LOG_ERROR("get value of url key failed");
+ return -1;
+ }
+
+ /* get getType */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "getType", getType)) {
+ OTA_LOG_ERROR("get value of getType key failed");
+ return -1;
+ }
+ return 0;
+
+#undef OTA_FILESIZE_STR_LEN
+}
+
+int otalib_GetFotaParams(const char *json_doc, uint32_t json_len, char **version, uint32_t *file_size, char **sign,
+ char **signMethod, char **url, char **digestsign)
+{
+#define OTA_FILESIZE_STR_LEN (16)
+ char file_size_str[OTA_FILESIZE_STR_LEN + 1];
+
+ /* get version */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "version", version)) {
+ OTA_LOG_ERROR("get value of version failed");
+ return -1;
+ }
+
+ /* get file size */
+ if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "size", file_size_str, OTA_FILESIZE_STR_LEN)) {
+ OTA_LOG_ERROR("get value of size key failed");
+ return -1;
+ }
+ file_size_str[OTA_FILESIZE_STR_LEN] = '\0';
+ *file_size = atoi(file_size_str);
+
+ /* get sign */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "sign", sign)) {
+ OTA_LOG_ERROR("get value of sign key failed");
+ return -1;
+ }
+
+ /* get signMethod */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "signMethod", signMethod)) {
+ OTA_LOG_ERROR("get value of signMethod key failed");
+ return -1;
+ }
+
+ /* get url */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) {
+ OTA_LOG_ERROR("get value of url key failed");
+ return -1;
+ }
+
+ /* get digestsign */
+ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "digestSign", digestsign)) {
+ OTA_LOG_ERROR("get value of digestSign key failed, maybe not security ota");
+ }
+
+ return 0;
+
+#undef OTA_FILESIZE_STR_LEN
+}
+
+/* Generate firmware information according to @id, @version */
+/* and then copy to @buf. */
+/* 0, successful; -1, failed */
+int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version)
+{
+ int ret;
+ ret = HAL_Snprintf(buf,
+ buf_len,
+ "{\"id\":%d,\"params\":{\"version\":\"%s\"}}",
+ id,
+ version);
+
+ if (ret < 0) {
+ OTA_LOG_ERROR("HAL_Snprintf failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Generate report information according to @id, @msg */
+/* and then copy to @buf. */
+/* 0, successful; -1, failed */
+int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail)
+{
+ int ret;
+ if (NULL == msg_detail) {
+ ret = HAL_Snprintf(buf,
+ buf_len,
+ "{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"\"}}",
+ id,
+ progress);
+ } else {
+ ret = HAL_Snprintf(buf,
+ buf_len,
+ "{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"%s\"}}",
+ id,
+ progress,
+ msg_detail);
+ }
+
+
+ if (ret < 0) {
+ OTA_LOG_ERROR("HAL_Snprintf failed");
+ return -1;
+ } else if (ret >= buf_len) {
+ OTA_LOG_ERROR("msg is too long");
+ return IOT_OTAE_STR_TOO_LONG;
+ }
+
+ return 0;
+}
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_mqtt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_mqtt.c
new file mode 100644
index 00000000..ceea75c7
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_mqtt.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __OTA_MQTT_C_H__
+#define __OTA_MQTT_C_H__
+
+#if (OTA_SIGNAL_CHANNEL) == 1
+
+#include "mqtt_api.h"
+#include "ota_api.h"
+#include "iotx_ota_internal.h"
+
+/* OSC, OTA signal channel */
+
+/* Specify the maximum characters of version */
+#define OTA_MQTT_TOPIC_LEN (128)
+
+typedef struct {
+ void *mqtt;
+ const char *product_key;
+ const char *device_name;
+ char topic_upgrade[OTA_MQTT_TOPIC_LEN];
+ char topic_request[OTA_MQTT_TOPIC_LEN];
+ char topic_config_get[OTA_MQTT_TOPIC_LEN];
+ char topic_config_push[OTA_MQTT_TOPIC_LEN];
+ ota_cb_fpt cb;
+ void *context;
+} otamqtt_Struct_t, *otamqtt_Struct_pt;
+
+
+/* Generate topic name according to @ota_topic_type, @product_key, @device_name */
+/* and then copy to @buf. */
+/* 0, successful; -1, failed */
+static int otamqtt_GenTopicName(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_key,
+ const char *device_name)
+{
+ int ret;
+
+ ret = HAL_Snprintf(buf,
+ buf_len,
+ "/ota/device/%s/%s/%s",
+ ota_topic_type,
+ product_key,
+ device_name);
+
+ if (ret >= buf_len) {
+ return -1;
+ }
+
+ if (ret < 0) {
+ OTA_LOG_ERROR("HAL_Snprintf failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* report progress of OTA */
+static int otamqtt_Publish(otamqtt_Struct_pt handle, const char *topic_type, int qos, const char *msg)
+{
+ int ret;
+ char topic_name[OTA_MQTT_TOPIC_LEN];
+ iotx_mqtt_topic_info_t topic_info;
+
+ memset(&topic_info, 0, sizeof(iotx_mqtt_topic_info_t));
+
+ if (0 == qos) {
+ topic_info.qos = IOTX_MQTT_QOS0;
+ } else {
+ topic_info.qos = IOTX_MQTT_QOS1;
+ }
+ topic_info.payload = (void *)msg;
+ topic_info.payload_len = strlen(msg);
+
+ /* inform OTA to topic: "/ota/device/progress/$(product_key)/$(device_name)" */
+ ret = otamqtt_GenTopicName(topic_name, OTA_MQTT_TOPIC_LEN, topic_type, handle->product_key, handle->device_name);
+ if (ret < 0) {
+ OTA_LOG_ERROR("generate topic name of info failed");
+ return -1;
+ }
+
+ ret = IOT_MQTT_Publish(handle->mqtt, topic_name, &topic_info);
+ if (ret < 0) {
+ OTA_LOG_ERROR("publish failed");
+ return IOT_OTAE_OSC_FAILED;
+ }
+
+ return 0;
+}
+
+static int otamqtt_publish_full_topic(otamqtt_Struct_pt handle, const char *topic_name,
+ iotx_mqtt_topic_info_pt topic_msg)
+{
+ if (IOT_MQTT_Publish(handle->mqtt, topic_name, topic_msg) < 0) {
+ OTA_LOG_ERROR("publish failed");
+ return IOT_OTAE_OSC_FAILED;
+ }
+
+ return 0;
+}
+
+
+/* decode JSON string to get firmware information, like firmware version, URL, file size, MD5. */
+/* return NONE */
+static void otamqtt_UpgrageCb(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
+{
+ otamqtt_Struct_pt handle = (otamqtt_Struct_pt) pcontext;
+ iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg;
+
+ OTA_LOG_DEBUG("topic=%.*s", topic_info->topic_len, topic_info->ptopic);
+ OTA_LOG_DEBUG("len=%u, topic_msg=%.*s", topic_info->payload_len, topic_info->payload_len, (char *)topic_info->payload);
+
+ if (IOTX_MQTT_EVENT_PUBLISH_RECEIVED != msg->event_type) {
+ return;
+ }
+
+ if (NULL != strstr(topic_info->ptopic, "/ota/device/request")) {
+ OTA_LOG_DEBUG("receive device request");
+ /*if(NULL != HAL_strnstr(topic_info->payload, topic_info->payload_len,
+ "url", strlen("url")))*/
+ if (NULL != strstr(topic_info->payload, "url")) {
+ OTA_LOG_INFO("get request reply for new version image");
+ if (NULL != handle->cb) {
+ handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_DEVICE_REQUEST);
+ }
+ }
+ } else if (NULL != strstr(topic_info->ptopic, "/ota/device/upgrade")) {
+ OTA_LOG_DEBUG("receive device upgrade");
+ if (NULL != handle->cb) {
+ handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE);
+ }
+ } else if (NULL != strstr(topic_info->ptopic, "/thing/config/get_reply")) {
+ OTA_LOG_DEBUG("receive config get_reply");
+ if (NULL != handle->cb) {
+ handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_CONFIG_GET);
+ }
+ } else if (NULL != strstr(topic_info->ptopic, "/thing/config/push")) {
+ OTA_LOG_DEBUG("receive config push");
+ if (NULL != handle->cb) {
+ if (0 != handle->cb(handle->context, topic_info->payload, topic_info->payload_len, IOTX_OTA_TOPIC_TYPE_CONFIG_PUSH)) {
+ /* fail, send fail response code:400 */
+ const char *pvalue;
+ uint32_t val_len;
+ char topic[OTA_MQTT_TOPIC_LEN] = {0};
+ char message[OTA_MQTT_TOPIC_LEN] = {0};
+ iotx_mqtt_topic_info_t message_info;
+
+ memset(&message_info, 0, sizeof(iotx_mqtt_topic_info_t));
+
+ pvalue = otalib_JsonValueOf(topic_info->payload, topic_info->payload_len, "id", &val_len);
+
+ HAL_Snprintf(topic,
+ OTA_MQTT_TOPIC_LEN,
+ "/sys/%s/%s/thing/config/push_reply",
+ handle->product_key,
+ handle->device_name);
+ HAL_Snprintf(message,
+ OTA_MQTT_TOPIC_LEN,
+ "\"id\":%.*s,\"code\":\"%d\",\"data\":{}",
+ val_len,
+ pvalue,
+ 400);
+ message_info.qos = IOTX_MQTT_QOS0;
+ message_info.payload = (void *)message;
+ message_info.payload_len = strlen(message);
+
+ if (IOT_MQTT_Publish(handle->mqtt, topic, &message_info) < 0) {
+ OTA_LOG_ERROR("publish failed");
+ }
+ }
+ }
+ }
+}
+
+void *osc_Init(const char *product_key, const char *device_name, void *ch_signal, ota_cb_fpt cb, void *context)
+{
+ int ret;
+ otamqtt_Struct_pt h_osc = NULL;
+
+ if (NULL == (h_osc = OTA_MALLOC(sizeof(otamqtt_Struct_t)))) {
+ OTA_LOG_ERROR("allocate for h_osc failed");
+ return NULL;
+ }
+
+ memset(h_osc, 0, sizeof(otamqtt_Struct_t));
+
+ /* subscribe the OTA topic: "/ota/device/request/$(product_key)/$(device_name)" */
+ ret = otamqtt_GenTopicName(h_osc->topic_request, OTA_MQTT_TOPIC_LEN, "request", product_key, device_name);
+ if (ret < 0) {
+ OTA_LOG_ERROR("generate topic name of request failed");
+ goto do_exit;
+ }
+
+ ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_request, IOTX_MQTT_QOS1, otamqtt_UpgrageCb, h_osc);
+ if (ret < 0) {
+ OTA_LOG_ERROR("mqtt subscribe failed");
+ goto do_exit;
+ }
+
+ /* subscribe the OTA topic: "/ota/device/upgrade/$(product_key)/$(device_name)" */
+ ret = otamqtt_GenTopicName(h_osc->topic_upgrade, OTA_MQTT_TOPIC_LEN, "upgrade", product_key, device_name);
+ if (ret < 0) {
+ OTA_LOG_ERROR("generate topic name of upgrade failed");
+ goto do_exit;
+ }
+
+ ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_upgrade, IOTX_MQTT_QOS1, otamqtt_UpgrageCb, h_osc);
+ if (ret < 0) {
+ OTA_LOG_ERROR("mqtt subscribe failed");
+ goto do_exit;
+ }
+
+ /* subscribe the OTA topic: "/sys/{productKey}/{deviceName}/thing/config/get_reply" */
+ ret = HAL_Snprintf(h_osc->topic_config_get,
+ OTA_MQTT_TOPIC_LEN,
+ "/sys/%s/%s/thing/config/get_reply",
+ product_key,
+ device_name);
+ if (ret < 0) {
+ OTA_LOG_ERROR("generate topic name of config get failed");
+ goto do_exit;
+ }
+
+ ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_config_get, IOTX_MQTT_QOS0, otamqtt_UpgrageCb, h_osc);
+ if (ret < 0) {
+ OTA_LOG_ERROR("mqtt subscribe failed");
+ goto do_exit;
+ }
+
+ /* subscribe the OTA topic: "/sys/{productKey}/{deviceName}/thing/config/push" */
+ ret = HAL_Snprintf(h_osc->topic_config_push,
+ OTA_MQTT_TOPIC_LEN,
+ "/sys/%s/%s/thing/config/push",
+ product_key,
+ device_name);
+ if (ret < 0) {
+ OTA_LOG_ERROR("generate topic name of config get failed");
+ goto do_exit;
+ }
+
+ ret = IOT_MQTT_Subscribe(ch_signal, h_osc->topic_config_push, IOTX_MQTT_QOS0, otamqtt_UpgrageCb, h_osc);
+ if (ret < 0) {
+ OTA_LOG_ERROR("mqtt subscribe failed");
+ goto do_exit;
+ }
+
+ h_osc->mqtt = ch_signal;
+ h_osc->product_key = product_key;
+ h_osc->device_name = device_name;
+ h_osc->cb = cb;
+ h_osc->context = context;
+
+ return h_osc;
+
+do_exit:
+ if (NULL != h_osc) {
+ OTA_FREE(h_osc);
+ }
+
+ return NULL;
+}
+
+int osc_Deinit(void *handle)
+{
+ if (NULL != handle) {
+ OTA_FREE(handle);
+ }
+
+ return 0;
+}
+
+/* report progress of OTA */
+int osc_ReportProgress(void *handle, const char *msg)
+{
+ return otamqtt_Publish(handle, "progress", 0, msg);
+}
+
+
+/* report version of OTA firmware */
+int osc_ReportVersion(void *handle, const char *msg)
+{
+ return otamqtt_Publish(handle, "inform", 1, msg);
+}
+
+/* request the OTA firmware pushed by user*/
+int osc_RequestImage(void *handle, const char *msg)
+{
+ return otamqtt_Publish(handle, "request", 1, msg);
+}
+
+/* request the config */
+int osc_RequestConfig(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg)
+{
+ return otamqtt_publish_full_topic(handle, topic_name, topic_msg);
+}
+
+#endif /* #if (OTA_SIGNAL_CHANNEL) == 1 */
+#endif /* #ifndef __OTA_MQTT_C_H__ */
+
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_wrapper.h
new file mode 100644
index 00000000..d5a0794b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/ota/ota_wrapper.h
@@ -0,0 +1,16 @@
+#ifndef _OTA_WRAPPER_H_
+#define _OTA_WRAPPER_H_
+
+#include "infra_types.h"
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+void HAL_Printf(const char *fmt, ...);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+
+int HAL_SetProductKey(char *product_key);
+int HAL_SetDeviceName(char *device_name);
+int HAL_SetDeviceSecret(char *device_secret);
+
+#endif
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/awss_dev_ap.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/awss_dev_ap.c
new file mode 100644
index 00000000..7d05cd4d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/awss_dev_ap.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#ifdef AWSS_SUPPORT_DEV_AP
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+#define AWSS_DEV_AP_WAIT_TIME_MAX_MS (2000)
+
+static void *g_awss_dev_ap_mutex = NULL;
+static char awss_dev_ap_switchap_done = 0;
+static char awss_dev_ap_switchap_resp_suc = 0;
+static char awss_dev_ap_ongoing = 0;
+
+static int awss_dev_ap_setup()
+{
+ char ssid[PLATFORM_MAX_SSID_LEN + 1] = {0};
+ char passwd[PLATFORM_MAX_PASSWD_LEN + 1] = {0};
+
+ do { /* reduce stack used */
+ char pk[OS_PRODUCT_KEY_LEN + 1] = {0};
+ char mac_str[OS_MAC_LEN + 1] = {0};
+
+ HAL_GetProductKey(pk);
+ os_wifi_get_mac_str(mac_str);
+ memmove(mac_str + 11, mac_str + 12, 2);
+ memmove(mac_str + 13, mac_str + 15, 2);
+ mac_str[15] = '\0';
+ HAL_Snprintf(ssid, PLATFORM_MAX_SSID_LEN, "adh_%s_%s", pk, &mac_str[9]);
+ } while (0);
+
+ awss_trace("ssid:%s\n", ssid);
+
+ return HAL_Awss_Open_Ap(ssid, passwd, 100, 0);
+}
+
+extern int awss_success_notify(void);
+int awss_dev_ap_start(void)
+{
+ int ret = -1;
+
+ if (g_awss_dev_ap_mutex || awss_dev_ap_ongoing) {
+ awss_trace("dev ap already running");
+ return -1;
+ }
+
+ if (g_awss_dev_ap_mutex == NULL)
+ g_awss_dev_ap_mutex = HAL_MutexCreate();
+ if (g_awss_dev_ap_mutex == NULL) {
+ awss_trace("awss dev ap start fail");
+ goto AWSS_DEV_AP_FAIL;
+ }
+
+ HAL_MutexLock(g_awss_dev_ap_mutex);
+
+ awss_dev_ap_ongoing = 1;
+ awss_dev_ap_switchap_done = 0;
+ awss_dev_ap_switchap_resp_suc = 0;
+
+ ret = awss_dev_ap_setup();
+ HAL_MutexUnlock(g_awss_dev_ap_mutex);
+ HAL_SleepMs(1000); /* wait for dev ap to work well */
+ HAL_MutexLock(g_awss_dev_ap_mutex);
+ if (awss_dev_ap_ongoing) {
+ awss_cmp_local_init(AWSS_LC_INIT_DEV_AP);
+ }
+ while (awss_dev_ap_ongoing) {
+ HAL_MutexUnlock(g_awss_dev_ap_mutex);
+ HAL_SleepMs(200);
+ HAL_MutexLock(g_awss_dev_ap_mutex);
+ if (awss_dev_ap_switchap_done)
+ break;
+ }
+ HAL_MutexUnlock(g_awss_dev_ap_mutex);
+
+ ret = awss_dev_ap_switchap_done == 0 ? -1 : 0;
+
+ if (awss_dev_ap_ongoing == 0) { /* interrupt by user */
+ HAL_SleepMs(1000);
+ return -1;
+ }
+
+ awss_dev_ap_ongoing = 0;
+ awss_success_notify();
+
+AWSS_DEV_AP_FAIL:
+ if (g_awss_dev_ap_mutex) {
+ HAL_MutexUnlock(g_awss_dev_ap_mutex);
+ HAL_MutexDestroy(g_awss_dev_ap_mutex);
+ }
+ g_awss_dev_ap_mutex = NULL;
+ return ret;
+}
+
+extern int HAL_Awss_Close_Ap(void);
+int awss_dev_ap_stop(void)
+{
+ if (awss_dev_ap_ongoing == 0)
+ return 0;
+
+ awss_dev_ap_ongoing = 0;
+
+ awss_trace("%s", __func__);
+
+ if (g_awss_dev_ap_mutex)
+ HAL_MutexLock(g_awss_dev_ap_mutex);
+
+ HAL_Awss_Close_Ap();
+
+ awss_cmp_local_deinit(1);
+
+ if (g_awss_dev_ap_mutex) {
+ HAL_MutexUnlock(g_awss_dev_ap_mutex);
+ HAL_MutexDestroy(g_awss_dev_ap_mutex);
+ g_awss_dev_ap_mutex = NULL;
+ }
+
+ awss_dev_ap_switchap_done = 0;
+ awss_dev_ap_switchap_resp_suc = 0;
+
+ awss_trace("%s exit", __func__);
+
+ return 0;
+}
+
+static int awss_dev_ap_switchap_resp(void *context, int result,
+ void *userdata, void *remote,
+ void *message) {
+ if (result == 2) { /* success */
+ awss_dev_ap_switchap_resp_suc = 1;
+ }
+ return 0;
+}
+
+int softap_decrypt_password(const char *cipher, const uint8_t *random, char *passwd)
+{
+ uint8_t cipher_hex[AES128_KEY_LEN] = {0};
+ uint8_t aes_key[SHA256_DIGEST_SIZE + 1] = {0};
+ uint8_t iv[AES128_KEY_LEN] = {0};
+ p_aes128_t aes_ctx = NULL;
+
+ /* get cipher hex */
+ utils_str_to_hex((char *)cipher, 32, cipher_hex, 16);
+
+ /* setup iv */
+ utils_str_to_hex((char *)random, RANDOM_MAX_LEN * 2, iv, RANDOM_MAX_LEN);
+
+ /* generate aes key */
+ utils_sha256(random, RANDOM_MAX_LEN * 2, aes_key);
+
+ /* aes decryption with cbc mode */
+ aes_ctx = HAL_Aes128_Init((const uint8_t *)aes_key, iv, PLATFORM_AES_DECRYPTION);
+ HAL_Aes128_Cbc_Decrypt(aes_ctx, cipher_hex, sizeof(cipher_hex) / AES128_KEY_LEN, passwd);
+ HAL_Aes128_Destroy(aes_ctx);
+
+ return 0;
+}
+
+int wifimgr_process_dev_ap_switchap_request(void *ctx, void *resource, void *remote, void *request)
+{
+#define AWSS_DEV_AP_SWITCHA_RSP_LEN (512)
+ char ssid[PLATFORM_MAX_SSID_LEN * 2 + 1] = {0}, passwd[PLATFORM_MAX_PASSWD_LEN + 1] = {0};
+ int str_len = 0, success = 1, len = 0;
+ char req_msg_id[MSG_REQ_ID_LEN] = {0};
+ char random[RANDOM_MAX_LEN + 1] = {0};
+ char *msg = NULL, *dev_info = NULL;
+ char *str = NULL, *buf = NULL;
+ char bssid[ETH_ALEN] = {0};
+ char ssid_found = 0;
+ uint8_t token[RANDOM_MAX_LEN + 1];
+ char token_found = 0;
+ uint8_t isRandomKey = 0;
+ const char *p_ranodm_str = NULL;
+ int ret = -1;
+
+ static char dev_ap_switchap_parsed = 0;
+ char topic[TOPIC_LEN_MAX] = {0};
+ uint16_t msgid = -1;
+ int result = 0;
+
+ if (0 == awss_dev_ap_ongoing) {
+ awss_trace("not in awss mode");
+ return -1;
+ }
+
+ if (dev_ap_switchap_parsed != 0)
+ goto DEV_AP_SWITCHAP_END;
+ dev_ap_switchap_parsed = 1;
+
+ AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_TIME_START);
+
+ msg = os_zalloc(AWSS_DEV_AP_SWITCHA_RSP_LEN);
+ if (msg == NULL) {
+ awss_trace("switchap resp alloc fail");
+ goto DEV_AP_SWITCHAP_END;
+ }
+ dev_info = os_zalloc(AWSS_DEV_AP_SWITCHA_RSP_LEN);
+ if (dev_info == NULL) {
+ awss_trace("switchap resp alloc fail");
+ goto DEV_AP_SWITCHAP_END;
+ }
+
+ buf = awss_cmp_get_coap_payload(request, &len);
+ str = json_get_value_by_name(buf, len, "id", &str_len, 0);
+ memcpy(req_msg_id, str, str_len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : str_len);
+ awss_trace("dev ap, len:%u, %s\r\n", len, buf);
+ buf = json_get_value_by_name(buf, len, "params", &len, 0);
+ if (buf == NULL) {
+ awss_trace("switchap req param fail");
+ goto DEV_AP_SWITCHAP_END;
+ }
+
+ do {
+ /* get security version */
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "security", &str_len, 0);
+ if (str && str_len == 3 && !memcmp("2.0", str, str_len)) {
+ awss_trace("security ver = %.*s\r\n", str_len, str);
+ isRandomKey = 1;
+ }
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "ssid", &str_len, 0);
+ awss_trace("ssid, len:%u, %s\r\n", str_len, str != NULL ? str : "NULL");
+ if (str && (str_len < PLATFORM_MAX_SSID_LEN)) {
+ memcpy(ssid, str, str_len);
+ ssid_found = 1;
+ }
+
+ if (!ssid_found) {
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "xssid", &str_len, 0);
+ if (str && (str_len < PLATFORM_MAX_SSID_LEN * 2 - 1)) {
+ uint8_t decoded[OS_MAX_SSID_LEN] = {0};
+ int len = str_len / 2;
+ memcpy(ssid, str, str_len);
+ utils_str_to_hex(ssid, str_len, decoded, OS_MAX_SSID_LEN);
+ memcpy(ssid, (const char *)decoded, len);
+ ssid[len] = '\0';
+ } else {
+ awss_trace("witchap req ssid err");
+ HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -1, "\"ssid error\"");
+ awss_event_post(IOTX_AWSS_CS_ERR);
+ success = 0;
+ break;
+ }
+ }
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "random", &str_len, 0);
+ if (str && str_len == RANDOM_MAX_LEN * 2) {
+ utils_str_to_hex(str, str_len, (unsigned char *)random, RANDOM_MAX_LEN);
+ p_ranodm_str = str;
+ } else {
+ HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -4, "\"random len error\"");
+ awss_event_post(IOTX_AWSS_CS_ERR);
+ success = 0;
+ break;
+ }
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "token", &str_len, 0);
+ if (str && str_len == RANDOM_MAX_LEN * 2) { /* token len equal to random len */
+ utils_str_to_hex(str, str_len, (unsigned char *)token, RANDOM_MAX_LEN);
+ token_found = 1;
+ }
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "bssid", &str_len, 0);
+ if (str) os_wifi_str2mac(str, bssid);
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "passwd", &str_len, 0);
+
+ if (str_len < (PLATFORM_MAX_PASSWD_LEN * 2) - 1) {
+ char encoded[PLATFORM_MAX_PASSWD_LEN * 2 + 1] = {0};
+ memcpy(encoded, str, str_len);
+ // aes_decrypt_string(encoded, passwd, str_len,
+ // 0, awss_get_encrypt_type(), 1, random); /* 64bytes=2x32bytes */
+ if (isRandomKey) {
+ if (softap_decrypt_password(encoded, (const uint8_t*)p_ranodm_str, passwd) < 0) {
+ success = 0;
+ awss_trace("randomkey passwd decode fail");
+ awss_event_post(IOTX_AWSS_PASSWD_ERR);
+ }
+ }
+ else {
+ if (aes_decrypt_string(encoded, passwd, str_len, 0, HAL_Awss_Get_Encrypt_Type(), 1, random) < 0) {
+ /* 64bytes=2x32bytes */
+ success = 0;
+ awss_trace("non-random passwd decode");
+ awss_event_post(IOTX_AWSS_PASSWD_ERR);
+ }
+ }
+ } else {
+ awss_trace("passwd len err");
+ HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -3, "\"passwd len error\"");
+ awss_event_post(IOTX_AWSS_PASSWD_ERR);
+ success = 0;
+ AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ }
+
+ if (success && is_utf8(passwd, strlen(passwd)) == 0) {
+ awss_trace("passwd content err");
+ HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -3 , "\"passwd content error\"");
+ awss_event_post(IOTX_AWSS_PASSWD_ERR);
+ success = 0;
+ AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ }
+ } while (0);
+
+ if (success == 1) {
+ if (token_found == 0) {
+ // no token found in switchap request, produce new token by dev itself
+ produce_random(aes_random, sizeof(aes_random));
+ } else {
+ // token found in switchap request, no need to produce dev token
+ awss_set_token((uint8_t *)token);
+ }
+ dev_info[0] = '{';
+ awss_build_dev_info(token_found == 1 ? AWSS_NOTIFY_TYPE_MAX : AWSS_NOTIFY_DEV_BIND_TOKEN, dev_info + 1,
+ AWSS_DEV_AP_SWITCHA_RSP_LEN - 1);
+ dev_info[strlen(dev_info)] = '}';
+ dev_info[AWSS_DEV_AP_SWITCHA_RSP_LEN - 1] = '\0';
+ snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, 200, dev_info);
+ }
+
+ awss_trace("Sending message to app: %s", msg);
+ awss_trace("switch to ap: '%s'", ssid);
+ awss_build_topic((const char *)TOPIC_AWSS_DEV_AP_SWITCHAP, topic, TOPIC_LEN_MAX);
+ result = awss_cmp_coap_send_resp(msg, strlen(msg), remote, topic, request, awss_dev_ap_switchap_resp, &msgid, 1);
+ // (void)result; /* remove complier warnings */
+ awss_trace("sending %s.", result == 0 ? "success" : "fail");
+
+ if (success == 1) {
+ awss_event_post(IOTX_AWSS_GOT_SSID_PASSWD);
+ }
+
+ do {
+ int wait_ms = AWSS_DEV_AP_WAIT_TIME_MAX_MS;
+ if (!success)
+ break;
+
+ while (wait_ms > 0 && awss_dev_ap_switchap_resp_suc == 0 && awss_dev_ap_ongoing) {
+ HAL_SleepMs(100);
+ wait_ms -= 100;
+ }
+ awss_cmp_coap_cancel_packet(msgid);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_START);
+ if (awss_dev_ap_ongoing == 0) { /* interrupt by user */
+ ret = -1;
+ goto DEV_AP_SWITCHAP_END;
+ }
+ HAL_Awss_Close_Ap();
+
+ ret = HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT_MS, ssid, passwd, 0, 0, (uint8_t *)bssid, 0);
+ if (ret == 0) {
+ AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ awss_dev_ap_switchap_done = 1;
+ AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ } else {
+ awss_dev_ap_setup();
+ }
+ awss_trace("connect '%s' %s\r\n", ssid, ret == 0 ? "success" : "fail");
+ } while (0);
+
+DEV_AP_SWITCHAP_END:
+ dev_ap_switchap_parsed = 0;
+ if (dev_info) HAL_Free(dev_info);
+ if (msg) HAL_Free(msg);
+ return ret;
+}
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/awss_dev_ap.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/awss_dev_ap.h
new file mode 100644
index 00000000..0250ca2b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/awss_dev_ap.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_DEV_AP_H__
+#define __AWSS_DEV_AP_H__
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+int awss_dev_ap_stop(void);
+int awss_dev_ap_start(void);
+int wifimgr_process_dev_ap_switchap_request(void *ctx, void *resource, void *remote, void *request);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/dev_ap_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/dev_ap_wrapper.h
new file mode 100644
index 00000000..a073de82
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/dev_ap/dev_ap_wrapper.h
@@ -0,0 +1,62 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+/*************************************** common hals ***************************************/
+int HAL_Timer_Stop(void *timer);
+int HAL_Timer_Delete(void *timer);
+void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
+int HAL_Timer_Start(void *timer, int ms);
+void HAL_SleepMs(uint32_t ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+uint64_t HAL_UptimeMs(void);
+void HAL_Free(void *ptr);
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+
+/*************************************** wifi provision frameworks hals ***************************************/
+/* frameworks/awss.c*/
+int HAL_Awss_Get_Timeout_Interval_Ms(void);
+int HAL_Sys_Net_Is_Ready();
+int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
+/* awss_crypt.c */
+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_Awss_Close_Monitor(void);
+void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
+void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
+int HAL_Awss_Get_Channelscan_Interval_Ms(void);
+/* zconfig_vendor_common.c */
+DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init(
+ _IN_ const uint8_t *key,
+ _IN_ const uint8_t *iv,
+ _IN_ AES_DIR_t dir);
+DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
+DLL_HAL_API int HAL_Aes128_Cbc_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t blockNum,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cfb_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t length,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Awss_Get_Encrypt_Type(void);
+DLL_HAL_API int HAL_Awss_Get_Conn_Encrypt_Type(void);
+/* os_misc.c */
+char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
+/* awss_main.c */
+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);
+/*************************************** dev-ap special hals ***************************************/
+int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide);
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aplist/awss_aplist.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aplist/awss_aplist.c
new file mode 100644
index 00000000..15f0367b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aplist/awss_aplist.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#ifdef AWSS_SUPPORT_APLIST
+
+#define CLR_APLIST_MONITOR_TIMEOUT_MS (24 * 60 *60 * 1000)
+/* storage to store apinfo */
+struct ap_info *zconfig_aplist = NULL;
+/* aplist num, less than MAX_APLIST_NUM */
+uint8_t zconfig_aplist_num = 0;
+
+static uint8_t clr_aplist = 0;
+static void *clr_aplist_timer = NULL;
+
+static void awss_clr_aplist_monitor()
+{
+ clr_aplist = 1;
+ HAL_Timer_Start(clr_aplist_timer, CLR_APLIST_MONITOR_TIMEOUT_MS);
+}
+
+int awss_is_ready_clr_aplist(void)
+{
+ return clr_aplist;
+}
+
+int awss_clear_aplist(void)
+{
+ memset(zconfig_aplist, 0, sizeof(struct ap_info) * MAX_APLIST_NUM);
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ memset(adha_aplist, 0, sizeof(*adha_aplist));
+#endif
+ zconfig_aplist_num = 0;
+ clr_aplist = 0;
+
+ return 0;
+}
+
+int awss_open_aplist_monitor(void)
+{
+ if (clr_aplist_timer == NULL)
+ clr_aplist_timer = HAL_Timer_Create("clr_aplist", (void (*)(void *))awss_clr_aplist_monitor, (void *)NULL);
+ if (clr_aplist_timer == NULL)
+ return -1;
+
+ HAL_Timer_Stop(clr_aplist_timer);
+ HAL_Timer_Start(clr_aplist_timer, CLR_APLIST_MONITOR_TIMEOUT_MS);
+ return 0;
+}
+
+int awss_close_aplist_monitor(void)
+{
+ if (clr_aplist_timer == NULL)
+ return 0;
+ awss_stop_timer(clr_aplist_timer);
+ clr_aplist_timer = NULL;
+ return 0;
+}
+
+int awss_init_ieee80211_aplist(void)
+{
+ if (zconfig_aplist)
+ return 0;
+ zconfig_aplist = (struct ap_info *)os_zalloc(sizeof(struct ap_info) * MAX_APLIST_NUM);
+ if (zconfig_aplist == NULL)
+ return -1;
+ zconfig_aplist_num = 0;
+ return 0;
+}
+
+int awss_deinit_ieee80211_aplist(void)
+{
+ if (zconfig_aplist == NULL)
+ return 0;
+ HAL_Free(zconfig_aplist);
+ zconfig_aplist = NULL;
+ zconfig_aplist_num = 0;
+ return 0;
+}
+
+struct ap_info *zconfig_get_apinfo(uint8_t *mac)
+{
+ int i;
+
+ for (i = 1; i < zconfig_aplist_num; i++) {
+ if (!memcmp(zconfig_aplist[i].mac, mac, ETH_ALEN))
+ return &zconfig_aplist[i];
+ }
+
+ return NULL;
+}
+
+struct ap_info *zconfig_get_apinfo_by_ssid(uint8_t *ssid)
+{
+ int i;
+
+ for (i = 1; i < zconfig_aplist_num; i ++) {
+ if (!strcmp((char *)zconfig_aplist[i].ssid, (char *)ssid))
+ return &zconfig_aplist[i];
+ }
+
+ return NULL;
+}
+
+/* 通过ssid前缀 */
+struct ap_info *zconfig_get_apinfo_by_ssid_prefix(uint8_t *ssid_prefix)
+{
+ int i;
+ int len = strlen((const char *)ssid_prefix);
+ if (!len)
+ return NULL;
+
+ for (i = 1; i < zconfig_aplist_num; i++) {
+ if (!strncmp((char *)zconfig_aplist[i].ssid, (char *)ssid_prefix, len)) {
+ /* TODO: first match or best match??? */
+ return &zconfig_aplist[i];/* first match */
+ }
+ }
+
+ return NULL;
+}
+
+int str_end_with(const char *str, const char *suffix)
+{
+ int lenstr, lensuffix;
+ if (!str || !suffix)
+ return 0;
+ lenstr = strlen(str);
+ lensuffix = strlen(suffix);
+ if (lensuffix > lenstr)
+ return 0;
+ return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
+}
+
+/* 通过ssid后缀 */
+struct ap_info *zconfig_get_apinfo_by_ssid_suffix(uint8_t *ssid_suffix)
+{
+ int i;
+ int len = strlen((const char *)ssid_suffix);
+ if (!len)
+ return NULL;
+
+ for (i = 1; i < zconfig_aplist_num; i++) {
+ if (str_end_with((char *)zconfig_aplist[i].ssid, (char *)ssid_suffix)) {
+ /* TODO: first match or best match??? */
+ return &zconfig_aplist[i];/* first match */
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * save apinfo
+ *
+ * @ssid: [IN] ap ssid
+ * @bssid: [IN] ap bssid
+ * @channel: [IN] ap channel
+ * @auth: [IN] optional, ap auth mode, like OPEN/WEP/WPA/WPA2/WPAWPA2
+ * @encry: [IN], ap encryption mode, i.e. NONE/WEP/TKIP/AES/TKIP-AES
+ *
+ * Note:
+ * 1) if ap num exceed zconfig_aplist[], always save at [0]
+ * but why...I forgot...
+ * 2) always update channel if channel != 0
+ * 3) if chn is locked, save ssid to zc_ssid, because zc_ssid
+ * can be used for ssid-auto-completion
+ * Return:
+ * 0/success, -1/invalid params(empty ssid/bssid)
+ */
+
+int awss_save_apinfo(uint8_t *ssid, uint8_t* bssid, uint8_t channel, uint8_t auth,
+ uint8_t pairwise_cipher, uint8_t group_cipher, signed char rssi)
+{
+ int i;
+
+ /* ssid, bssid cannot empty, channel can be 0, auth/encry can be invalid */
+ if (!(ssid && bssid))
+ return -1;
+
+ /* sanity check */
+ if (channel > ZC_MAX_CHANNEL || channel < ZC_MIN_CHANNEL)
+ channel = 0;
+ else
+ zconfig_add_active_channel(channel);
+
+ if (auth > ZC_AUTH_TYPE_MAX)
+ auth = ZC_AUTH_TYPE_INVALID;
+
+ if (pairwise_cipher > ZC_ENC_TYPE_MAX)
+ pairwise_cipher = ZC_ENC_TYPE_INVALID;
+ if (group_cipher > ZC_ENC_TYPE_MAX)
+ group_cipher = ZC_ENC_TYPE_INVALID;
+
+ /* FIXME: */
+ if (pairwise_cipher == ZC_ENC_TYPE_TKIPAES)
+ pairwise_cipher = ZC_ENC_TYPE_AES; /* tods */
+
+ /*
+ * start from zconfig_aplist[1], leave [0] for temp use
+ * if zconfig_aplist[] is full, always replace [0]
+ */
+ if (!zconfig_aplist_num) {
+ zconfig_aplist_num = 1;
+ }
+
+ for (i = 1; i < zconfig_aplist_num; i++) {
+ if(!strncmp(zconfig_aplist[i].ssid, (char *)ssid, ZC_MAX_SSID_LEN)
+ && !memcmp(zconfig_aplist[i].mac, bssid, ETH_ALEN)) {
+ /* FIXME: useless? */
+ /* found the same bss */
+ if (!zconfig_aplist[i].channel)
+ zconfig_aplist[i].channel = channel;
+ if (zconfig_aplist[i].auth == ZC_AUTH_TYPE_INVALID)
+ zconfig_aplist[i].auth = auth;
+ if (zconfig_aplist[i].encry[0] == ZC_ENC_TYPE_INVALID)
+ zconfig_aplist[i].encry[0] = group_cipher;
+ if (zconfig_aplist[i].encry[1] == ZC_ENC_TYPE_INVALID)
+ zconfig_aplist[i].encry[1] = pairwise_cipher;
+
+ return 0;/* duplicated ssid */
+ }
+ }
+
+ if (i < MAX_APLIST_NUM) {
+ zconfig_aplist_num ++;
+ } else {
+ i = 0; /* [0] for temp use, always replace [0] */
+ }
+
+ strncpy((char *)&zconfig_aplist[i].ssid, (const char *)&ssid[0], ZC_MAX_SSID_LEN - 1);
+ memcpy(&zconfig_aplist[i].mac, bssid, ETH_ALEN);
+ zconfig_aplist[i].auth = auth;
+ zconfig_aplist[i].rssi = rssi;
+ zconfig_aplist[i].channel = channel;
+ zconfig_aplist[i].encry[0] = group_cipher;
+ zconfig_aplist[i].encry[1] = pairwise_cipher;
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ do {
+ char save_adha = 0;
+#ifdef AWSS_SUPPORT_ADHA
+ if (!strcmp((void *)ssid, zc_adha_ssid))
+ save_adha = 1;
+#endif
+#ifdef AWSS_SUPPORT_AHA
+ if (!strcmp((void *)ssid, zc_default_ssid))
+ save_adha = 1;
+#endif
+ if (save_adha) {
+ if (adha_aplist->cnt < MAX_APLIST_NUM)
+ adha_aplist->aplist[adha_aplist->cnt ++] = i;
+ }
+ } while(0);
+#endif
+
+ do {
+ char adha = 0;
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ adha = adha_aplist->cnt;
+#endif
+ awss_debug("[%d] ssid:%s, mac:%02x%02x%02x%02x%02x%02x, chn:%d, rssi:%d, adha:%d\r\n",
+ i, ssid, bssid[0], bssid[1], bssid[2],
+ bssid[3], bssid[4], bssid[5], channel,
+ rssi > 0 ? rssi - 256 : rssi, adha);
+ } while (0);
+ /*
+ * if chn already locked(zc_bssid set),
+ * copy ssid to zc_ssid for ssid-auto-completiont
+ */
+ if (!memcmp(zc_bssid, bssid, ETH_ALEN) && ssid[0] != '\0') {
+ strncpy((char *)zc_ssid, (char const *)ssid, ZC_MAX_SSID_LEN - 1);
+ }
+
+ return 0;
+}
+
+/*
+ * [IN] ssid or bssid
+ * [OUT] auth, encry, channel
+ */
+int awss_get_auth_info(uint8_t *ssid, uint8_t *bssid, uint8_t *auth,
+ uint8_t *encry, uint8_t *channel)
+{
+ uint8_t *valid_bssid = NULL;
+ struct ap_info *ap_info = NULL;
+
+ /* sanity check */
+ if (!bssid || !memcmp(bssid, zero_mac, ETH_ALEN)) {
+ valid_bssid = NULL;
+ } else {
+ valid_bssid = bssid;
+ }
+
+ /* use mac or ssid to search apinfo */
+ if (valid_bssid) {
+ ap_info = zconfig_get_apinfo(valid_bssid);
+ } else {
+ ap_info = zconfig_get_apinfo_by_ssid(ssid);
+ }
+
+ if (!ap_info)
+ return 0;
+
+ if (auth)
+ *auth = ap_info->auth;
+ if (encry)
+ *encry = ap_info->encry[1]; /* tods side */
+ if (!valid_bssid && bssid)
+ memcpy(bssid, ap_info->mac, ETH_ALEN);
+ if (channel)
+ *channel = ap_info->channel;
+
+ return 1;
+
+}
+
+void aws_try_adjust_chan(void)
+{
+ struct ap_info *ap = NULL;
+ char ssid[ZC_MAX_SSID_LEN] = {0};
+ ap = zconfig_get_apinfo(zc_bssid);
+ if (ap == NULL)
+ return;
+ if (zconfig_get_lock_chn() == ap->channel)
+ return;
+ if (!zconfig_is_valid_channel(ap->channel))
+ return;
+ strncpy(ssid, (const char *)ap->ssid, ZC_MAX_SSID_LEN - 1);
+
+#ifdef AWSS_SUPPORT_AHA
+ if (strlen(ssid) == strlen(zc_default_ssid) &&
+ strncmp(ap->ssid, zc_default_ssid, strlen(zc_default_ssid)) == 0)
+ return;
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ if (strlen(ssid) == strlen(zc_adha_ssid) &&
+ strncmp(ap->ssid, zc_adha_ssid, strlen(zc_adha_ssid)) == 0)
+ return;
+#endif
+
+ aws_set_dst_chan(ap->channel);
+ aws_switch_channel();
+}
+
+int awss_ieee80211_aplist_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
+{
+ uint8_t ssid[ZC_MAX_SSID_LEN] = {0}, bssid[ETH_ALEN] = {0};
+ uint8_t auth, pairwise_cipher, group_cipher;
+ struct ieee80211_hdr *hdr;
+ int fc, ret, channel;
+
+ if (mgmt_header == NULL)
+ return ALINK_INVALID;
+
+ hdr = (struct ieee80211_hdr *)mgmt_header;
+ fc = hdr->frame_control;
+
+ /*
+ * just for save ap in aplist for ssid amend.
+ */
+ if (!ieee80211_is_beacon(fc) && !ieee80211_is_probe_resp(fc))
+ return ALINK_INVALID;
+
+ ret = ieee80211_get_bssid(mgmt_header, bssid);
+ if (ret < 0)
+ return ALINK_INVALID;
+
+ ret = ieee80211_get_ssid(mgmt_header, len, ssid);
+ if (ret < 0)
+ return ALINK_INVALID;
+
+ /*
+ * skip all the adha and aha
+ */
+#ifdef AWSS_SUPPORT_AHA
+ if (strcmp((const char *)ssid, zc_default_ssid) == 0)
+ return ALINK_INVALID;
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ if (strcmp((const char *)ssid, zc_adha_ssid) == 0)
+ return ALINK_INVALID;
+#endif
+
+ channel = cfg80211_get_bss_channel(mgmt_header, len);
+ rssi = rssi > 0 ? rssi - 256 : rssi;
+
+ cfg80211_get_cipher_info(mgmt_header, len, &auth,
+ &pairwise_cipher, &group_cipher);
+ awss_save_apinfo(ssid, bssid, channel, auth,
+ pairwise_cipher, group_cipher, rssi);
+ return ALINK_INVALID;
+}
+
+#endif
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aplist/awss_aplist.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aplist/awss_aplist.h
new file mode 100644
index 00000000..8ec3927b
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aplist/awss_aplist.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_APLIST_H__
+#define __AWSS_APLIST_H__
+
+#include
+#include "os.h"
+#include "zconfig_protocol.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+#ifdef AWSS_SUPPORT_APLIST
+struct ap_info {
+ uint8_t auth;
+ uint8_t channel;
+ uint8_t encry[2];
+ uint8_t mac[ETH_ALEN];
+ char ssid[ZC_MAX_SSID_LEN];
+ signed char rssi;
+};
+
+void aws_try_adjust_chan(void);
+
+int awss_clear_aplist(void);
+int awss_is_ready_clr_aplist(void);
+int awss_open_aplist_monitor(void);
+int awss_close_aplist_monitor(void);
+int awss_init_ieee80211_aplist(void);
+int awss_deinit_ieee80211_aplist(void);
+int awss_get_auth_info(uint8_t *ssid, uint8_t *bssid, uint8_t *auth,
+ uint8_t *encry, uint8_t *channel);
+int awss_ieee80211_aplist_process(uint8_t *mgmt_header, int len, int link_type,
+ struct parser_res *res, signed char rssi);
+int awss_save_apinfo(uint8_t *ssid, uint8_t* bssid, uint8_t channel, uint8_t auth,
+ uint8_t pairwise_cipher, uint8_t group_cipher, signed char rssi);
+
+/* storage to store apinfo */
+extern struct ap_info *zconfig_aplist;
+/* aplist num, less than MAX_APLIST_NUM */
+extern uint8_t zconfig_aplist_num;
+#endif
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aws_lib.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aws_lib.h
new file mode 100644
index 00000000..a713a8bb
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/aws_lib.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWS_LIB_H__
+#define __AWS_LIB_H__
+
+#include
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+/* auth type */
+enum AWS_AUTH_TYPE {
+ AWS_AUTH_TYPE_OPEN,
+ AWS_AUTH_TYPE_SHARED,
+ AWS_AUTH_TYPE_WPAPSK,
+ AWS_AUTH_TYPE_WPA8021X,
+ AWS_AUTH_TYPE_WPA2PSK,
+ AWS_AUTH_TYPE_WPA28021X,
+ AWS_AUTH_TYPE_WPAPSKWPA2PSK,
+ AWS_AUTH_TYPE_MAX = AWS_AUTH_TYPE_WPAPSKWPA2PSK,
+ AWS_AUTH_TYPE_INVALID = 0xff,
+};
+
+/* encry type */
+enum AWS_ENC_TYPE {
+ AWS_ENC_TYPE_NONE,
+ AWS_ENC_TYPE_WEP,
+ AWS_ENC_TYPE_TKIP,
+ AWS_ENC_TYPE_AES,
+ AWS_ENC_TYPE_TKIPAES,
+ AWS_ENC_TYPE_MAX = AWS_ENC_TYPE_TKIPAES,
+ AWS_ENC_TYPE_INVALID = 0xff,
+};
+
+/* link type */
+enum AWS_LINK_TYPE {
+ AWS_LINK_TYPE_NONE,
+ AWS_LINK_TYPE_PRISM,
+ AWS_LINK_TYPE_80211_RADIO,
+ AWS_LINK_TYPE_80211_RADIO_AVS
+};
+
+#if 0
+/* 将monitor模式下抓到的包传入该函数进行处理
+ * 参数:
+ * buf: frame buffer
+ * length: frame len
+ * link_type: see enum AWS_LINK_TYPE
+ * with_fcs: frame include 80211 fcs field, the tailing 4bytes
+ *
+ * 说明:
+ * 适配前执行以下命令, 检查link_type和with_fcs参数
+ * a) iwconfig wlan0 mode monitor #进入monitor模式
+ * b) iwconfig wlan0 channel 6 #切换到信道6(以路由器信道为准)
+ * c) tcpdump -i wlan0 -s0 -w file.pacp #抓包保存文件
+ * d) 用wireshark或者omnipeek打开,检查包头格式,及包尾是否包含FCS 4字节
+ *
+ * 常见的包头类型为:
+ * 无额外的包头:AWS_LINK_TYPE_NONE
+ * radio header: hdr_len = *(uint16_t *)(buf + 2)
+ * avs header: hdr_len = *(unsigned long *)(buf + 4)
+ * prism header: hdr_len = 144
+ */
+int aws_80211_frame_handler(char *buf, int length,
+ int link_type, int with_fcs);
+#endif
+
+/* 启动一键配网服务, 该函数会block,直到配网成功或者超时退出,
+ * 超时时间由aws_timeout_period_ms设置
+ * 参数:
+ * pk: product key
+ * dn: device name
+ * ds: device security
+ * ps: product security
+ */
+void aws_start(char *pk, char *dn, char *ds, char *ps);
+/* {该函数大致流程如下:
+ * init();
+ * platform_monitor_open();
+ * aws_main_thread_func();
+ * platform_monitor_close();
+ * destroy();
+ * }
+
+ * aws_start返回后,调用该函数,获取ssid和passwd等信息
+ * aws成功时,ssid & passwd一定会返回非NULL字符串, 但bssid和auth, encry, channel
+ * 有可能会返回NULL或者INVALID值(取决于是否能在wifi列表里搜索命中)
+ * aws失败超时后,该函数会返回0, 且所有参数为NULL或INVALID VALUE
+ *
+ * auth defined by enum AWS_AUTH_TYPE
+ * encry defined by enum AWS_ENC_TYPE
+ *
+ * 返回值:1--成功,0--失败
+ */
+int aws_get_ssid_passwd(char ssid[32 + 1], char passwd[64 + 1], uint8_t bssid[6],
+ char *auth, char *encry, uint8_t *channel);
+
+/* 配网结束(成功或失败)后,调用该函数,释放配网库占用的资源 */
+void aws_destroy(void);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss.c
new file mode 100644
index 00000000..117df17a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#define AWSS_PRESS_TIMEOUT_MS (60000)
+
+extern int switch_ap_done;
+static uint8_t awss_stopped = 1;
+static uint8_t g_user_press = 0;
+static void *press_timer = NULL;
+
+static void awss_press_timeout(void);
+
+int awss_success_notify(void)
+{
+ g_user_press = 0;
+ awss_press_timeout();
+
+ awss_cmp_local_init(AWSS_LC_INIT_SUC);
+ awss_suc_notify_stop();
+ awss_suc_notify();
+ awss_start_connectap_monitor();
+ AWSS_DISP_STATIS();
+ return 0;
+}
+
+int awss_start(void)
+{
+ if (awss_stopped == 0) {
+ awss_debug("awss already running\n");
+ return -1;
+ }
+
+ awss_stopped = 0;
+ awss_event_post(IOTX_AWSS_START);
+ produce_random(aes_random, sizeof(aes_random));
+
+ do {
+ __awss_start();
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ do {
+ char ssid[PLATFORM_MAX_SSID_LEN + 1] = {0};
+#ifdef AWSS_SUPPORT_ADHA
+ while (1) {
+ memset(ssid, 0, sizeof(ssid));
+ HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
+ awss_debug("start, ssid:%s, strlen:%lu\n", ssid, strlen(ssid));
+ if (strlen(ssid) > 0 && strcmp(ssid, ADHA_SSID)) { /* not adha AP */
+ break;
+ }
+
+ if (HAL_Sys_Net_Is_Ready()) { /* skip the adha failed */
+ awss_cmp_local_init(AWSS_LC_INIT_ROUTER);
+
+ awss_open_adha_monitor();
+ while (!awss_is_ready_switch_next_adha()) {
+ if (awss_stopped) {
+ break;
+ }
+ HAL_SleepMs(50);
+ }
+ awss_cmp_local_deinit(0);
+ }
+
+ if (switch_ap_done || awss_stopped) {
+ break;
+ }
+ __awss_start();
+ }
+#endif
+ if (awss_stopped) {
+ break;
+ }
+
+ if (switch_ap_done) {
+ break;
+ }
+
+ HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
+ if (strlen(ssid) > 0 && strcmp(ssid, DEFAULT_SSID)) { /* not AHA */
+ break;
+ }
+
+ if (HAL_Sys_Net_Is_Ready()) {
+ char dest_ap = 0;
+ awss_open_aha_monitor();
+
+ awss_cmp_local_init(AWSS_LC_INIT_PAP);
+ while (!awss_aha_monitor_is_timeout()) {
+ memset(ssid, 0, sizeof(ssid));
+ HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
+ if (HAL_Sys_Net_Is_Ready() &&
+ strlen(ssid) > 0 && strcmp(ssid, DEFAULT_SSID)) { /* not AHA */
+ dest_ap = 1;
+ break;
+ }
+ if (awss_stopped) {
+ break;
+ }
+ HAL_SleepMs(50);
+ }
+
+ awss_cmp_local_deinit(0);
+
+ if (switch_ap_done || awss_stopped) {
+ break;
+ }
+
+ if (dest_ap == 1) {
+ break;
+ }
+ }
+ awss_event_post(IOTX_AWSS_ENABLE_TIMEOUT);
+ __awss_start();
+ } while (1);
+#endif
+ if (awss_stopped) {
+ break;
+ }
+
+ if (HAL_Sys_Net_Is_Ready()) {
+ break;
+ }
+ } while (1);
+
+ if (awss_stopped) {
+ return -1;
+ }
+
+#ifdef AWSS_SUPPORT_AHA
+ awss_close_aha_monitor();
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ awss_close_adha_monitor();
+#endif
+
+ awss_success_notify();
+ awss_stopped = 1;
+
+ return 0;
+}
+
+int awss_stop(void)
+{
+ awss_stopped = 1;
+#ifdef AWSS_SUPPORT_AHA
+ awss_close_aha_monitor();
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ awss_close_adha_monitor();
+#endif
+ awss_stop_connectap_monitor();
+ g_user_press = 0;
+ awss_press_timeout();
+
+ __awss_stop();
+
+ return 0;
+}
+
+static void awss_press_timeout(void)
+{
+ awss_stop_timer(press_timer);
+ press_timer = NULL;
+ if (g_user_press) {
+ awss_event_post(IOTX_AWSS_ENABLE_TIMEOUT);
+ }
+ g_user_press = 0;
+}
+
+int awss_config_press(void)
+{
+ int timeout = HAL_Awss_Get_Timeout_Interval_Ms();
+
+ awss_trace("enable awss\r\n");
+
+ g_user_press = 1;
+
+ awss_event_post(IOTX_AWSS_ENABLE);
+
+ if (press_timer == NULL) {
+ press_timer = HAL_Timer_Create("press", (void (*)(void *))awss_press_timeout, NULL);
+ }
+ if (press_timer == NULL) {
+ return -1;
+ }
+
+ HAL_Timer_Stop(press_timer);
+
+ if (timeout < AWSS_PRESS_TIMEOUT_MS) {
+ timeout = AWSS_PRESS_TIMEOUT_MS;
+ }
+ HAL_Timer_Start(press_timer, timeout);
+
+ return 0;
+}
+
+uint8_t awss_get_config_press(void)
+{
+ return g_user_press;
+}
+
+void awss_set_config_press(uint8_t press)
+{
+ g_user_press = press;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_main.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_main.c
new file mode 100644
index 00000000..e1fc1ac4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_main.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+char awss_finished = 2;
+char awss_stop_connecting = 0;
+int __awss_start(void)
+{
+ char ssid[OS_MAX_SSID_LEN + 1] = {0}, passwd[OS_MAX_PASSWD_LEN + 1] = {0};
+ enum AWSS_AUTH_TYPE auth = AWSS_AUTH_TYPE_INVALID;
+ enum AWSS_ENC_TYPE encry = AWSS_ENC_TYPE_INVALID;
+ uint8_t bssid[OS_ETH_ALEN] = {0};
+ uint8_t channel = 0;
+ int ret;
+
+ awss_stop_connecting = 0;
+ awss_finished = 0;
+ /* these params is useless, keep it for compatible reason */
+ aws_start(NULL, NULL, NULL, NULL);
+
+ ret = aws_get_ssid_passwd(&ssid[0], &passwd[0], &bssid[0],
+ (char *)&auth, (char *)&encry, &channel);
+ if (!ret) {
+ awss_warn("awss timeout!");
+ }
+
+ if (awss_stop_connecting) {
+ awss_finished = 1;
+ return -1;
+ }
+
+ aws_destroy();
+
+ do {
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ char awss_notify_needed = 1;
+ int adha = 0;
+#endif
+
+ if (awss_stop_connecting || strlen(ssid) == 0) {
+ break;
+ }
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ if ((adha = strcmp(ssid, ADHA_SSID)) == 0 || strcmp(ssid, DEFAULT_SSID) == 0) {
+ awss_notify_needed = 0;
+ awss_event_post(adha != 0 ? IOTX_AWSS_CONNECT_AHA : IOTX_AWSS_CONNECT_ADHA);
+ } else
+#endif
+ {
+ awss_event_post(IOTX_AWSS_CONNECT_ROUTER);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_START);
+ }
+
+ ret = HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT_MS, ssid, passwd,
+ auth, encry, bssid, channel);
+ if (!ret) {
+ awss_debug("awss connect ssid:%s success", ssid);
+ awss_event_post(IOTX_AWSS_GOT_IP);
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ if (awss_notify_needed == 0) {
+ awss_dev_bind_notify_stop();
+ awss_suc_notify_stop();
+ awss_cmp_local_init(adha == 0 ? AWSS_LC_INIT_ROUTER : AWSS_LC_INIT_PAP);
+ awss_devinfo_notify();
+ if (adha == 0) {
+ AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ }
+ awss_event_post(IOTX_AWSS_SETUP_NOTIFY);
+ } else
+#endif
+ {
+ AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ awss_devinfo_notify_stop();
+ produce_random(aes_random, sizeof(aes_random));
+ }
+ } else {
+ awss_debug("awss connect ssid:%s fail", ssid);
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ if (awss_notify_needed == 0) {
+ awss_event_post(adha != 0 ? IOTX_AWSS_CONNECT_AHA_FAIL : IOTX_AWSS_CONNECT_ADHA_FAIL);
+ } else
+#endif
+ {
+ awss_event_post(IOTX_AWSS_CONNECT_ROUTER_FAIL);
+ }
+ }
+ } while (0);
+
+ AWSS_DISP_STATIS();
+ awss_finished = 1;
+ return 0;
+}
+
+int __awss_stop(void)
+{
+ awss_stop_connecting = 1;
+ aws_destroy();
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ awss_devinfo_notify_stop();
+#endif
+ awss_suc_notify_stop();
+#ifndef AWSS_DISABLE_REGISTRAR
+ awss_registrar_deinit();
+#endif
+ if (awss_finished < 2) {
+ awss_cmp_local_deinit(1);
+ } else {
+ awss_cmp_local_deinit(0);
+ }
+
+ while (1) {
+ if (awss_finished) {
+ break;
+ }
+ HAL_SleepMs(300);
+ }
+ aws_release_mutex();
+ awss_finished = 2;
+ return 0;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_main.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_main.h
new file mode 100644
index 00000000..6175213a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_main.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_MAIN_H__
+#define __AWSS_MAIN_H__
+
+#include "awss_log.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#define DEFAULT_SSID zc_default_ssid
+#define DEFAULT_PASSWD zc_default_passwd
+#define ADHA_SSID zc_adha_ssid
+#define ADHA_PASSWD zc_adha_passwd
+
+extern const char *zc_default_ssid;
+extern const char *zc_default_passwd;
+extern const char *zc_adha_ssid;
+extern const char *zc_adha_passwd;
+
+int __awss_start(void);
+int __awss_stop(void);
+
+int awss_cancel_aha_monitor(void);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_smartconfig.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_smartconfig.h
new file mode 100644
index 00000000..13e0a7e4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/awss_smartconfig.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_SMARTCONFIG_H__
+#define __AWSS_SMARTCONFIG_H__
+
+#include
+#include "os.h"
+#include "zconfig_lib.h"
+#include "zconfig_ieee80211.h"
+#include "zconfig_protocol.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+/* invalid channel, neither 0, 0xff, nor 1-13 */
+#define INVALID_CHANNEL (0)
+#define PAYLOAD_BITS_CNT (7)
+#define PAYLOAD_BITS_MASK ((1 << PAYLOAD_BITS_CNT) - 1)
+
+extern const uint8_t zconfig_fixed_offset[ZC_ENC_TYPE_MAX + 1][2];
+extern const uint16_t zconfig_hint_frame[];
+
+uint8_t is_data_frame(uint16_t len);
+uint8_t is_start_frame(uint16_t len);
+uint8_t is_group_frame(uint16_t len);
+uint8_t get_data_index(uint16_t len);
+uint8_t get_group_index(uint16_t len);
+
+int zconfig_recv_completed(uint8_t tods);
+int zconfig_get_ssid_passwd(uint8_t tods);
+int package_cmp(uint8_t *package, uint8_t *src, uint8_t *dst, uint8_t tods, uint16_t len);
+int package_save(uint8_t *package, uint8_t *src, uint8_t *dst, uint8_t tods, uint16_t len);
+int awss_recv_callback_smartconfig(struct parser_res *res);
+int awss_ieee80211_smartconfig_process(uint8_t *ieee80211, int len, int link_type,
+ struct parser_res *res, signed char rssi);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c
new file mode 100644
index 00000000..07f4a9f8
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c
@@ -0,0 +1,825 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+/**
+ * ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT
+ * @fc: frame control bytes in little-endian byteorder
+ */
+#if 0
+int ieee80211_is_mgmt(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE)) ==
+ os_htole16(IEEE80211_FTYPE_MGMT);
+}
+#endif
+
+/**
+ * ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_ctl(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE)) ==
+ os_htole16(IEEE80211_FTYPE_CTL);
+}
+
+/**
+ * ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_data(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE)) ==
+ os_htole16(IEEE80211_FTYPE_DATA);
+}
+
+
+/**
+ * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_has_tods(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_TODS)) != 0;
+}
+
+/**
+ * ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_has_fromds(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FROMDS)) != 0;
+}
+
+/**
+ * ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_has_a4(uint16_t fc)
+{
+ uint16_t tmp = os_htole16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+ return (fc & tmp) == tmp;
+}
+
+/**
+ * ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_has_order(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_ORDER)) != 0;
+}
+
+/**
+ * ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_has_protected(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_PROTECTED)) != 0;
+}
+
+/**
+ * ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_data_qos(uint16_t fc)
+{
+ /*
+ * mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need
+ * to check the one bit
+ */
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) ==
+ os_htole16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA);
+}
+
+/**
+ * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data
+ * @fc: frame control bytes in little-endian byteorder
+ */
+#if 0
+int ieee80211_is_data_present(uint16_t fc)
+{
+ /*
+ * mask with 0x40 and test that that bit is clear to only return true
+ * for the data-containing substypes.
+ */
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE | 0x40)) ==
+ os_htole16(IEEE80211_FTYPE_DATA);
+}
+#endif
+
+/**
+ * ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and only data
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_data_exact(uint16_t fc)
+{
+ uint16_t tmp = fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
+
+ return (tmp == os_htole16(IEEE80211_FTYPE_DATA)) ||
+ (tmp == os_htole16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA));
+}
+
+/**
+ * ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_beacon(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
+}
+
+/**
+ * ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION
+ * @fc: frame control bytes in little-endian byteorder
+ */
+#if 0
+int ieee80211_is_action(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
+}
+#endif
+
+/**
+ * ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_probe_req(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ);
+}
+
+/**
+ * ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP
+ * @fc: frame control bytes in little-endian byteorder
+ */
+int ieee80211_is_probe_resp(uint16_t fc)
+{
+ return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
+}
+
+
+/**
+ * ieee80211_get_SA - get pointer to SA
+ * @hdr: the frame
+ *
+ * Given an 802.11 frame, this function returns the offset
+ * to the source address (SA). It does not verify that the
+ * header is long enough to contain the address, and the
+ * header must be long enough to contain the frame control
+ * field.
+ */
+uint8_t *ieee80211_get_SA(struct ieee80211_hdr *hdr)
+{
+ if (ieee80211_has_a4(hdr->frame_control))
+ return hdr->addr4;
+ if (ieee80211_has_fromds(hdr->frame_control))
+ return hdr->addr3;
+ return hdr->addr2;
+}
+
+/**
+ * ieee80211_get_DA - get pointer to DA
+ * @hdr: the frame
+ *
+ * Given an 802.11 frame, this function returns the offset
+ * to the destination address (DA). It does not verify that
+ * the header is long enough to contain the address, and the
+ * header must be long enough to contain the frame control
+ * field.
+ */
+uint8_t *ieee80211_get_DA(struct ieee80211_hdr *hdr)
+{
+ if (ieee80211_has_tods(hdr->frame_control))
+ return hdr->addr3;
+ else
+ return hdr->addr1;
+}
+
+uint8_t *ieee80211_get_BSSID(struct ieee80211_hdr *hdr)
+{
+ if (ieee80211_has_tods(hdr->frame_control)) {
+ if (!ieee80211_has_fromds(hdr->frame_control))
+ return hdr->addr1;
+ else
+ return NULL;
+ } else {
+ if (ieee80211_has_fromds(hdr->frame_control))
+ return hdr->addr2;
+ else
+ return hdr->addr3;
+ }
+}
+
+int ieee80211_get_bssid(uint8_t *in, uint8_t *mac)
+{
+ uint8_t *bssid = ieee80211_get_BSSID((struct ieee80211_hdr *)in);
+
+ if (bssid)
+ memcpy(mac, bssid, ETH_ALEN);
+ else
+ return -1;
+
+ return 0;
+}
+
+int ieee80211_has_frags(uint16_t fc)
+{
+ uint16_t tmp = fc & os_htole16(IEEE80211_FCTL_MOREFRAGS | IEEE80211_FCTL_ORDER);
+
+ return !!tmp;
+}
+
+/* DATA: 24B */
+/* QOS-DATA: 26B */
+int ieee80211_hdrlen(uint16_t fc)
+{
+ uint32_t hdrlen = 24;
+
+ if (ieee80211_is_data(fc)) {
+ if (ieee80211_has_a4(fc))
+ hdrlen = 30;
+ if (ieee80211_is_data_qos(fc)) {
+ hdrlen += IEEE80211_QOS_CTL_LEN;
+ if (ieee80211_has_order(fc))
+ hdrlen += IEEE80211_HT_CTL_LEN;
+ }
+ goto out;
+ }
+
+ if (ieee80211_is_ctl(fc)) {
+ /*
+ * ACK and CTS are 10 bytes, all others 16. To see how
+ * to get this condition consider
+ * subtype mask: 0b0000000011110000 (0x00F0)
+ * ACK subtype: 0b0000000011010000 (0x00D0)
+ * CTS subtype: 0b0000000011000000 (0x00C0)
+ * bits that matter: ^^^ (0x00E0)
+ * value of those: 0b0000000011000000 (0x00C0)
+ */
+ if ((fc & os_htole16(0x00E0)) == os_htole16(0x00C0))
+ hdrlen = 10;
+ else
+ hdrlen = 16;
+ }
+
+out:
+ return hdrlen;
+}
+
+/* helpers */
+int ieee80211_get_radiotap_len(uint8_t *data)
+{
+ struct ieee80211_radiotap_header *hdr =
+ (struct ieee80211_radiotap_header *)data;
+
+ return os_get_unaligned_le16((uint8_t *)&hdr->it_len);
+}
+
+const uint8_t *cfg80211_find_ie(uint8_t eid, const uint8_t *ies, int len)
+{
+ while (len > 2 && ies[0] != eid) {
+ len -= ies[1] + 2;
+ ies += ies[1] + 2;
+ }
+ if (len < 2)
+ return NULL;
+ if (len < 2 + ies[1])
+ return NULL;
+ return ies;
+}
+
+/**
+ * cfg80211_find_vendor_ie - find vendor specific information element in data
+ *
+ * @oui: vendor OUI
+ * @oui_type: vendor-specific OUI type
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * Return: %NULL if the vendor specific element ID could not be found or if the
+ * element is invalid (claims to be longer than the given data), or a pointer to
+ * the first byte of the requested element, that is the byte containing the
+ * element ID.
+ *
+ * Note: There are no checks on the element length other than having to fit into
+ * the given data.
+ */
+const uint8_t *cfg80211_find_vendor_ie(uint32_t oui, uint8_t oui_type, const uint8_t *ies, int len)
+{
+ struct ieee80211_vendor_ie *ie;
+ const uint8_t *pos = ies, *end = ies + len;
+ int ie_oui;
+
+ while (pos < end) {
+ pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
+ end - pos);
+ if (!pos)
+ return NULL;
+
+ ie = (struct ieee80211_vendor_ie *)pos;
+
+ /* make sure we can access ie->len */
+ /* BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); */
+
+ if (ie->len < sizeof(*ie))
+ goto cont;
+
+ ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
+ /* awss_trace("oui=%x, type=%x, len=%d\r\n", ie_oui, oui_type, ie->len); */
+ if (ie_oui == oui && ie->oui_type == oui_type)
+ return pos;
+cont:
+ pos += 2 + ie->len;
+ }
+ return NULL;
+}
+
+/**
+ * extract ssid from beacon frame or probe resp frame
+ *
+ * @beacon_frame: [IN] original 80211 beacon frame
+ * @frame_len: [IN] len of beacon frame
+ * @ssid: [OUT] null-terminated string, max len 32 bytes
+ *
+ * Return:
+ * 0/success, -1/failed
+ */
+int ieee80211_get_ssid(uint8_t *beacon_frame, uint16_t frame_len, uint8_t *ssid)
+{
+ uint16_t ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);/* same as u.probe_resp.variable */
+ const uint8_t *ptr = cfg80211_find_ie(WLAN_EID_SSID,
+ beacon_frame + ieoffset, frame_len - ieoffset);
+ if (ptr) {
+ uint8_t ssid_len = ptr[1];
+ if (ssid_len <= 32) { /* ssid 32 octets at most */
+ memcpy(ssid, ptr + 2, ssid_len);/* eating EID & len */
+ ssid[ssid_len] = '\0';
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * extract channel from beacon frame or probe resp frame
+ *
+ * @beacon_frame: [IN] original 80211 beacon frame
+ * @frame_len: [IN] len of beacon frame
+ *
+ * Return:
+ * bss channel 1-13, 0--means invalid channel
+ */
+int cfg80211_get_bss_channel(uint8_t *beacon_frame, uint16_t frame_len)
+{
+ uint16_t ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);/* same as u.probe_resp.variable */
+ const uint8_t *ie = beacon_frame + ieoffset;
+ uint16_t ielen = frame_len - ieoffset;
+
+ const uint8_t *tmp;
+ int channel_number = 0;
+
+ tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
+ if (tmp && tmp[1] == 1) {
+ channel_number = tmp[2];
+ } else {
+ tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
+ if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
+ struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
+
+ channel_number = htop->primary_chan;
+ }
+ }
+
+ return channel_number;
+}
+
+static const uint8_t WPA_OUI23A_TYPE[] = {0x00, 0x50, 0xf2, 0x01};
+static const uint8_t RSN_SUITE_1X[] = {0x00, 0x0f, 0xac, 0x01};
+
+static const uint8_t WPA_CIPHER_SUITE_NONE23A[] = {0x00, 0x50, 0xf2, 0x00};
+static const uint8_t WPA_CIPHER_SUITE_WEP4023A[] = {0x00, 0x50, 0xf2, 0x01};
+static const uint8_t WPA_CIPHER_SUITE_TKIP23A[] = {0x00, 0x50, 0xf2, 0x02};
+/* static const uint8_t WPA_CIPHER_SUITE_WRAP23A[] = {0x00, 0x50, 0xf2, 0x03}; */
+static const uint8_t WPA_CIPHER_SUITE_CCMP23A[] = {0x00, 0x50, 0xf2, 0x04};
+static const uint8_t WPA_CIPHER_SUITE_WEP10423A[] = {0x00, 0x50, 0xf2, 0x05};
+
+static const uint8_t RSN_CIPHER_SUITE_NONE23A[] = {0x00, 0x0f, 0xac, 0x00};
+static const uint8_t RSN_CIPHER_SUITE_WEP4023A[] = {0x00, 0x0f, 0xac, 0x01};
+static const uint8_t RSN_CIPHER_SUITE_TKIP23A[] = {0x00, 0x0f, 0xac, 0x02};
+/* static const uint8_t RSN_CIPHER_SUITE_WRAP23A[] = {0x00, 0x0f, 0xac, 0x03}; */
+static const uint8_t RSN_CIPHER_SUITE_CCMP23A[] = {0x00, 0x0f, 0xac, 0x04};
+static const uint8_t RSN_CIPHER_SUITE_WEP10423A[] = {0x00, 0x0f, 0xac, 0x05};
+
+#define WPA_SELECTOR_LEN (4)
+#define RSN_SELECTOR_LEN (4)
+
+#define BIT(x) (1 << (x))
+#define WPA_CIPHER_NONE BIT(0)
+#define WPA_CIPHER_WEP40 BIT(1)
+#define WPA_CIPHER_WEP104 BIT(2)
+#define WPA_CIPHER_TKIP BIT(3)
+#define WPA_CIPHER_CCMP BIT(4)
+
+static uint8_t map_cipher_to_encry(uint8_t cipher)
+{
+ switch (cipher) {
+ case WPA_CIPHER_CCMP:
+ return ZC_ENC_TYPE_AES;
+ case WPA_CIPHER_TKIP:
+ return ZC_ENC_TYPE_TKIP;
+ case WPA_CIPHER_WEP40:
+ case WPA_CIPHER_WEP104:
+ return ZC_ENC_TYPE_WEP;
+ case WPA_CIPHER_NONE:
+ return ZC_ENC_TYPE_NONE;
+ case (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP):
+ return ZC_ENC_TYPE_TKIPAES;
+ default:
+ awss_warn("unknow cipher type: %x\r\n", cipher);
+ return ZC_ENC_TYPE_INVALID;
+ }
+}
+
+static int get_wpa_cipher_suite(const uint8_t *s)
+{
+ if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_NONE;
+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_WEP40;
+ if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_TKIP;
+ if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_CCMP;
+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_WEP104;
+
+ return 0;
+}
+
+static int get_wpa2_cipher_suite(const uint8_t *s)
+{
+ if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_NONE;
+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_WEP40;
+ if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_TKIP;
+ if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_CCMP;
+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_WEP104;
+
+ return 0;
+}
+
+int cfg80211_parse_wpa_info(const uint8_t *wpa_ie, int wpa_ie_len,
+ uint8_t *group_cipher, uint8_t *pairwise_cipher,
+ uint8_t *is_8021x)
+{
+ int i, ret = 0;
+ int left, count;
+ const uint8_t *pos;
+
+ if (wpa_ie_len <= 0) {
+ /* No WPA IE - fail silently */
+ return -1;
+ }
+
+ if (wpa_ie[1] != (uint8_t)(wpa_ie_len - 2))
+ return -1;
+
+ pos = wpa_ie;
+
+ pos += 8;
+ left = wpa_ie_len - 8;
+
+ /* group_cipher */
+ if (left >= WPA_SELECTOR_LEN) {
+
+ *group_cipher = get_wpa_cipher_suite(pos);
+
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ } else if (left > 0) {
+ return -1;
+ }
+
+ /* pairwise_cipher */
+ if (left >= 2) {
+ /* count = le16_to_cpu(*(uint16_t*)pos); */
+ count = os_get_unaligned_le16((uint8_t *)pos);
+ pos += 2;
+ left -= 2;
+
+ if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+ return -1;
+ }
+
+ for (i = 0; i < count; i++) {
+ *pairwise_cipher |= get_wpa_cipher_suite(pos);
+
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ return -1;
+ }
+
+ if (is_8021x) {
+ if (left >= 6) {
+ pos += 2;
+ if (!memcmp(pos, WPA_OUI23A_TYPE, 4)) {
+ *is_8021x = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int cfg80211_parse_wpa2_info(const uint8_t* rsn_ie, int rsn_ie_len, uint8_t *group_cipher,
+ uint8_t *pairwise_cipher, uint8_t *is_8021x)
+{
+ int i, ret = 0;
+ int left, count;
+ const uint8_t *pos;
+
+ if (rsn_ie_len <= 0) {
+ /* No RSN IE - fail silently */
+ return -1;
+ }
+
+ if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (uint8_t)(rsn_ie_len - 2)) {
+ return -1;
+ }
+
+ pos = rsn_ie;
+ pos += 4;
+ left = rsn_ie_len - 4;
+
+ /* group_cipher */
+ if (left >= RSN_SELECTOR_LEN) {
+ *group_cipher = get_wpa2_cipher_suite(pos);
+
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ } else if (left > 0) {
+ return -1;
+ }
+
+ /* pairwise_cipher */
+ if (left >= 2) {
+ /* count = le16_to_cpu(*(uint16_t*)pos); */
+ count = os_get_unaligned_le16((uint8_t *)pos);
+ pos += 2;
+ left -= 2;
+
+ if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+ return -1;
+ }
+
+ for (i = 0; i < count; i++) {
+ *pairwise_cipher |= get_wpa2_cipher_suite(pos);
+
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ return -1;
+ }
+
+ if (is_8021x) {
+ if (left >= 6) {
+ pos += 2;
+ if (!memcmp(pos, RSN_SUITE_1X, 4)) {
+ *is_8021x = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * extract auth/encry type from beacon frame or probe resp frame
+ *
+ * @beacon_frame: [IN] original 80211 beacon frame
+ * @frame_len: [IN] len of beacon frame
+ *
+ * Return:
+ * bss channel 1-13, 0--means invalid channel
+ */
+int cfg80211_get_cipher_info(uint8_t *beacon_frame, uint16_t frame_len,
+ uint8_t *auth_type, uint8_t *pairwise_cipher_type,
+ uint8_t *group_cipher_type)
+{
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon_frame;
+ uint8_t is_privacy = !!(mgmt->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY);
+
+ uint16_t ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);/* same as u.probe_resp.variable */
+ const uint8_t *ie = beacon_frame + ieoffset;
+ uint16_t ielen = frame_len - ieoffset;
+
+ uint8_t auth = 0, group_cipher = 0, pairwise_cipher = 0, is80211X = 0;
+ const uint8_t *tmp;
+ int ret = 0;
+
+ tmp = cfg80211_find_ie(WLAN_EID_RSN, ie, ielen);
+ if (tmp && tmp[1]) {
+ ret = cfg80211_parse_wpa2_info(tmp, tmp[1] + 2, &group_cipher, &pairwise_cipher, &is80211X);
+ if (is80211X)
+ auth = ZC_AUTH_TYPE_WPA28021X;
+ else
+ auth = ZC_AUTH_TYPE_WPA2PSK;
+ group_cipher = map_cipher_to_encry(group_cipher);
+ pairwise_cipher = map_cipher_to_encry(pairwise_cipher);
+ } else {
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+ tmp = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, ie, ielen);
+ if (tmp) {
+ ret = cfg80211_parse_wpa_info(tmp, tmp[1] + 2, &group_cipher, &pairwise_cipher, &is80211X);
+ if (is80211X)
+ auth = ZC_AUTH_TYPE_WPA8021X;
+ else
+ auth = ZC_AUTH_TYPE_WPAPSK;
+ group_cipher = map_cipher_to_encry(group_cipher);
+ pairwise_cipher = map_cipher_to_encry(pairwise_cipher);
+ } else
+#endif
+ {
+ if (is_privacy) {
+ auth = ZC_AUTH_TYPE_SHARED; /* TODO: WEP */
+ pairwise_cipher = ZC_ENC_TYPE_WEP;
+ group_cipher = ZC_ENC_TYPE_WEP;
+ } else {
+ auth = ZC_AUTH_TYPE_OPEN;
+ pairwise_cipher = ZC_ENC_TYPE_NONE;
+ group_cipher = ZC_ENC_TYPE_NONE;
+ }
+ }
+ }
+
+ if (auth_type)
+ *auth_type = auth;
+ if (pairwise_cipher_type)
+ *pairwise_cipher_type = pairwise_cipher;
+ if (group_cipher_type)
+ *group_cipher_type = group_cipher;
+
+ return ret;
+}
+
+/*
+ * make sure 80211 frame is word align, otherwise struct ieee80211_hdr will bug
+ * TODO: code refactor, avoid using memmove
+ */
+#define check_ieee80211_buf_alignment(buf_addr, len) \
+do {\
+ if (((unsigned long)(buf_addr) & 0x1) && len > 0) {\
+ uint8_t *word_align_addr = (uint8_t *)((unsigned long)(buf_addr) & ~0x1);\
+ memmove(word_align_addr, buf_addr, len);\
+ buf_addr = word_align_addr;\
+ }\
+} while (0)
+
+uint8_t *zconfig_remove_link_header(uint8_t **in, int *len, int link_type)
+{
+ int lt_len = 0;
+
+ switch (link_type) {
+ case AWS_LINK_TYPE_NONE:
+ break;
+ case AWS_LINK_TYPE_PRISM:
+#define PRISM_HDR_LEN 144
+ *in += PRISM_HDR_LEN;
+ *len -= PRISM_HDR_LEN;
+ /* 144, no need to check buf aligment */
+ break;
+ case AWS_LINK_TYPE_80211_RADIO:
+ lt_len = ieee80211_get_radiotap_len(*in);
+ *in += lt_len;
+ *len -= lt_len;
+ check_ieee80211_buf_alignment(*in, *len);
+ break;
+ case AWS_LINK_TYPE_80211_RADIO_AVS:
+#define WLANCAP_MAGIC_COOKIE_V1 0x80211001
+#define WLANCAP_MAGIC_COOKIE_V2 0x80211002
+ lt_len = *(uint32_t *)(*in + 4);/* first 4 byte is magic code */
+ *in += lt_len;
+ *len -= lt_len;
+ check_ieee80211_buf_alignment(*in, *len);
+ break;
+ default:
+ awss_debug("un-supported link type!\r\n");
+ break;
+ }
+
+ return *in;
+}
+
+struct awss_protocol_couple_type awss_protocol_couple_array[] = {
+#ifdef AWSS_SUPPORT_HT40
+ {ALINK_HT_CTRL, awss_ieee80211_ht_ctrl_process, awss_recv_callback_ht_ctrl},
+#endif
+#ifdef AWSS_SUPPORT_APLIST
+ {ALINK_APLIST, awss_ieee80211_aplist_process, NULL},
+#endif
+#ifdef AWSS_SUPPORT_AHA
+ {ALINK_DEFAULT_SSID, awss_ieee80211_aha_process, awss_recv_callback_aha_ssid},
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ {ALINK_ADHA_SSID, awss_ieee80211_adha_process, awss_recv_callback_adha_ssid},
+#endif
+#ifndef AWSS_DISABLE_ENROLLEE
+ {ALINK_ZERO_CONFIG, awss_ieee80211_zconfig_process, awss_recv_callback_zconfig},
+#endif
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+ {ALINK_WPS, awss_ieee80211_wps_process, awss_recv_callback_wps},
+#endif
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+ {ALINK_BROADCAST, awss_ieee80211_smartconfig_process, awss_recv_callback_smartconfig}
+#endif
+};
+
+/**
+ * ieee80211_data_extratct - extract 80211 frame info
+ *
+ * @in: [IN] 80211 frame
+ * @len: [IN] 80211 frame len
+ * @link_type: [IN] link type @see enum AWS_LINK_TYPE
+ * @res: [OUT] 80211 frame parser result, see struct parser_res.
+ *
+ * @warning: encry_type may collision with aes & tpip in some cases,
+ * then encry_type will be set to INVALID.
+ * @Return:
+ * @see enum ALINK_TYPE
+ *
+ * @Note: howto deal with radio RSSI signal
+ */
+int ieee80211_data_extract(uint8_t *in, int len, int link_type, struct parser_res *res, signed char rssi)
+{
+ struct ieee80211_hdr *hdr;
+ int alink_type = ALINK_INVALID;
+ int pkt_type = PKG_INVALID;
+ int i, fc;
+
+ hdr = (struct ieee80211_hdr *)zconfig_remove_link_header(&in, &len, link_type);
+ if (len <= 0)
+ goto drop;
+ fc = hdr->frame_control;
+
+ for (i = 0; i < sizeof(awss_protocol_couple_array) / sizeof(awss_protocol_couple_array[0]); i ++) {
+ awss_protocol_process_func_type protocol_func = awss_protocol_couple_array[i].awss_protocol_process_func;
+ if (protocol_func == NULL)
+ continue;
+ alink_type = protocol_func((uint8_t *)hdr, len, link_type, res, rssi);
+ if (alink_type != ALINK_INVALID)
+ break;
+ }
+
+ if (alink_type == ALINK_INVALID)
+ goto drop;
+
+ if (alink_type != ALINK_HT_CTRL) {
+ /* convert IEEE 802.11 header + possible LLC headers into Ethernet header
+ * IEEE 802.11 address fields:
+ * ToDS FromDS Addr1 Addr2 Addr3 Addr4
+ * 0 0 DA SA BSSID n/a
+ * 0 1 DA BSSID SA n/a
+ * 1 0 BSSID SA DA n/a
+ * 1 1 RA TA DA SA
+ */
+ res->src = ieee80211_get_SA(hdr);
+ res->dst = ieee80211_get_DA(hdr);
+ res->bssid = ieee80211_get_BSSID(hdr);
+ res->tods = ieee80211_has_tods(fc);
+ }
+
+ do {
+ awss_protocol_finish_func_type finish_func = awss_protocol_couple_array[i].awss_protocol_finish_func;
+ if (finish_func)
+ pkt_type = finish_func(res);
+ } while(0);
+
+drop:
+ return pkt_type;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h
new file mode 100644
index 00000000..bf329fb6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __ZCONFIG_IEEE80211_H__
+#define __ZCONFIG_IEEE80211_H__
+
+#include "zconfig_utils.h"
+#include "zconfig_protocol.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#define WIFI_RX_SENSITIVITY (-85)
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+/*
+ * DS bit usage
+ *
+ * TA = transmitter address
+ * RA = receiver address
+ * DA = destination address
+ * SA = source address
+ *
+ * ToDS FromDS A1(RA) A2(TA) A3 A4 Use
+ * -----------------------------------------------------------------
+ * 0 0 DA SA BSSID - IBSS/DLS
+ * 0 1 DA BSSID SA - AP -> STA
+ * 1 0 BSSID SA DA - AP <- STA
+ * 1 1 RA TA DA SA unspecified (WDS)
+ */
+#define FCS_LEN (4)
+
+#define IEEE80211_FCTL_VERS (0x0003)
+#define IEEE80211_FCTL_FTYPE (0x000c)
+#define IEEE80211_FCTL_STYPE (0x00f0)
+#define IEEE80211_FCTL_TODS (0x0100)
+#define IEEE80211_FCTL_FROMDS (0x0200)
+#define IEEE80211_FCTL_MOREFRAGS (0x0400)
+#define IEEE80211_FCTL_RETRY (0x0800)
+#define IEEE80211_FCTL_PM (0x1000)
+#define IEEE80211_FCTL_MOREDATA (0x2000)
+#define IEEE80211_FCTL_PROTECTED (0x4000)
+#define IEEE80211_FCTL_ORDER (0x8000)
+#define IEEE80211_FCTL_CTL_EXT (0x0f00)
+
+#define IEEE80211_SCTL_FRAG (0x000F)
+#define IEEE80211_SCTL_SEQ (0xFFF0)
+
+#define IEEE80211_FTYPE_MGMT (0x0000)
+#define IEEE80211_FTYPE_CTL (0x0004)
+#define IEEE80211_FTYPE_DATA (0x0008)
+#define IEEE80211_FTYPE_EXT (0x000c)
+
+#define IEEE80211_STYPE_DATA (0x0000)
+#define IEEE80211_STYPE_QOS_DATA (0x0080)
+#define IEEE80211_STYPE_PROBE_REQ (0x0040)
+#define IEEE80211_STYPE_PROBE_RESP (0x0050)
+#define IEEE80211_STYPE_BEACON (0x0080)
+#define IEEE80211_STYPE_ACTION (0x00D0)
+
+#define IEEE80211_QOS_CTL_LEN (2)
+#define IEEE80211_HT_CTL_LEN (4)
+
+/* beacon capab_info */
+#define WLAN_CAPABILITY_PRIVACY (1 << 4)
+
+#define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+
+#define WLAN_CATEGORY_VENDOR_SPECIFIC (127)
+
+#define WLAN_EID_SSID (0)
+#define WLAN_EID_DS_PARAMS (3)
+#define WLAN_EID_RSN (48)
+#define WLAN_EID_HT_OPERATION (61)
+#define WLAN_EID_VENDOR_SPECIFIC (221)
+
+#define WLAN_OUI_ALIBABA (0xD896E0)
+#define WLAN_OUI_TYPE_ALIBABA (1)
+#define WLAN_OUI_TYPE_ENROLLEE (0xAA)
+#define WLAN_OUI_TYPE_REGISTRAR (0xAB)
+
+enum ALINK_TYPE {
+ ALINK_INVALID = 0,
+ ALINK_BROADCAST = 1,
+ ALINK_ROUTER = 2,
+ ALINK_ACTION = 3,
+ ALINK_WPS = 4,
+ ALINK_DEFAULT_SSID = 5,
+ ALINK_ZERO_CONFIG = 6,
+ ALINK_ADHA_SSID = 7,
+ ALINK_APLIST,
+ ALINK_HT_CTRL,
+};
+
+/* 80211 frame parser result */
+struct parser_res {
+ union _alink_type_ {
+ /* for broadcast data frame */
+ struct broadcast_info {
+ uint8_t encry_type;/* none/wep/tkip/aes */
+ uint16_t data_len;/* framelen - 80211 hdr - fcs(4) */
+ uint16_t sn;
+ } br;
+ /* for alink ie frame */
+ struct ie_info {
+ uint8_t *alink_ie;
+ uint16_t alink_ie_len;
+ } ie;
+ /* for p2p action frame */
+ struct action_info {
+ uint8_t *data;
+ uint16_t data_len;
+ } action;
+ /* for p2p wps frame */
+ struct wps_info {
+ uint8_t *data;
+ uint16_t data_len;
+ } wps;
+ /* for ht40 ctrl frame */
+ struct ht_ctrl_info {
+ signed char rssi;
+ uint8_t filter;
+ uint16_t data_len;
+ } ht_ctrl;
+ } u;
+
+ uint8_t *src; /* src mac of sender */
+ uint8_t *dst; /* ff:ff:ff:ff:ff:ff */
+ uint8_t *bssid; /* mac of AP */
+
+ uint8_t tods; /* fromDs or toDs */
+ uint8_t channel; /* 1 - 13 */
+};
+
+struct ieee80211_hdr {
+ uint16_t frame_control;
+ uint16_t duration_id;
+ uint8_t addr1[ETH_ALEN];
+ uint8_t addr2[ETH_ALEN];
+ uint8_t addr3[ETH_ALEN];
+ uint16_t seq_ctrl;
+ uint8_t addr4[ETH_ALEN];
+};
+
+/*
+ * The radio capture header precedes the 802.11 header.
+ *
+ * Note well: all radiotap fields are little-endian.
+ */
+struct ieee80211_radiotap_header {
+ uint8_t it_version; /* Version 0. Only increases
+ * for drastic changes,
+ * introduction of compatible
+ * new fields does not count.
+ */
+ uint8_t it_pad;
+ uint16_t it_len; /* length of the whole
+ * header in bytes, including
+ * it_version, it_pad,
+ * it_len, and data fields.
+ */
+ uint32_t it_present; /* A bitmap telling which
+ * fields are present. Set bit 31
+ * (0x80000000) to extend the
+ * bitmap by another 32 bits.
+ * Additional extensions are made
+ * by setting bit 31.
+ */
+};
+
+/**
+ * struct ieee80211_ht_operation - HT operation IE
+ *
+ * This structure is the "HT operation element" as
+ * described in 802.11n-2009 7.3.2.57
+ */
+struct ieee80211_ht_operation {
+ uint8_t primary_chan;
+ uint8_t ht_param;
+ uint16_t operation_mode;
+ uint16_t stbc_param;
+ uint8_t basic_set[16];
+};
+
+struct ieee80211_vendor_ie {
+ uint8_t element_id;
+ uint8_t len;
+ uint8_t oui[3];
+ uint8_t oui_type;
+};
+/*
+ * i.e. alibaba ie
+ * @name @len @payload
+ * element_id 1 221
+ * len 1 22
+ * oui 3 0xD896E0
+ * oui_type 1 1 -- alink router service advertisement
+ * version 1 1
+ * challenge 16 non-zero-ascii code
+ * reserve 1 0
+ */
+
+struct ieee80211_mgmt {
+ uint16_t frame_control;
+ uint16_t duration;
+ uint8_t da[ETH_ALEN];
+ uint8_t sa[ETH_ALEN];
+ uint8_t bssid[ETH_ALEN];
+ uint16_t seq_ctrl;
+ union {
+ struct {
+ /* __le64 timestamp; */
+ uint16_t timestamp[4];
+ uint16_t beacon_int;
+ uint16_t capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ uint8_t variable;
+ } beacon;
+ struct {
+ /* only variable items: SSID, Supported rates */
+ uint8_t variable;
+ } probe_req;
+ struct {
+ /* __le64 timestamp; */
+ uint16_t timestamp[4];
+ uint16_t beacon_int;
+ uint16_t capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params */
+ uint8_t variable;
+ } probe_resp;
+ } u;
+};
+
+typedef int (*awss_protocol_process_func_type)(uint8_t *, int, int, struct parser_res *, signed char);
+typedef int (*awss_protocol_finish_func_type)(struct parser_res *);
+
+struct awss_protocol_couple_type {
+ int type;
+ awss_protocol_process_func_type awss_protocol_process_func;
+ awss_protocol_finish_func_type awss_protocol_finish_func;
+};
+
+int ieee80211_data_extract(uint8_t *in, int len, int link_type,
+ struct parser_res *res, signed char rssi);
+
+struct ap_info *zconfig_get_apinfo(uint8_t *mac);
+struct ap_info *zconfig_get_apinfo_by_ssid(uint8_t *ssid);
+struct ap_info *zconfig_get_apinfo_by_ssid_prefix(uint8_t *ssid_prefix);
+struct ap_info *zconfig_get_apinfo_by_ssid_suffix(uint8_t *ssid_suffix);
+
+/* add channel to scanning channel list */
+int zconfig_add_active_channel(int channel);
+uint8_t zconfig_get_press_status();
+
+int ieee80211_hdrlen(uint16_t fc);
+int ieee80211_has_a4(uint16_t fc);
+int ieee80211_is_ctl(uint16_t fc);
+int ieee80211_is_mgmt(uint16_t fc);
+int ieee80211_is_data(uint16_t fc);
+int ieee80211_has_tods(uint16_t fc);
+int ieee80211_has_frags(uint16_t fc);
+int ieee80211_has_order(uint16_t fc);
+int ieee80211_is_beacon(uint16_t fc);
+int ieee80211_is_action(uint16_t fc);
+int ieee80211_has_fromds(uint16_t fc);
+int ieee80211_is_data_qos(uint16_t fc);
+int ieee80211_is_probe_req(uint16_t fc);
+int ieee80211_is_probe_resp(uint16_t fc);
+int ieee80211_is_data_exact(uint16_t fc);
+int ieee80211_has_protected(uint16_t fc);
+int ieee80211_is_data_present(uint16_t fc);
+int ieee80211_get_radiotap_len(uint8_t *data);
+int ieee80211_get_bssid(uint8_t *in, uint8_t *mac);
+int ieee80211_get_ssid(uint8_t *beacon_frame, uint16_t frame_len, uint8_t *ssid);
+int ieee80211_data_extract(uint8_t *in, int len, int link_type, struct parser_res *res, signed char rssi);
+int cfg80211_get_bss_channel(uint8_t *beacon_frame, uint16_t frame_len);
+int cfg80211_get_cipher_info(uint8_t *beacon_frame, uint16_t frame_len,
+ uint8_t *auth_type, uint8_t *pairwise_cipher_type, uint8_t *group_cipher_type);
+uint8_t *ieee80211_get_SA(struct ieee80211_hdr *hdr);
+uint8_t *ieee80211_get_DA(struct ieee80211_hdr *hdr);
+uint8_t *ieee80211_get_BSSID(struct ieee80211_hdr *hdr);
+const uint8_t *cfg80211_find_ie(uint8_t eid, const uint8_t *ies, int len);
+const uint8_t *cfg80211_find_vendor_ie(uint32_t oui, uint8_t oui_type, const uint8_t *ies, int len);
+struct ap_info *zconfig_get_apinfo(uint8_t *mac);
+struct ap_info *zconfig_get_apinfo_by_ssid(uint8_t *ssid);
+struct ap_info *zconfig_get_apinfo_by_ssid_prefix(uint8_t *ssid_prefix);
+struct ap_info *zconfig_get_apinfo_by_ssid_suffix(uint8_t *ssid_suffix);
+
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif /* __IEEE80211_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/statics/awss_statis.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/statics/awss_statis.c
new file mode 100644
index 00000000..f3e364b1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/statics/awss_statis.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#ifdef AWSS_SUPPORT_STATIS
+
+#define DROUTE_START g_awss_statis.droute.conn_router_start
+#define DROUTE_END g_awss_statis.droute.conn_router_end
+#define DROUTE_CNT g_awss_statis.droute.conn_router_cnt
+#define DROUTE_SUC g_awss_statis.droute.conn_router_suc
+#define DROUTE_TMIN g_awss_statis.droute.conn_router_time_min
+#define DROUTE_TMAX g_awss_statis.droute.conn_router_time_max
+#define DROUTE_TMEAN g_awss_statis.droute.conn_router_time_mean
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+#define WPS_CNT g_awss_statis.wps.wps_parse_cnt
+#define WPS_CRC_ERR g_awss_statis.wps.wps_parse_crc_err
+#define WPS_PW_ERR g_awss_statis.wps.wps_parse_passwd_err
+#define WPS_SUC g_awss_statis.wps.wps_parse_suc
+#endif
+#define SM_CNT g_awss_statis.sm.sm_parse_cnt
+#define SM_CRC_ERR g_awss_statis.sm.sm_parse_crc_err
+#define SM_PW_ERR g_awss_statis.sm.sm_parse_passwd_err
+#define SM_SUC g_awss_statis.sm.sm_parse_suc
+#define SM_START g_awss_statis.sm.sm_parse_start
+#define SM_END g_awss_statis.sm.sm_parse_end
+#define SM_TMIN g_awss_statis.sm.sm_time_min
+#define SM_TMAX g_awss_statis.sm.sm_time_max
+#define SM_TMEAN g_awss_statis.sm.sm_time_mean
+#endif
+
+#ifdef AWSS_SUPPORT_AHA
+#define PAP_CNT g_awss_statis.pap.aha_cnt
+#define PAP_SUC g_awss_statis.pap.aha_suc
+#define PAP_TMIN g_awss_statis.pap.aha_time_min
+#define PAP_TMAX g_awss_statis.pap.aha_time_max
+#define PAP_TMEAN g_awss_statis.pap.aha_time_mean
+#define PAP_START g_awss_statis.pap.aha_start
+#define PAP_END g_awss_statis.pap.aha_end
+#define PAP_SSTART g_awss_statis.pap.aha_scan_start
+#define PAP_SSTOP g_awss_statis.pap.aha_scan_end
+#define PAP_SAP g_awss_statis.pap.aha_switch_ap
+#define PAP_PW_ERR g_awss_statis.pap.aha_passwd_err
+#endif
+
+#ifdef AWSS_SUPPORT_DEV_AP
+#define DAP_CNT g_awss_statis.dap.dev_ap_cnt
+#define DAP_SUC g_awss_statis.dap.dev_ap_suc
+#define DAP_TMIN g_awss_statis.dap.dev_ap_time_min
+#define DAP_TMAX g_awss_statis.dap.dev_ap_time_max
+#define DAP_TMEAN g_awss_statis.dap.dev_ap_time_mean
+#define DAP_START g_awss_statis.dap.dev_ap_start
+#define DAP_END g_awss_statis.dap.dev_ap_end
+#define DAP_PW_ERR g_awss_statis.dap.dev_ap_passwd_err
+#endif
+
+#ifdef AWSS_SUPPORT_ADHA
+#define ROUTE_CNT g_awss_statis.route.adha_cnt
+#define ROUTE_SUC g_awss_statis.route.adha_suc
+#define ROUTE_TMIN g_awss_statis.route.adha_time_min
+#define ROUTE_TMAX g_awss_statis.route.adha_time_max
+#define ROUTE_TMEAN g_awss_statis.route.adha_time_mean
+#define ROUTE_START g_awss_statis.route.adha_start
+#define ROUTE_END g_awss_statis.route.adha_end
+#endif
+
+#ifndef AWSS_DISABLE_ENROLLEE
+#define ZC_CNT g_awss_statis.zconfig.zc_cnt
+#define ZC_SUC g_awss_statis.zconfig.zc_suc
+#define ZC_PW_ERR g_awss_statis.zconfig.zc_passwd_err
+#endif
+
+#define AWSS_STATIS_BUF_LEN (768)
+
+static void *awss_statis_mutex = NULL;
+static uint32_t awss_statis_trace_id = 0;
+static uint32_t awss_statis_report_id = 0;
+static struct awss_statis_t g_awss_statis = {0};
+
+int awss_report_statis(const char *module)
+{
+ const char *elem_fmt = "[%s max:%u min:%u mean:%u cnt:%u suc:%u crc-err:%u pw-err:%u],";
+ int log_buf_len = AWSS_STATIS_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_BUF_LEN + 1);
+ if (log_content == NULL)
+ goto STATIS_ERR;
+ log_buf = os_zalloc(log_buf_len + 1);
+ if (log_buf == NULL)
+ goto STATIS_ERR;
+
+ if (awss_build_topic(TOPIC_POST_STATIS, statis_topic, TOPIC_LEN_MAX) == NULL) {
+ awss_err("awss build statis topic fail\n");
+ goto STATIS_ERR;
+ }
+
+ if (awss_statis_mutex)
+ HAL_MutexLock(awss_statis_mutex);
+
+ if (DROUTE_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "ConnRouter",
+ DROUTE_TMAX, DROUTE_TMIN, DROUTE_TMEAN, DROUTE_CNT, DROUTE_SUC, 0, 0);
+ }
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+ if (SM_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Smartconfig",
+ SM_TMAX, SM_TMIN, SM_TMEAN, SM_CNT, SM_SUC, SM_CRC_ERR, SM_PW_ERR);
+ }
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+ if (WPS_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Smartconfig-wps",
+ 0, 0, 0, WPS_CNT, WPS_SUC, WPS_CRC_ERR, WPS_PW_ERR);
+ }
+#endif
+#endif
+#ifdef AWSS_SUPPORT_AHA
+ if (PAP_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Aha",
+ PAP_TMAX, PAP_TMIN, PAP_TMEAN, PAP_CNT, PAP_SUC, 0, PAP_PW_ERR);
+ }
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ if (ROUTE_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Adha",
+ ROUTE_TMAX, ROUTE_TMIN, ROUTE_TMEAN, ROUTE_CNT, ROUTE_SUC, 0, 0);
+ }
+#endif
+#ifndef AWSS_DISABLE_ENROLLEE
+ if (ZC_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Zconfig",
+ 0, 0, 0, ZC_CNT, ZC_SUC, 0, ZC_PW_ERR);
+ }
+#endif
+#ifdef AWSS_SUPPORT_DEV_AP
+ if (DAP_CNT > 0) {
+ len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Dev-ap",
+ DAP_TMAX, DAP_TMIN, DAP_TMEAN, DAP_CNT, DAP_SUC, 0, DAP_PW_ERR);
+ }
+#endif
+
+ do {
+ if (len == 0) /* no need to report log */
+ break;
+ log_buf[len - 1] = '\0'; /* remove end of ',' */
+
+ HAL_Snprintf(log_content, AWSS_STATIS_BUF_LEN, AWSS_STATIS_FMT, (uint32_t)HAL_UptimeMs(), "AWSS_TRACE",
+ module == NULL ? "default" : module, awss_statis_trace_id, log_buf);
+
+ HAL_Snprintf(id_str, sizeof(id_str), "%u", ++ awss_statis_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("awss report statis %s\n", ret == 0 ? "success" : "fail");
+ } while (0);
+
+ if (awss_statis_mutex)
+ HAL_MutexUnlock(awss_statis_mutex);
+
+ HAL_Free(log_buf);
+ HAL_Free(log_content);
+
+ return 0;
+
+STATIS_ERR:
+ if (log_content) HAL_Free(log_content);
+ if (log_buf) HAL_Free(log_buf);
+ return -1;
+}
+
+void awss_disp_statis()
+{
+ if (awss_statis_mutex)
+ HAL_MutexLock(awss_statis_mutex);
+
+ awss_debug("--------------------------------AWSS STATIS-----------------------------------");
+ awss_debug("name\t\tmax\tmin\tmean\tcnt\tsuc\tcrc-err\tpasswd-err");
+ awss_debug("ConnRouter \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ DROUTE_TMAX, DROUTE_TMIN, DROUTE_TMEAN, DROUTE_CNT, DROUTE_SUC, 0, 0);
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+ awss_debug("Smartconfig \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ SM_TMAX, SM_TMIN, SM_TMEAN, SM_CNT, SM_SUC, SM_CRC_ERR, SM_PW_ERR);
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+ awss_debug("Smartconfig-wps \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ 0, 0, 0, WPS_CNT, WPS_SUC, WPS_CRC_ERR, WPS_PW_ERR);
+#endif
+#endif
+#ifdef AWSS_SUPPORT_AHA
+ awss_debug("Aha \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ PAP_TMAX, PAP_TMIN, PAP_TMEAN, PAP_CNT, PAP_SUC, 0, PAP_PW_ERR);
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ awss_debug("Adha \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ ROUTE_TMAX, ROUTE_TMIN, ROUTE_TMEAN, ROUTE_CNT, ROUTE_SUC, 0, 0);
+#endif
+#ifndef AWSS_DISABLE_ENROLLEE
+ awss_debug("Zconfig \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ 0, 0, 0, ZC_CNT, ZC_SUC, 0, ZC_PW_ERR);
+#endif
+#ifdef AWSS_SUPPORT_DEV_AP
+ awss_debug("Dev-ap \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
+ DAP_TMAX, DAP_TMIN, DAP_TMEAN, DAP_CNT, DAP_SUC, 0, DAP_PW_ERR);
+#endif
+ awss_debug("------------------------------------------------------------------------------");
+
+ if (awss_statis_mutex)
+ HAL_MutexUnlock(awss_statis_mutex);
+}
+
+void awss_clear_statis()
+{
+ if (awss_statis_mutex)
+ HAL_MutexLock(awss_statis_mutex);
+
+ memset(&g_awss_statis, 0, sizeof(g_awss_statis));
+
+ awss_statis_trace_id = 0;
+ awss_statis_report_id = 0;
+
+ if (awss_statis_mutex) {
+ HAL_MutexUnlock(awss_statis_mutex);
+ HAL_MutexDestroy(awss_statis_mutex);
+ }
+ awss_statis_mutex = NULL;
+}
+
+void awss_update_statis(int awss_statis_idx, int type)
+{
+ uint32_t time = HAL_UptimeMs();
+
+ if (awss_statis_mutex == NULL) {
+ awss_statis_mutex = HAL_MutexCreate();
+ if (awss_statis_mutex == NULL) {
+ awss_debug("a-statis am fail\n");
+ return;
+ }
+ }
+
+ HAL_MutexLock(awss_statis_mutex);
+
+ if (type == AWSS_STATIS_TYPE_TIME_START)
+ awss_statis_trace_id ++;
+
+ switch (awss_statis_idx) {
+ case AWSS_STATIS_CONN_ROUTER_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ DROUTE_CNT ++;
+ DROUTE_START = time;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ DROUTE_SUC ++;
+ DROUTE_END = time;
+ time = (uint32_t)(DROUTE_END - DROUTE_START);
+ if (DROUTE_SUC > 0) {
+ DROUTE_TMEAN = (DROUTE_TMEAN + time) / (DROUTE_SUC);
+ } else {
+ DROUTE_TMEAN = time;
+ DROUTE_SUC = 1;
+ }
+ if (DROUTE_TMIN == 0 || DROUTE_TMIN > time)
+ DROUTE_TMIN = time;
+ if (DROUTE_TMAX == 0 || DROUTE_TMAX < time)
+ DROUTE_TMAX = time;
+ break;
+ default:
+ break;
+ }
+ break;
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+ case AWSS_STATIS_WPS_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ WPS_CNT ++;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ WPS_SUC ++;
+ break;
+ case AWSS_STATIS_TYPE_PASSWD_ERR:
+ WPS_PW_ERR ++;
+ break;
+ case AWSS_STATIS_TYPE_CRC_ERR:
+ WPS_CRC_ERR ++;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+ case AWSS_STATIS_SM_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ SM_CNT ++;
+ SM_START = time;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ SM_SUC ++;
+ SM_END = time;
+ time = (uint32_t)(SM_END - SM_START);
+ if (SM_SUC > 0) {
+ SM_TMEAN = (SM_TMEAN + time) / (SM_SUC);
+ } else {
+ SM_TMEAN = time;
+ SM_SUC = 1;
+ }
+
+ if (SM_TMIN == 0 || SM_TMIN > time)
+ SM_TMIN = time;
+ if (SM_TMAX == 0 || SM_TMAX < time)
+ SM_TMAX = time;
+ break;
+ case AWSS_STATIS_TYPE_PASSWD_ERR:
+ SM_PW_ERR ++;
+ break;
+ case AWSS_STATIS_TYPE_CRC_ERR:
+ SM_CRC_ERR ++;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#ifdef AWSS_SUPPORT_AHA
+ case AWSS_STATIS_PAP_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ PAP_CNT ++;
+ PAP_START = time;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ PAP_SUC ++;
+ PAP_END = time;
+ time = (uint32_t)(PAP_END - PAP_START);
+ if (PAP_SUC > 0) {
+ PAP_TMEAN = (PAP_TMEAN + time) / (PAP_SUC);
+ } else {
+ PAP_TMEAN = time;
+ PAP_SUC = 1;
+ }
+ if (PAP_TMIN == 0 || PAP_TMIN > time)
+ PAP_TMIN = time;
+ if (PAP_TMAX == 0 || PAP_TMAX < time)
+ PAP_TMAX = time;
+ break;
+ case AWSS_STATIS_TYPE_PASSWD_ERR:
+ PAP_PW_ERR ++;
+ break;
+ case AWSS_STATIS_TYPE_SCAN_START:
+ PAP_SSTART = time;
+ break;
+ case AWSS_STATIS_TYPE_SCAN_STOP:
+ PAP_SSTOP = time;
+ break;
+ case AWSS_STATIS_TYPE_SWITCHAP:
+ PAP_SAP ++;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#ifdef AWSS_SUPPORT_DEV_AP
+ case AWSS_STATIS_DAP_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ DAP_CNT ++;
+ DAP_START = time;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ DAP_SUC ++;
+ DAP_END = time;
+ time = (uint32_t)(DAP_END - DAP_START);
+ if (DAP_SUC > 0) {
+ DAP_TMEAN = (DAP_TMEAN + time) / (DAP_SUC);
+ } else {
+ DAP_TMEAN = time;
+ DAP_SUC = 1;
+ }
+ if (DAP_TMIN == 0 || DAP_TMIN > time)
+ DAP_TMIN = time;
+ if (DAP_TMAX == 0 || DAP_TMAX < time)
+ DAP_TMAX = time;
+ break;
+ case AWSS_STATIS_TYPE_PASSWD_ERR:
+ DAP_PW_ERR ++;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ case AWSS_STATIS_ROUTE_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ ROUTE_CNT ++;
+ ROUTE_START = time;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ ROUTE_SUC ++;
+ ROUTE_END = time;
+ time = (uint32_t)(ROUTE_END - ROUTE_START);
+ if (ROUTE_SUC > 0) {
+ ROUTE_TMEAN = (ROUTE_TMEAN + time) / (ROUTE_SUC);
+ } else {
+ ROUTE_TMEAN = time;
+ ROUTE_SUC = 1;
+ }
+
+ if (ROUTE_TMIN == 0 || ROUTE_TMIN > time)
+ ROUTE_TMIN = time;
+ if (ROUTE_TMAX == 0 || ROUTE_TMAX < time)
+ ROUTE_TMAX = time;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#ifndef AWSS_DISABLE_ENROLLEE
+ case AWSS_STATIS_ZCONFIG_IDX:
+ switch (type) {
+ case AWSS_STATIS_TYPE_TIME_START:
+ ZC_CNT ++;
+ break;
+ case AWSS_STATIS_TYPE_TIME_SUC:
+ ZC_SUC ++;
+ break;
+ case AWSS_STATIS_TYPE_PASSWD_ERR:
+ ZC_PW_ERR ++;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ HAL_MutexUnlock(awss_statis_mutex);
+}
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/statics/awss_statis.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/statics/awss_statis.h
new file mode 100644
index 00000000..19afd4dd
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/statics/awss_statis.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_STATIS_H__
+#define __AWSS_STATIS_H__
+
+#include
+#ifdef AWSS_SUPPORT_DEV_AP
+#include "awss_dev_ap.h"
+#endif
+
+enum {
+ AWSS_STATIS_CONN_ROUTER_IDX = 0, /* Statistic for connection with router */
+ AWSS_STATIS_SM_IDX, /* Statistic for smartconfig with bcast */
+ AWSS_STATIS_WPS_IDX, /* Statistic for smartconfig with wps */
+ AWSS_STATIS_PAP_IDX, /* Statistic for phone as AP */
+ AWSS_STATIS_DAP_IDX, /* Statistic for device AP */
+ AWSS_STATIS_ROUTE_IDX, /* Statistic for route solution */
+ AWSS_STATIS_ZCONFIG_IDX, /* Statistic for zero config */
+};
+
+enum {
+ AWSS_STATIS_TYPE_TIME_START = 0, /* Begining of operation */
+ AWSS_STATIS_TYPE_TIME_SUC, /* Success of operation */
+ AWSS_STATIS_TYPE_PASSWD_ERR, /* Failure of parsing PASSWD of router*/
+ AWSS_STATIS_TYPE_CRC_ERR, /* Failure of CRC check */
+ AWSS_STATIS_TYPE_SCAN_START, /* Start of scan operation */
+ AWSS_STATIS_TYPE_SCAN_STOP, /* Stop of scan operation */
+ AWSS_STATIS_TYPE_SWITCHAP /* Increase count of switch ap */
+};
+
+#ifndef AWSS_SUPPORT_STATIS
+#define AWSS_SUPPORT_STATIS
+#endif
+
+#ifdef AWSS_SUPPORT_STATIS
+
+struct awss_statis_conn_router_t {
+ uint32_t conn_router_cnt; /* the count of connect router */
+ uint32_t conn_router_suc; /* the success count of connect router */
+ uint32_t conn_router_time_mean; /* the mean time of success connection with router */
+ uint32_t conn_router_time_max; /* the max time of success connection with router */
+ uint32_t conn_router_time_min; /* the min time of success connection with router */
+ uint32_t conn_router_start; /* the start time to connect router */
+ uint32_t conn_router_end; /* the end time of connect router */
+}; /* statistics for connection with router */
+
+struct awss_statis_sm_t {
+ uint32_t sm_parse_cnt; /* the count of smartconfig */
+ uint32_t sm_parse_crc_err; /* the count of crc error */
+ uint32_t sm_parse_passwd_err; /* the count of passwd error */
+ uint32_t sm_parse_suc; /* the count of smartconfig success */
+ uint32_t sm_parse_start; /* the start time to smartconfig */
+ uint32_t sm_parse_end; /* the ene time of smartconfig */
+ uint32_t sm_time_mean; /* the mean time of smartconfig */
+ uint32_t sm_time_max; /* the max time of smartconfig */
+ uint32_t sm_time_min; /* the min time of smartconfig */
+}; /* smartconfig-bcast statistic */
+
+struct awss_statis_wps_t {
+ uint32_t wps_parse_cnt; /* the count of smartconfig-wps */
+ uint32_t wps_parse_crc_err; /* the count of crc error */
+ uint32_t wps_parse_passwd_err; /* the count of passwd error */
+ uint32_t wps_parse_suc; /* the count of smartconfig-wps success */
+}; /* smartconfig-wps statistic */
+
+struct awss_statis_phone_ap_t {
+ uint32_t aha_cnt;
+ uint32_t aha_suc;
+ uint32_t aha_time_mean; /* mean time of phone as AP solution */
+ uint32_t aha_time_max; /* max time of phone as AP solution */
+ uint32_t aha_time_min; /* min time of phone as AP solution */
+ uint32_t aha_start;
+ uint32_t aha_end;
+ uint32_t aha_scan_start;
+ uint32_t aha_scan_end;
+ uint32_t aha_switch_ap;
+ uint32_t aha_passwd_err;
+}; /* Phone as AP */
+
+struct awss_statis_dev_ap_t {
+ uint32_t dev_ap_cnt;
+ uint32_t dev_ap_suc;
+ uint32_t dev_ap_time_mean; /* mean time of device AP solution */
+ uint32_t dev_ap_time_max; /* max time of device AP solution */
+ uint32_t dev_ap_time_min; /* min time of device AP solution */
+ uint32_t dev_ap_start;
+ uint32_t dev_ap_end;
+ uint32_t dev_ap_passwd_err;
+}; /* device work as AP */
+
+struct awss_statis_route_t {
+ uint32_t adha_cnt;
+ uint32_t adha_suc;
+ uint32_t adha_time_mean; /* mean time of discovery of route solution */
+ uint32_t adha_time_max; /* min time of discovery of route solution */
+ uint32_t adha_time_min; /* max time of discovery of route solution */
+ uint32_t adha_start;
+ uint32_t adha_end;
+}; /* discovery of route solution */
+
+struct awss_statis_zconfig_t {
+ uint32_t zc_cnt;
+ uint32_t zc_suc;
+ uint32_t zc_passwd_err;
+}; /* zero configure solution */
+
+struct awss_statis_t {
+ struct awss_statis_conn_router_t droute;
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+ struct awss_statis_sm_t sm;
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+ struct awss_statis_wps_t wps;
+#endif
+#endif
+#ifdef AWSS_SUPPORT_AHA
+ struct awss_statis_phone_ap_t pap;
+#endif
+#ifdef AWSS_SUPPORT_DEV_AP
+ struct awss_statis_dev_ap_t dap;
+#endif
+#ifdef AWSS_SUPPORT_ADHA
+ struct awss_statis_route_t route;
+#endif
+#ifndef AWSS_DISABLE_ENROLLEE
+ struct awss_statis_zconfig_t zconfig;
+#endif
+};
+
+int awss_report_statis(const char *module);
+void awss_update_statis(int awss_statis_idx, int type);
+void awss_clear_statis();
+void awss_disp_statis();
+
+#define AWSS_UPDATE_STATIS(idx, type) awss_update_statis(idx, type)
+#define AWSS_CLEAR_STATIS() awss_clear_statis()
+#define AWSS_DISP_STATIS() awss_disp_statis()
+#define AWSS_REPORT_STATIS(m) awss_disp_statis(m)
+#else
+#define AWSS_UPDATE_STATIS(idx, type)
+#define AWSS_CLEAR_STATIS()
+#define AWSS_DISP_STATIS()
+#define AWSS_REPORT_STATIS(m)
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/awss_crypt.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/awss_crypt.c
new file mode 100644
index 00000000..48b72ab0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/awss_crypt.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+static const char *cal_passwd(void *key, void *random, void *passwd)
+{
+ uint16_t key_len;
+ uint8_t digest[SHA256_DIGEST_SIZE + 1] = {0};
+ uint8_t passwd_src[KEY_MAX_LEN + RANDOM_MAX_LEN + 2] = {0};
+
+ if (!passwd || !key || !random)
+ return NULL;
+
+ /* combine key and random, with split of comma */
+ key_len = strlen(key);
+ if (key_len > KEY_MAX_LEN)
+ key_len = KEY_MAX_LEN;
+ memcpy(passwd_src, key, key_len);
+ passwd_src[key_len ++] = ',';
+ memcpy(passwd_src + key_len, random, RANDOM_MAX_LEN);
+ key_len += RANDOM_MAX_LEN;
+
+ SHA256_hash(passwd_src, key_len, digest);
+ #if 0
+ TODO
+ /* produce digest using combination of key and random */
+ utils_sha256_hash(passwd_src, key_len, digest);
+#endif
+
+ /* use the first 128bits as AES-Key */
+ memcpy(passwd, digest, AES128_KEY_LEN);
+
+ return passwd;
+}
+
+int aes_decrypt_string(char *cipher, char *plain, int len, int cipher_hex, int sec_lvl, char cbc, const char *rand)
+{
+ char res = 0;
+ char decrypt = 1;
+ uint8_t iv[AES128_KEY_LEN] = {0};
+ uint8_t key[AES128_KEY_LEN] = {0};
+ uint8_t random[RANDOM_MAX_LEN] = {0};
+
+ uint8_t *decoded = (uint8_t *)os_zalloc(len + 1);
+ if (decoded == NULL)
+ return -1;
+
+ if (cipher_hex == 0) {
+ /*
+ * mobile-ap, router, dev-ap
+ */
+ utils_str_to_hex(cipher, len, decoded, len);
+ } else { /* for smartconfig/wps, zconfig, */
+ /*
+ * smartconfig/wps, zconfig
+ */
+ memcpy(decoded, cipher, len);
+ }
+
+ if (rand) {
+ /*
+ * smartconfig/wps uses zero
+ * zconfig/dev-ap/mobile-ap/router uses random
+ */
+ memcpy(random, rand, sizeof(random));
+ }
+
+ awss_debug("security level: %d", sec_lvl);
+
+ switch (sec_lvl) {
+ case SEC_LVL_AES128_PRODUCT:
+ {
+ char product_sec[OS_PRODUCT_SECRET_LEN + 1] = {0};
+ HAL_GetProductSecret(product_sec);
+ cal_passwd(product_sec, random, key);
+ memcpy(iv, random, sizeof(random));
+ break;
+ }
+ case SEC_LVL_AES128_DEVICE:
+ {
+ char dev_sec[OS_DEVICE_SECRET_LEN + 1] = {0};
+ HAL_GetDeviceSecret(dev_sec);
+ cal_passwd(dev_sec, random, key);
+ memcpy(iv, random, sizeof(random));
+ break;
+ }
+ default:
+ {
+ decrypt = 0;
+ awss_debug("wrong security level: %d\n", sec_lvl);
+ res = -2;
+ break;
+ }
+ }
+
+ plain[0] = '\0';
+
+ if (decrypt) {
+ p_aes128_t aes = HAL_Aes128_Init(key, iv, PLATFORM_AES_DECRYPTION);
+ if (cbc) { /* AP */
+ /*
+ * mobile-ap, dev-ap, router
+ */
+ res = HAL_Aes128_Cbc_Decrypt(aes, decoded, len / AES128_KEY_LEN / 2, plain);
+ } else { /* smartconfig */
+ /*
+ * smartconfig/wps, zconfig
+ */
+ res = HAL_Aes128_Cfb_Decrypt(aes, decoded, len, plain);
+ }
+ HAL_Aes128_Destroy(aes);
+ }
+
+ HAL_Free(decoded);
+
+ return res;
+}
+
+
+
+/**
+ * @brief 获取配网服务的安全等级
+ *
+ * @param None.
+ * @return The security level:
+ @verbatim
+ 0: open (no encrypt)
+ 1: aes256cfb with default aes-key and aes-iv
+ 2: aes128cfb with default aes-key and aes-iv
+ 3: aes128cfb with aes-key per product and aes-iv = 0
+ 4: aes128cfb with aes-key per device and aes-iv = 0
+ 5: aes128cfb with aes-key per manufacture and aes-iv = 0
+ others: invalid
+ @endverbatim
+ * @see None.
+ */
+
+int awss_get_encrypt_type()
+{
+ return 3;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/awss_crypt.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/awss_crypt.h
new file mode 100644
index 00000000..8b80c27e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/awss_crypt.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_CRYPT_H__
+#define __AWSS_CRYPT_H__
+
+enum {
+ SEC_LVL_OPEN = 0, /* open */
+ SEC_LVL_AES256, /* AES256 */
+ SEC_LVL_AES128_DEFAULT, /* AES128 with default key */
+ SEC_LVL_AES128_PRODUCT, /* AES128 with key from product_sec */
+ SEC_LVL_AES128_DEVICE, /* AES128 with key from device_sec */
+ SEC_LVL_AES128_MANU, /* AES128 with key from manufacturer_sec */
+};
+
+int aes_decrypt_string(char *cipher, char *plain, int len, int cipher_hex, int sec_lvl, char cbc, const char *rand);
+
+int awss_get_encrypt_type();
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/zconfig_utils.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/zconfig_utils.c
new file mode 100644
index 00000000..54b2ac64
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/zconfig_utils.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+void dump_hex(uint8_t *data, int len, int tab_num)
+{
+ int i;
+ for (i = 0; i < len; i++) {
+ HAL_Printf("%02x ", data[i]);
+
+ if (!((i + 1) % tab_num))
+ HAL_Printf("\r\n");
+ }
+
+ HAL_Printf("\r\n");
+}
+#if 0
+void dump_ascii(uint8_t *data, int len, int tab_num)
+{
+ int i;
+ for (i = 0; i < len; i++) {
+ HAL_Printf("%-2c ", data[i]);
+
+ if (!((i + 1) % tab_num))
+ HAL_Printf(" ");
+ }
+
+ HAL_Printf("\r\n");
+}
+
+void dump_mac(uint8_t *src, uint8_t *dst)
+{
+ uint8_t *mac;
+
+ mac = src;
+ HAL_Printf("%02x:%02x:%02x:%02x:%02x:%02x > ",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ mac = dst;
+ HAL_Printf("%02x:%02x:%02x:%02x:%02x:%02x\r\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ /* elimite compiler warning */
+ mac = mac;
+}
+#endif
+/* for smartconfig with encrypt */
+uint16_t zconfig_checksum_v3(uint8_t *data, uint8_t len)
+{
+ uint8_t i;
+ uint16_t sum = 0, res;
+
+ for (i = 0; i < len; i++)
+ sum += data[i];
+
+ res = sum & (0x3F << 0);
+ res |= (sum & (0x3F << 6)) << 2;
+
+ if (!(res & 0x00FF))
+ res |= 0x0001;
+ if (!(res & 0xFF00))
+ res |= 0x0100;
+
+ return res;
+}
+
+char is_utf8(const char *ansi_str, int length)
+{
+ int i = 0;
+ char utf8 = 1;
+ while (i < length) {
+ if ((0x80 & ansi_str[i]) == 0) { /* ASCII */
+ i++;
+ continue;
+ } else if ((0xE0 & ansi_str[i]) == 0xC0) { /* 110xxxxx */
+ if (ansi_str[i + 1] == '\0') {
+ utf8 = 0;
+ break;
+ }
+ if ((0xC0 & ansi_str[i + 1]) == 0x80) { /* 10xxxxxx */
+ i += 2;
+ continue;
+ } else {
+ utf8 = 0;
+ break;
+ }
+ } else if ((0xF0 & ansi_str[i]) == 0xE0) { /* 1110xxxx */
+ if (ansi_str[i + 1] == '\0') {
+ utf8 = 0;
+ break;
+ }
+ if (ansi_str[i + 2] == '\0') {
+ utf8 = 0;
+ break;
+ }
+ if (((0xC0 & ansi_str[i + 1]) == 0x80) && ((0xC0 & ansi_str[i + 2]) == 0x80)) { /* 10xxxxxx 10xxxxxx */
+ i += 3;
+ continue;
+ } else {
+ utf8 = 0;
+ break;
+ }
+ } else {
+ utf8 = 0;
+ break;
+ }
+ }
+ return utf8;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/zconfig_utils.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/zconfig_utils.h
new file mode 100644
index 00000000..d738bb7a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/utils/zconfig_utils.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __ZCONFIG_UTILS_H__
+#define __ZCONFIG_UTILS_H__
+
+#include "os.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+void dump_mac(uint8_t *src, uint8_t *dst);
+void dump_hex(uint8_t *data, int len, int tab_num);
+void dump_ascii(uint8_t *data, int len, int tab_num);
+
+uint16_t zconfig_checksum_v3(uint8_t *data, uint8_t len);
+char is_utf8(const char *ansi_str, int length);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_lib.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_lib.h
new file mode 100644
index 00000000..32da0cfa
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_lib.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __ZCONFIG_LIB_H__
+#define __ZCONFIG_LIB_H__
+
+#include "os.h"
+
+#ifndef ETH_ALEN
+#define ETH_ALEN (6)
+#endif
+
+#define ZC_MAX_SSID_LEN (32 + 1)/* ssid: 32 octets at most, include the NULL-terminated */
+#define ZC_MAX_PASSWD_LEN (64 + 1)/* 8-63 ascii */
+#define MAX_APLIST_NUM (100)
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+enum _ZC_AUTH_TYPE_ {
+ ZC_AUTH_TYPE_OPEN,
+ ZC_AUTH_TYPE_SHARED,
+ ZC_AUTH_TYPE_WPAPSK,
+ ZC_AUTH_TYPE_WPA8021X,
+ ZC_AUTH_TYPE_WPA2PSK,
+ ZC_AUTH_TYPE_WPA28021X,
+ ZC_AUTH_TYPE_WPAPSKWPA2PSK,
+ ZC_AUTH_TYPE_MAX = ZC_AUTH_TYPE_WPAPSKWPA2PSK,
+ ZC_AUTH_TYPE_INVALID = 0xff,
+};
+
+enum _ZC_ENC_TYPE_ {
+ ZC_ENC_TYPE_NONE,
+ ZC_ENC_TYPE_WEP,
+ ZC_ENC_TYPE_TKIP,
+ ZC_ENC_TYPE_AES,
+ ZC_ENC_TYPE_TKIPAES,
+ ZC_ENC_TYPE_MAX = ZC_ENC_TYPE_TKIPAES,
+ ZC_ENC_TYPE_INVALID = 0xff,
+};
+
+enum _ZC_PKG_TYPE_ {
+ PKG_INVALID, /* invalid pkg, --无效包 */
+ PKG_BC_FRAME, /* broadcast frame, --信道扫描阶段,收到收到该返回值建议延长在当前信道停留时间,可以延长T1 */
+ PKG_START_FRAME, /* start frame, --信道扫描阶段,收到该返回值用于锁定信道 */
+ PKG_DATA_FRAME, /* data frame, --数据包,锁定信道后长时间T2收不到数据包,需重新进入扫描阶段 */
+ PKG_ALINK_ROUTER, /* alink router */
+ PKG_GROUP_FRAME, /* group frame */
+ PKG_END /* --配网结束事件,已拿到ssid和passwd,通过回调函数去获取ssid和passwd */
+ /*
+ * 参考值:
+ * T1: 400ms >= T2 >= 100ms
+ * T2: 3s
+ */
+};
+
+/*进入monitor模式前后调用该函数 */
+void zconfig_init();
+/* 配网成功后,调用该函数,释放内存资源 */
+void zconfig_destroy(void);
+/*
+ 进入monitor/sniffer模式后,将收到的包传给该函数进行处理
+ 若进入monitor时进行包过滤配置,以下几种包不能过滤:
+ 1) 数据包,目的地址为广播地址
+ 2) 长度>40的管理帧
+ 厂家需要自行切换信道,切信道时间按照自身平台需要进行调整,建议取值范围[100ms - 300ms]
+ 其中,6号信道需作为固定信道放在信道列表里!!!
+ input:
+ pkt_data: 80211 wireless raw package, include data frame & management frame
+ pkt_length: radio_hdr + 80211 hdr + payload, without fcs(4B)
+ return:
+ 见enum _PKG_TYPE_结构体说明
+*/
+int zconfig_recv_callback(void *pkt_data, uint32_t pkt_length, uint8_t channel,
+ int link_type, int with_fcs, signed char rssi);
+
+/*
+ * save apinfo
+ * 0 -- success, otherwise, failed.
+ */
+int zconfig_set_apinfo(uint8_t *ssid, uint8_t* bssid, uint8_t channel, uint8_t auth,
+ uint8_t pairwise_cipher, uint8_t group_cipher, signed char rssi);
+
+uint8_t zconfig_get_lock_chn(void);
+
+/* add channel to global scanning channel list */
+int zconfig_add_active_channel(int channel);
+/* channel locked callback */
+void zconfig_channel_locked_callback(uint8_t primary_channel,
+ uint8_t secondary_channel, uint8_t *bssid);
+/* got ssid&passwd callback */
+void zconfig_got_ssid_passwd_callback(uint8_t *ssid, uint8_t *passwd, uint8_t *bssid,
+ uint8_t auth, uint8_t encry, uint8_t channel);
+void zconfig_force_rescan(void);
+void aws_set_dst_chan(int channel);
+void aws_switch_channel(void);
+void aws_release_mutex(void);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_protocol.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_protocol.c
new file mode 100644
index 00000000..4128a60c
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_protocol.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+/* broadcast mac address */
+uint8_t br_mac[ETH_ALEN];
+/* all zero mac address */
+uint8_t zero_mac[ETH_ALEN];
+
+/* which channel lock at */
+uint8_t zconfig_channel_locked = INVALID_CHANNEL;/* locked channel */
+/*
+ * avoid zconfig_callback_over() was called twice,
+ * once from tods, once from fromds
+ */
+uint8_t zconfig_finished;
+
+/* global data structure, which hold all broadcast data */
+struct zconfig_data *zconfig_data;
+
+/*
+ * 8bit -> x bit
+ *
+ * serialize chinese char from 8bit to x bit
+ */
+void encode_chinese(uint8_t *in, uint8_t in_len,
+ uint8_t *out, uint8_t *out_len, uint8_t bits)
+{
+ if (bits == 0 || bits > 7) {
+ return;
+ }
+
+ do {
+ uint8_t i, j;
+ uint8_t bit[ZC_MAX_SSID_LEN * 8] = {0};
+ uint8_t output_len = ((in_len * 8) + bits - 1) / bits;
+
+ /* char to bit stream */
+ for (i = 0; i < in_len; i ++) {
+ for (j = 0; j < 8; j ++) {
+ bit[i * 8 + j] = (in[i] >> j) & 0x01;
+ }
+ }
+
+ out[output_len] = '\0'; /* NULL-terminated */
+ for (i = 0; i < output_len; i ++) {
+ for (j = 0, out[i] = 0; j < bits; j ++) {
+ out[i] |= bit[i * bits + j] << j;
+ }
+ }
+
+ if (out_len) {
+ *out_len = output_len;
+ }
+ } while (0);
+}
+
+/* x bit -> 8bit */
+void decode_chinese(uint8_t *in, uint8_t in_len,
+ uint8_t *out, uint8_t *out_len, uint8_t bits)
+{
+ if (bits == 0 || bits > 7 || in_len == 0) {
+ return;
+ }
+
+ do {
+ uint8_t i, j;
+ uint8_t output_len = (in_len * bits) / 8;
+ uint8_t *bit = (uint8_t *)os_zalloc(in_len * bits);
+
+ if (bit == NULL) {
+ awss_crit("decode malloc failed!\r\n");
+ return;
+ }
+
+ /* char to bit stream */
+ for (i = 0; i < in_len; i ++) {
+ for (j = 0; j < bits; j ++) {
+ bit[i * bits + j] = (in[i] >> j) & 0x01;
+ }
+ }
+
+ out[output_len] = '\0'; /* NULL-terminated */
+ for (i = 0; i < output_len; i++) {
+ for (j = 0, out[i] = 0; j < 8; j ++) {
+ out[i] |= bit[i * 8 + j] << j;
+ }
+ }
+
+ HAL_Free(bit);
+ if (out_len) {
+ *out_len = output_len;
+ }
+ } while (0);
+}
+
+/*
+ * 1/locked, 0/not locked
+ */
+uint8_t is_channel_locked(void)
+{
+ return zconfig_channel_locked != INVALID_CHANNEL;
+}
+
+/*
+ * Note: this notification will be kept called, in case of
+ * user clear the channel locked state to re-scanning
+ * channel because of waiting timeout.
+ */
+uint8_t zconfig_callback_channel_locked(uint8_t channel)
+{
+ if (channel != zconfig_channel_locked) {
+ awss_info("channel lock @ %d\r\n", channel);
+ zconfig_channel_locked = channel;
+ }
+
+ /*
+ * if recv timeout, vendor may re-scanning channel,
+ * so keep calling channel locked notification here.
+ */
+ zconfig_channel_locked_callback(channel, 0, zc_bssid);
+
+ return 0;
+}
+
+uint8_t zconfig_callback_over(uint8_t *ssid, uint8_t *passwd, uint8_t *bssid)
+{
+ uint8_t auth = ZC_AUTH_TYPE_INVALID, encry = ZC_ENC_TYPE_INVALID, channel = 0;
+
+ awss_info("zconfig done. ssid:%s, mac:%02x%02x%02x%02x%02x%02x\r\n",
+ ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+
+ if (zconfig_finished) {
+ return 0;
+ }
+
+#ifdef AWSS_SUPPORT_APLIST
+ awss_get_auth_info(ssid, bssid, &auth, &encry, &channel);
+#endif
+
+ zconfig_got_ssid_passwd_callback(ssid, passwd, bssid, auth, encry, channel);
+
+ zconfig_finished = 1;
+
+ HAL_Awss_Close_Monitor();
+
+ return 0;
+}
+
+void zconfig_set_state(uint8_t state, uint8_t tods, uint8_t channel)
+{
+ /* state change callback */
+ switch (state) {
+ case STATE_CHN_SCANNING:
+ break;
+ case STATE_CHN_LOCKED_BY_P2P:
+ /* locked state used by action/wps frame */
+ zconfig_callback_channel_locked(channel);
+ break;
+ case STATE_CHN_LOCKED_BY_BR:
+ /* locked state used by br frame */
+ zconfig_callback_channel_locked(zc_channel ? zc_channel : channel);
+ break;
+ case STATE_RCV_DONE:
+ /* prevent main_thread_func to free zconfig_data until curent task is finished. */
+ HAL_MutexLock(zc_mutex);
+ /*
+ * in case of p2p/router, direct into RCV_DONE state,
+ * skiped the chn lock state, so better to call channel lock here
+ */
+ if (!is_channel_locked()) {
+ zconfig_callback_channel_locked(channel);
+ }
+ zconfig_callback_over(zc_ssid, zc_passwd, zc_bssid);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * state machine loop:
+ * scanning -> p2p lock -> rcv_done
+ * scanning -> (p2p) rcv_done
+ * scanning -> br lock -> (br) rcv_done
+ * scanning -> br lock -> (p2p) recv_done
+ * scanning -> p2p lock -> br lock -> (br) recv_done
+ *
+ * watch out zc_state rolling back.
+ * zconfig_set_state(CHN_LOCKED) will be called more than once,
+ */
+ if (zc_state < state) {
+ zc_state = state;
+ }
+ if (state == STATE_RCV_DONE) {
+ HAL_MutexUnlock(zc_mutex);
+ }
+}
+
+/*
+ pkt_data & pkt_length:
+ radio_hdr + 80211 hdr + payload, without fcs(4B)
+ return:
+ PKG_INVALID -- invalid pkt,
+ PKG_START_FRAME -- start frame,
+ PKG_DATA_FRAME -- data frame,
+ PKG_ALINK_ROUTER -- alink router,
+ PKG_GROUP_FRAME -- group frame,
+ PKG_BC_FRAME -- broadcast frame
+*/
+int is_invalid_pkg(void *pkt_data, uint32_t pkt_length)
+{
+#define MIN_PKG (33)
+#define MAX_PKG (1480 + 56 + 200)
+ if (pkt_length < MIN_PKG || pkt_length > MAX_PKG) {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * zconfig_recv_callback()
+ *
+ * ieee80211 package parser
+ *
+ * @Return:
+ * zconfig state
+ */
+int zconfig_recv_callback(void *pkt_data, uint32_t pkt_length, uint8_t channel,
+ int link_type, int with_fcs, signed char rssi)
+{
+ int pkt_type = PKG_INVALID;
+ struct parser_res res;
+ memset(&res, 0, sizeof(res));
+
+ /* remove FCS filed */
+ if (with_fcs) {
+ pkt_length -= 4;
+ }
+
+ /* useless, will be removed */
+ if (is_invalid_pkg(pkt_data, pkt_length)) {
+ return PKG_INVALID;
+ }
+
+ res.channel = channel;
+
+ pkt_type = ieee80211_data_extract(pkt_data, pkt_length, link_type, &res, rssi);
+
+ return pkt_type;
+}
+
+/* init mem & timer */
+void zconfig_init()
+{
+ awss_info("%s\r\n", __func__);
+
+ zconfig_channel_locked = INVALID_CHANNEL;
+ zconfig_finished = 0;
+
+ memset(br_mac, 0xff, ETH_ALEN);
+ memset(zero_mac, 0x00, ETH_ALEN);
+
+ zconfig_data = (struct zconfig_data *)os_zalloc(sizeof(struct zconfig_data));
+ if (zconfig_data == NULL) {
+ goto ZCONFIG_INIT_FAIL;
+ }
+ zc_mutex = HAL_MutexCreate();
+ if (zc_mutex == NULL) {
+ goto ZCONFIG_INIT_FAIL;
+ }
+
+#ifdef AWSS_SUPPORT_APLIST
+ if (awss_init_ieee80211_aplist()) {
+ goto ZCONFIG_INIT_FAIL;
+ }
+#endif
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ if (awss_init_adha_aplist()) {
+ goto ZCONFIG_INIT_FAIL;
+ }
+#endif
+
+#ifdef AWSS_SUPPORT_HT40
+ ht40_init();
+#endif
+ return;
+
+ZCONFIG_INIT_FAIL:
+ awss_crit("malloc failed!\r\n");
+ zconfig_destroy();
+
+#ifdef AWSS_SUPPORT_APLIST
+ awss_deinit_ieee80211_aplist();
+#endif
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ awss_deinit_adha_aplist();
+#endif
+ return;
+}
+
+void zconfig_destroy(void)
+{
+ if (zconfig_data) {
+ if (zc_mutex) {
+ HAL_MutexDestroy(zc_mutex);
+ }
+ HAL_Free((void *)zconfig_data);
+ zconfig_data = NULL;
+ }
+}
+
+void zconfig_force_destroy(void)
+{
+ zconfig_destroy();
+
+#ifdef AWSS_SUPPORT_APLIST
+ awss_deinit_ieee80211_aplist();
+ awss_close_aplist_monitor();
+#endif
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ awss_deinit_adha_aplist();
+#endif
+}
+
+int zconfig_is_valid_channel(int channel)
+{
+ return (ZC_MIN_CHANNEL <= channel && channel <= ZC_MAX_CHANNEL);
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_protocol.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_protocol.h
new file mode 100644
index 00000000..57024637
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_protocol.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __ZCONFIG_PROTOCOL_H__
+#define __ZCONFIG_PROTOCOL_H__
+
+#include
+#include "zconfig_utils.h"
+#include "zconfig_ieee80211.h"
+#include "zconfig_lib.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+enum state_machine {
+ STATE_CHN_SCANNING,
+ STATE_CHN_LOCKED_BY_P2P, /* wps/action used for enrollee */
+ STATE_CHN_LOCKED_BY_BR, /* broadcast used for smartconfig */
+ STATE_GOT_BEACON,
+ STATE_RCV_IN_PROGRESS,
+ STATE_RCV_COMPLETE,
+ STATE_RCV_DONE
+};
+
+enum _GOT_RESULT_ {
+ GOT_NOTHING = 0,
+ GOT_CHN_LOCK = 1,
+ GOT_SSID_PASSWD = 2,
+};
+
+#define PASSWD_ENCRYPT_BIT_OFFSET (1)
+#define PASSWD_ENCRYPT_MASK (0x06)
+#define SSID_EXIST_BIT (0)
+#define SSID_EXIST_MASK (1 << SSID_EXIST_BIT)
+#define SSID_ENCODE_BIT (5)
+#define SSID_ENCODE_MASK (1 << SSID_ENCODE_BIT)
+
+enum passwd_encpyt_type {
+ PASSWD_ENCRYPT_OPEN = 0,
+ PASSWD_ENCRYPT_CIPHER,
+ PASSWD_ENCRYPT_AESCFB,
+ PASSWD_ENCRYPT_AESOFB,
+};
+
+#define flag_tods(tods) ((tods) ? 'T' : 'F')
+
+#define ZC_MAX_CHANNEL (14)
+#define ZC_MIN_CHANNEL (1)
+int zconfig_is_valid_channel(int channel);
+
+#define P2P_ENCODE_TYPE_OFFSET (0x05)
+#define P2P_SSID_LEN_MASK ((1 << P2P_ENCODE_TYPE_OFFSET) - 1)
+#define P2P_ENCRYPT_BIT_MASK ((uint8_t)(~P2P_SSID_LEN_MASK))
+enum p2p_encode_type {
+ P2P_ENCODE_TYPE_DICT = 0x00,
+ P2P_ENCODE_TYPE_ENCRYPT,
+};
+
+/* global data */
+/* max: 48(ssid gbk encode) + 64 (passwd) + 6 (1(tlen) + 1(flag) + 1(ssid_len) + 1(passwd_len) + 2(crc)) */
+#define MAX_PKG_NUMS (128)
+
+/* zconfig protocol */
+#define START_FRAME (0x4E0) /* 0x4E0 is group 0 */
+#define GROUP_FRAME (0x3E0) /* exclusive, 0x401 is group 1, 0x400 is not used */
+#define GROUP_FRAME_END (GROUP_FRAME + MAX_PKG_NUMS / GROUP_NUMBER) /* exclusive */
+#define GROUP_NUMBER (8)
+#define ZC_GRP_PKT_IDX_START (2)
+#define ZC_GRP_PKT_IDX_END (ZC_GRP_PKT_IDX_START + GROUP_NUMBER - 1)
+
+struct package {
+ uint16_t len;
+ char score;
+};
+
+struct zconfig_data {
+ struct {
+ uint8_t state_machine; /* state for tods/fromds */
+ uint8_t frame_offset; /* frame fixed offset */
+ uint8_t group_pos; /* latest group pkg pos */
+ uint8_t cur_pos; /* data abs. position */
+ uint8_t max_pos; /* data max len */
+ uint8_t last_index;
+ uint8_t replace; /* whether pkg has been replaced recently */
+ uint8_t score_uplimit;
+#define score_max (100)
+#define score_high (98)
+#define score_mid (50)
+#define score_low (1)
+#define score_min (0)
+
+ uint8_t pos_unsync;
+ uint16_t group_sn; /* latest group pkg sn */
+ uint16_t prev_sn; /* last sn */
+ uint16_t last_len; /* len pkg len */
+ uint32_t timestamp; /* last timestamp */
+#define time_interval (300) /* ms */
+ } data[2];
+
+ /* package store */
+ struct package pkg[2][MAX_PKG_NUMS];
+ struct package tmp_pkg[2][GROUP_NUMBER + 1];
+ uint8_t src_mac[ETH_ALEN];
+ uint8_t channel; /* from 1 -- 13 */
+
+ /* result, final result */
+ uint8_t ssid[ZC_MAX_SSID_LEN];
+ uint8_t passwd[ZC_MAX_PASSWD_LEN];
+ uint8_t bssid[ETH_ALEN];
+ uint8_t ssid_is_gbk;
+ uint8_t ssid_auto_complete_disable;
+
+ /* used by v2 android p2p protocol, for gbk ssid correctness */
+ uint8_t android_pre_ssid[ZC_MAX_SSID_LEN];
+ uint8_t android_ssid[ZC_MAX_SSID_LEN];
+ uint8_t android_bssid[ETH_ALEN];
+ uint8_t android_src[ETH_ALEN];
+ void *mutex;
+};
+
+#define zc_state zconfig_data->data[tods].state_machine
+#define zc_frame_offset zconfig_data->data[tods].frame_offset
+#define zc_group_pos zconfig_data->data[tods].group_pos
+#define zc_group_sn zconfig_data->data[tods].group_sn
+#define zc_prev_sn zconfig_data->data[tods].prev_sn
+#define zc_cur_pos zconfig_data->data[tods].cur_pos
+#define zc_max_pos zconfig_data->data[tods].max_pos
+#define zc_last_index zconfig_data->data[tods].last_index
+#define zc_last_len zconfig_data->data[tods].last_len
+#define zc_replace zconfig_data->data[tods].replace
+#define zc_score_uplimit zconfig_data->data[tods].score_uplimit
+#define zc_timestamp zconfig_data->data[tods].timestamp
+#define zc_pos_unsync zconfig_data->data[tods].pos_unsync
+
+#define zc_src_mac &zconfig_data->src_mac[0]
+
+#define zc_channel zconfig_data->channel
+
+#define zc_ssid (&zconfig_data->ssid[0])
+#define zc_passwd (&zconfig_data->passwd[0])
+#define zc_bssid (&zconfig_data->bssid[0])
+#define zc_ssid_is_gbk (zconfig_data->ssid_is_gbk)
+#define zc_ssid_auto_complete_disable (zconfig_data->ssid_auto_complete_disable)
+
+#define pkg_score(n) zconfig_data->pkg[tods][n].score
+#define pkg_len(n) zconfig_data->pkg[tods][n].len
+#define pkg(n) &zconfig_data->pkg[tods][n]
+
+#define tmp_score(n) zconfig_data->tmp_pkg[tods][n].score
+#define tmp_len(n) zconfig_data->tmp_pkg[tods][n].len
+#define tmp(n) &zconfig_data->tmp_pkg[tods][n]
+
+#define zc_pre_ssid (&zconfig_data->android_pre_ssid[0])
+#define zc_android_ssid (&zconfig_data->android_ssid[0])
+#define zc_android_bssid (&zconfig_data->android_bssid[0])
+#define zc_android_src (&zconfig_data->android_src[0])
+#define zc_mutex zconfig_data->mutex
+
+void zconfig_force_destroy(void);
+void encode_chinese(uint8_t *in, uint8_t in_len, uint8_t *out, uint8_t *out_len, uint8_t bits);
+void decode_chinese(uint8_t *in, uint8_t in_len, uint8_t *out, uint8_t *out_len, uint8_t bits);
+void zconfig_set_state(uint8_t state, uint8_t tods, uint8_t channel);
+int is_ascii_string(uint8_t *str);
+
+/*
+ * [IN] ssid or bssid
+ * [OUT] auth, encry, channel
+ */
+uint8_t zconfig_get_auth_info(uint8_t *ssid, uint8_t *bssid, uint8_t *auth, uint8_t *encry, uint8_t *channel);
+uint8_t zconfig_callback_over(uint8_t *ssid, uint8_t *passwd, uint8_t *bssid);
+
+#define MAC_FORMAT "%02x%02x%02x%02x%02x%02x"
+#define MAC_VALUE(mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
+
+extern const char *zc_default_ssid;
+extern const char *zc_default_passwd;
+extern struct zconfig_data *zconfig_data;
+extern uint8_t zconfig_finished;
+/* broadcast mac address */
+extern uint8_t br_mac[ETH_ALEN];
+/* all zero mac address */
+extern uint8_t zero_mac[ETH_ALEN];
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif /* __IEEE80211_123_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_vendor_common.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_vendor_common.c
new file mode 100644
index 00000000..43e8eaf4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/frameworks/zconfig_vendor_common.c
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+/* aws state machine */
+enum {
+ /* used by aws_state */
+ AWS_SCANNING,
+ AWS_CHN_LOCKED,
+ AWS_SUCCESS,
+ AWS_TIMEOUT,
+
+ /* used by aws_stop */
+ AWS_STOPPING,
+ AWS_STOPPED
+};
+
+struct aws_info {
+ uint8_t state;
+
+ uint8_t cur_chn; /* current working channel */
+ uint8_t chn_index;
+
+ uint8_t locked_chn;
+
+#define AWS_MAX_CHN_NUMS (2 * 13 + 5) /* +5 for safety gap */
+ uint8_t chn_list[AWS_MAX_CHN_NUMS];
+ uint8_t stop;
+
+ uint32_t chn_timestamp;/* channel start time */
+ uint32_t start_timestamp;/* aws start time */
+} *aws_info;
+
+#define aws_state (aws_info->state)
+#define aws_locked_chn (aws_info->locked_chn)
+#define aws_cur_chn (aws_info->cur_chn)
+#define aws_chn_index (aws_info->chn_index)
+#define aws_chn_list (aws_info->chn_list)
+#define aws_chn_timestamp (aws_info->chn_timestamp)
+#define aws_start_timestamp (aws_info->start_timestamp)
+#define aws_stop (aws_info->stop)
+
+#define aws_channel_lock_timeout_ms (8 * 1000)
+
+static const uint8_t aws_fixed_scanning_channels[] = {
+ 1, 6, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
+};
+
+static void *rescan_timer = NULL;
+
+static void rescan_monitor(void);
+
+#define RESCAN_MONITOR_TIMEOUT_MS (5 * 60 * 1000)
+static uint8_t rescan_available = 0;
+
+/*
+ * sniffer result/storage
+ * use global variable/buffer to keep it usable after zconfig_destroy
+ */
+uint8_t aws_result_ssid[ZC_MAX_SSID_LEN + 1];
+uint8_t aws_result_passwd[ZC_MAX_PASSWD_LEN + 1];
+uint8_t aws_result_bssid[ETH_ALEN];/* mac addr */
+uint8_t aws_result_channel = 0;
+uint8_t aws_result_encry;
+uint8_t aws_result_auth;
+
+int aws_80211_frame_handler(char *, int, enum AWSS_LINK_TYPE, int, signed char);
+
+uint8_t zconfig_get_lock_chn(void)
+{
+ return aws_locked_chn;
+}
+
+void zconfig_force_rescan(void)
+{
+ if (aws_info) {
+ aws_state = AWS_SCANNING;
+ }
+}
+
+void zconfig_channel_locked_callback(uint8_t primary_channel,
+ uint8_t secondary_channel, uint8_t *bssid)
+{
+ aws_locked_chn = primary_channel;
+
+ if (aws_state == AWS_SCANNING) {
+ aws_state = AWS_CHN_LOCKED;
+ }
+
+ awss_event_post(IOTX_AWSS_LOCK_CHAN);
+}
+
+void zconfig_got_ssid_passwd_callback(uint8_t *ssid, uint8_t *passwd,
+ uint8_t *bssid, uint8_t auth, uint8_t encry, uint8_t channel)
+{
+ if (bssid) {
+ awss_debug("ssid:%s, bssid:%02x%02x%02x%02x%02x%02x, %d\r\n",
+ ssid, bssid[0], bssid[1], bssid[2],
+ bssid[3], bssid[4], bssid[5], channel);
+ } else {
+ awss_debug("ssid:%s, bssid:--, %d\r\n",
+ ssid, channel);
+ }
+
+ memset(aws_result_ssid, 0, sizeof(aws_result_ssid));
+ memset(aws_result_passwd, 0, sizeof(aws_result_passwd));
+ strncpy((char *)aws_result_ssid, (const char *)ssid, ZC_MAX_SSID_LEN - 1);
+ strncpy((char *)aws_result_passwd, (const char *)passwd, ZC_MAX_PASSWD_LEN - 1);
+
+ if (bssid) {
+ memcpy(aws_result_bssid, bssid, ETH_ALEN);
+ }
+ aws_result_auth = auth;
+ aws_result_encry = encry;
+ aws_result_channel = channel;
+
+ aws_state = AWS_SUCCESS;
+
+ awss_event_post(IOTX_AWSS_GOT_SSID_PASSWD);
+}
+
+uint8_t aws_next_channel(void)
+{
+ /* aws_chn_index start from -1 */
+ while (1) {
+ aws_chn_index ++;
+ if (aws_chn_index >= AWS_MAX_CHN_NUMS) {
+ aws_chn_index = 0; /* rollback to start */
+ }
+
+ if (aws_chn_list[aws_chn_index]) { /* valid channel */
+ break;
+ }
+ }
+
+ aws_cur_chn = aws_chn_list[aws_chn_index];
+
+ return aws_cur_chn;
+}
+
+static void aws_switch_dst_chan(int channel);
+static int aws_amend_dst_chan = 0;
+void aws_switch_channel(void)
+{
+ HAL_MutexLock(zc_mutex);
+ if (aws_amend_dst_chan != 0) {
+ aws_switch_dst_chan(aws_amend_dst_chan);
+ aws_amend_dst_chan = 0;
+ HAL_MutexUnlock(zc_mutex);
+ return;
+ }
+
+ if (aws_state == AWS_CHN_LOCKED) {
+ HAL_MutexUnlock(zc_mutex);
+ return;
+ }
+
+ do {
+ int channel = aws_next_channel();
+ aws_chn_timestamp = os_get_time_ms();
+ HAL_Awss_Switch_Channel(channel, 0, NULL);
+ awss_trace("chan %d\r\n", channel);
+ } while (0);
+ HAL_MutexUnlock(zc_mutex);
+}
+
+void aws_set_dst_chan(int channel)
+{
+ HAL_MutexLock(zc_mutex);
+ aws_amend_dst_chan = channel;
+ HAL_MutexUnlock(zc_mutex);
+}
+
+static void aws_switch_dst_chan(int channel)
+{
+ int i = aws_chn_index;
+ for (; i < AWS_MAX_CHN_NUMS; i ++) {
+ if (aws_chn_list[i] == 0) {
+ continue;
+ }
+ if (aws_chn_list[i] == channel) {
+ break;
+ }
+ }
+
+ if (i >= AWS_MAX_CHN_NUMS) {
+ for (i = 0; i < aws_chn_index; i ++) {
+ if (aws_chn_list[i] == 0) {
+ continue;
+ }
+ if (aws_chn_list[i] == channel) {
+ break;
+ }
+ }
+ }
+
+ if (i == aws_chn_index) { /* no need to switch channel. */
+ return;
+ }
+
+ aws_chn_index = i;
+ aws_locked_chn = channel;
+ aws_cur_chn = channel;
+ aws_chn_timestamp = os_get_time_ms();
+ if (aws_state == AWS_SCANNING) {
+ aws_state = AWS_CHN_LOCKED;
+ }
+ HAL_Awss_Switch_Channel(channel, 0, NULL);
+
+ awss_trace("adjust chan %d\r\n", channel);
+}
+
+enum {
+ CHNSCAN_ONGOING, /* no timeout, continue */
+ CHNSCAN_NEXT_CHN, /* should swith to next channel */
+ CHNSCAN_TIMEOUT /* aws timeout */
+};
+
+int aws_is_chnscan_timeout(void)
+{
+ if (aws_stop == AWS_STOPPING) {
+ awss_debug("aws will stop...\r\n");
+ return CHNSCAN_TIMEOUT;
+ }
+
+ if (time_elapsed_ms_since(aws_chn_timestamp) > HAL_Awss_Get_Channelscan_Interval_Ms()) {
+ if ((0 != HAL_Awss_Get_Timeout_Interval_Ms()) &&
+ (time_elapsed_ms_since(aws_start_timestamp) > HAL_Awss_Get_Timeout_Interval_Ms())) {
+ return CHNSCAN_TIMEOUT;
+ } else {
+ return CHNSCAN_NEXT_CHN;
+ }
+ }
+
+ return CHNSCAN_ONGOING;
+}
+
+int zconfig_add_active_channel(int channel)
+{
+ int fixed_channel_nums = sizeof(aws_fixed_scanning_channels);
+
+ if (!zconfig_is_valid_channel(channel)) {
+ return -1;
+ }
+
+ aws_chn_list[fixed_channel_nums + channel] = channel;
+ return 0;
+}
+
+/*
+ * channel scanning/re-scanning control
+ * Note: 修改该函数时,需考虑到各平台差异
+ * 庆科平台:
+ * --aws_switch_channel() 为空
+ * --zconfig_destroy()会被调用两次,一次被aws_main_thread_fun(),一次被庆科驱动
+ * linux/rtos平台差异
+ * --vendor_recv_80211_frame()有实现,rtos平台该函数通常为空,通过注册callback方式收包
+ */
+void aws_main_thread_func(void)
+{
+ int interval = 0;
+ aws_start_timestamp = os_get_time_ms();
+
+ /* channel switch init */
+ aws_switch_channel();
+
+rescanning:
+ /* start scaning channel */
+ memset(zc_bssid, 0, ETH_ALEN);
+ while (aws_amend_dst_chan != 0 || aws_state == AWS_SCANNING) {
+ switch (aws_is_chnscan_timeout()) {
+ case CHNSCAN_ONGOING:
+ break;
+ case CHNSCAN_NEXT_CHN:
+ aws_switch_channel();
+ break;
+ case CHNSCAN_TIMEOUT:
+ goto timeout_scanning;
+ default:
+ break;
+ }
+
+ if (aws_stop == AWS_STOPPING) { /* interrupt by user */
+ goto timeout_scanning;
+ }
+
+ if (aws_state != AWS_SCANNING) { /* channel is locked, don't need to tx probe req */
+ break;
+ }
+
+ interval = (HAL_Awss_Get_Channelscan_Interval_Ms() + 2) / 3;
+ if (interval < 1) {
+ interval = 1;
+ }
+
+ /* 80211 frame handled by callback */
+ HAL_SleepMs(interval);
+#ifndef AWSS_DISABLE_ENROLLEE
+ awss_broadcast_enrollee_info();
+#endif
+ HAL_SleepMs(interval);
+#ifdef AWSS_SUPPORT_ADHA
+ aws_send_adha_probe_req();
+#endif
+ HAL_SleepMs(interval);
+#ifdef AWSS_SUPPORT_AHA
+ aws_send_aha_probe_req();
+#endif
+ }
+
+ /* channel lock */
+ awss_debug("[channel scanning] %d ms\r\n",
+ time_elapsed_ms_since(aws_start_timestamp));
+
+ /*
+ * make sure switch to locked channel,
+ * in case of inconsistent with aws_cur_chn
+ */
+#ifdef AWSS_SUPPORT_APLIST
+ aws_try_adjust_chan();
+#endif
+ awss_debug("final channel %d\r\n", aws_locked_chn);
+
+ while (aws_state != AWS_SUCCESS) {
+ /* 80211 frame handled by callback */
+ HAL_SleepMs(300);
+
+ if (aws_stop == AWS_STOPPING) {
+ goto timeout_recving;
+ }
+#ifdef AWSS_SUPPORT_APLIST
+ aws_try_adjust_chan();
+#endif
+ if (aws_is_chnscan_timeout() == CHNSCAN_TIMEOUT) {
+ goto timeout_recving;
+ }
+
+ if (aws_state == AWS_SCANNING) {
+ awss_debug("channel rescanning...\n");
+ goto rescanning;
+ }
+ }
+
+ awss_debug("[channel recving] %d ms\r\n",
+ time_elapsed_ms_since(aws_start_timestamp));
+
+ goto success;
+
+timeout_scanning:
+ awss_debug("aws timeout scanning!\r\n");
+timeout_recving:
+ awss_debug("aws timeout recving!\r\n");
+ do {
+ if (aws_stop == AWS_STOPPING) {
+ break;
+ }
+ if (rescan_timer == NULL) {
+ rescan_timer = HAL_Timer_Create("rescan", (void(*)(void *))rescan_monitor, NULL);
+ }
+ HAL_Timer_Stop(rescan_timer);
+ HAL_Timer_Start(rescan_timer, RESCAN_MONITOR_TIMEOUT_MS);
+ HAL_Awss_Close_Monitor();
+ while (rescan_available == 0) {
+ if (awss_get_config_press() ||
+ aws_stop == AWS_STOPPING) { /* user interrupt sleep */
+ HAL_Timer_Stop(rescan_timer);
+ break;
+ }
+ HAL_SleepMs(200);
+ }
+ rescan_available = 0;
+ } while (0);
+
+ if (aws_stop == AWS_STOPPING) { /* interrupt by user */
+ aws_stop = AWS_STOPPED;
+ goto success;
+ }
+
+ aws_state = AWS_SCANNING;
+#ifdef AWSS_SUPPORT_APLIST
+ if (awss_is_ready_clr_aplist()) {
+ awss_clear_aplist();
+ }
+#endif
+
+ aws_start_timestamp = os_get_time_ms();
+ HAL_Awss_Open_Monitor(aws_80211_frame_handler);
+ goto rescanning;
+
+success:
+ awss_stop_timer(rescan_timer);
+ rescan_timer = NULL;
+ /* don't destroy zconfig_data until monitor_cb is finished. */
+ HAL_MutexLock(zc_mutex);
+ HAL_MutexUnlock(zc_mutex);
+ /*
+ * zconfig_destroy() after os_awss_monitor_close() beacause
+ * zconfig_destroy will release mem/buffer that
+ * zconfig_recv_callback will use
+ *
+ * Note: hiflying will reboot after calling this func, so
+ * aws_get_ssid_passwd() was called in os_awss_monitor_close()
+ */
+ if (aws_stop == AWS_STOPPED) {
+ zconfig_force_destroy();
+ }
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ else if (strcmp((const char *)aws_result_ssid, (const char *)zc_adha_ssid) == 0 ||
+ strcmp((const char *)aws_result_ssid, (const char *)zc_default_ssid) == 0) {
+ zconfig_destroy();
+ }
+#endif
+ else {
+ zconfig_force_destroy();
+ }
+}
+
+static void rescan_monitor(void)
+{
+ rescan_available = 1;
+}
+
+int aws_80211_frame_handler(char *buf, int length, enum AWSS_LINK_TYPE link_type, int with_fcs, signed char rssi)
+{
+ static uint32_t lock_start;
+
+ int ret = zconfig_recv_callback(buf, length, aws_cur_chn, link_type, with_fcs, rssi);
+
+ if (aws_state == AWS_CHN_LOCKED) {
+ switch (ret) {
+ case PKG_START_FRAME:
+ case PKG_DATA_FRAME:
+ case PKG_GROUP_FRAME:
+ lock_start = os_get_time_ms();
+ break;
+ default:
+ /* set to rescanning */
+ if (time_elapsed_ms_since(lock_start) > aws_channel_lock_timeout_ms) {
+ aws_state = AWS_SCANNING;
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void aws_start(char *pk, char *dn, char *ds, char *ps)
+{
+ aws_info = os_zalloc(sizeof(struct aws_info));
+ if (!aws_info) {
+ return;
+ }
+
+ aws_state = AWS_SCANNING;
+
+ /* start from -1 */
+ aws_chn_index = 0xff;
+ memcpy(aws_chn_list, aws_fixed_scanning_channels,
+ sizeof(aws_fixed_scanning_channels));
+
+ memset(aws_result_ssid, 0, sizeof(aws_result_ssid));
+ memset(aws_result_passwd, 0, sizeof(aws_result_passwd));
+ memset(aws_result_bssid, 0, sizeof(aws_result_bssid));
+ aws_result_auth = ZC_AUTH_TYPE_INVALID;
+ aws_result_encry = ZC_ENC_TYPE_INVALID;
+ aws_result_channel = 0;
+
+ zconfig_init();
+#ifdef AWSS_SUPPORT_APLIST
+ awss_open_aplist_monitor();
+#endif
+
+ HAL_Awss_Open_Monitor(aws_80211_frame_handler);
+
+#ifndef AWSS_DISABLE_ENROLLEE
+ awss_init_enrollee_info();
+#endif
+
+ aws_main_thread_func();
+}
+
+static void *aws_mutex = NULL;
+
+void aws_destroy(void)
+{
+ if (aws_mutex == NULL) {
+ aws_mutex = HAL_MutexCreate();
+ }
+ if (aws_mutex) {
+ HAL_MutexLock(aws_mutex);
+ }
+
+ if (aws_info == NULL) {
+ return;
+ }
+
+ if (aws_stop == AWS_STOPPED) {
+ return;
+ }
+
+ aws_stop = AWS_STOPPING;
+
+ HAL_Awss_Close_Monitor();
+
+ while (aws_stop != AWS_STOPPED) {
+ if (aws_state == AWS_SUCCESS) {
+ break;
+ }
+ HAL_MutexUnlock(aws_mutex);
+ HAL_SleepMs(100);
+ HAL_MutexLock(aws_mutex);
+ }
+ if (NULL != aws_info) {
+ HAL_Free(aws_info);
+ }
+ aws_info = NULL;
+
+#ifndef AWSS_DISABLE_ENROLLEE
+ awss_destroy_enrollee_info();
+#endif
+ if (aws_mutex) {
+ HAL_MutexUnlock(aws_mutex);
+ }
+}
+
+void aws_release_mutex()
+{
+ if (aws_mutex) {
+ HAL_MutexDestroy(aws_mutex);
+ aws_mutex = NULL;
+ }
+}
+
+int aws_get_ssid_passwd(char *ssid, char *passwd, uint8_t *bssid,
+ char *auth, char *encry, uint8_t *channel)
+{
+ if (aws_state != AWS_SUCCESS) {
+ return 0;
+ }
+ if (ssid) {
+ strncpy((char *)ssid, (const char *)aws_result_ssid, ZC_MAX_SSID_LEN - 1);
+ }
+ if (passwd) {
+ strncpy((char *)passwd, (const char *)aws_result_passwd, ZC_MAX_PASSWD_LEN - 1);
+ }
+ if (bssid) {
+ memcpy(bssid, aws_result_bssid, ETH_ALEN);
+ }
+ if (auth) {
+ *auth = aws_result_auth;
+ }
+ if (encry) {
+ *encry = aws_result_encry;
+ }
+ if (channel) {
+ *channel = aws_result_channel;
+ }
+ return 1;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/awss_wps.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/awss_wps.c
new file mode 100644
index 00000000..2242160e
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/awss_wps.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+int is_ascii_string(uint8_t *str)
+{
+ int i = 0;
+ while (str[i] != '\0') {
+ if (str[i] < 128) {
+ i ++;
+ } else {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**
+ * extract device name attribute from wps ie struct
+ *
+ * @wps_ie: [IN] wps ie struct
+ * @len: [OUT] len of dev name attr if exist
+ *
+ * Return:
+ * %NULL if dev name attr could not be found, otherwise return a
+ * pointer to dev name attr
+ */
+static uint8_t *get_device_name_attr_from_wps(uint8_t *wps_ie, uint8_t *len)
+{
+ /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
+ uint8_t *attr_ptr = wps_ie + 6; /* goto first attr */
+ uint8_t wps_ielen = wps_ie[1];
+
+#define device_name_id (0x1011)
+ while (attr_ptr - wps_ie < wps_ielen) {
+ /* 4 = 2(Attribute ID) + 2(Length) */
+ uint16_t attr_id = os_get_unaligned_be16(attr_ptr);
+ uint16_t attr_data_len = os_get_unaligned_be16(attr_ptr + 2);
+ uint16_t attr_len = attr_data_len + 4;
+
+ if (attr_id == device_name_id) {
+ *len = attr_len;
+ return attr_ptr;
+ } else {
+ attr_ptr += attr_len; /* goto next */
+ }
+ }
+ return NULL;
+}
+
+/*
+ * passwd_check_utf8()
+ *
+ * @Note: see andriod smartconfig with p2p
+ * if the byte in passwd is zero, jave will change 0x00 with 0xc080
+ * the function will restore 0xc080 to 0x00
+ */
+void passwd_check_utf8(uint8_t *passwd, int *passwd_len)
+{
+ int i, len;
+
+ if (!passwd || !passwd_len) {
+ return;
+ }
+
+ len = *passwd_len;
+ for (i = 0; i < len; i ++) {
+ if (passwd[i] < 0x80) { /* [0x01 ~ 0x7F] */
+ continue;
+ }
+ passwd[i] = 0; /* resetore to 0x00 */
+ if (i + 2 < len) { /* move the rest to overwrite useless content. */
+ memmove(passwd + i + 1, passwd + i + 2, len - i - 2);
+ }
+ len --;
+ }
+ *passwd_len = len;
+}
+
+/*
+ * get_ssid_passwd_from_wps()
+ *
+ * @Note: see andriod zconfig protocol
+ * android sdk limit sizeof(passwd) <= 23
+ *
+ * @Return: _GOT_RESULT_
+ *
+ * use src mac to do ssid completion
+ */
+static int get_ssid_passwd_from_w(uint8_t *in, int total_len, uint8_t *src, uint8_t *bssid)
+{
+ uint8_t tmp_ssid[ZC_MAX_SSID_LEN + 1] = {0}, tmp_passwd[ZC_MAX_PASSWD_LEN + 1] = {0};
+ int ssid_len, passwd_len, ssid_truncated = 0;
+ uint16_t crc, cal_crc;
+ char encrypt = 0;
+ /* used by prepare frame */
+ char *magic_p_w_d = "zl&ws";/* FIXME: Maybe it will be dangerous when opening source. */
+ static uint32_t start_time = 0;
+
+#define W_LEN (32) /* total_len */
+#define EXTRA_LEN (3) /* ssid_len(1B) + checksum(2B) */
+ if (!in || total_len <= 4 + EXTRA_LEN) {
+ return GOT_NOTHING;
+ }
+
+ /* attr_id(2) + attr_len(2) = 4 */
+ in += 4;
+ total_len -= 4;
+
+ if (total_len > W_LEN) {
+ awss_warn("ssid len > 32\r\n");
+ }
+
+ /* total_len: ssid_len(1B), ssid, passwd, crc(2B) */
+ ssid_len = in[0];
+ if (ssid_len & P2P_ENCRYPT_BIT_MASK) {
+ encrypt = (ssid_len & P2P_ENCRYPT_BIT_MASK) >> P2P_ENCODE_TYPE_OFFSET;
+ ssid_len &= P2P_SSID_LEN_MASK;
+ }
+ if (encrypt > P2P_ENCODE_TYPE_ENCRYPT) {
+ return GOT_NOTHING;
+ }
+
+ passwd_len = total_len - ssid_len - EXTRA_LEN; /* ssid_len(1B), crc(2B) */
+ if (ssid_len > W_LEN - EXTRA_LEN || passwd_len < 0) {
+ return GOT_NOTHING;
+ }
+
+ AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_TIME_START);
+ /* ssid_len(1B), ssid, passwd, crc(2B) */
+ crc = os_get_unaligned_be16(in + 1 + ssid_len + passwd_len);
+ /* restore 0xc080 to 0x00 */
+ passwd_check_utf8(in + 1 + ssid_len, &passwd_len);
+ cal_crc = zconfig_checksum_v3(in, 1 + ssid_len + passwd_len);
+ if (crc != cal_crc) {
+ memset(zc_android_src, 0, sizeof(zconfig_data->android_src));
+ memset(zc_pre_ssid, 0, sizeof(zconfig_data->android_pre_ssid));
+ memset(zc_android_ssid, 0, sizeof(zconfig_data->android_ssid));
+ memset(zc_android_bssid, 0, sizeof(zconfig_data->android_bssid));
+ awss_debug("rx illegal p2p (0x%x != 0x%x)\r\n", crc, cal_crc);
+ awss_event_post(IOTX_AWSS_CS_ERR);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_CRC_ERR);
+ /*
+ * use zconfig_checksum_v3() because
+ * java modified UTF-8, U+C080 equal U+00,
+ * ssid len & ssid & crc is not be 0,
+ * the content of passwd encrypted may be 0
+ */
+ return GOT_NOTHING;
+ }
+
+ if (start_time == 0) {
+ start_time = os_get_time_ms();
+ }
+
+#define MAC_LOCAL_ADMINISTERED_BIT (0x02)
+ memcpy(zc_android_src, src, ETH_ALEN);
+ if (zc_android_src[0] & MAC_LOCAL_ADMINISTERED_BIT) {
+ zc_android_src[0] &= ~MAC_LOCAL_ADMINISTERED_BIT;
+ /*awss_debug("android src: %02x%02x%02x\r\n", zc_android_src[0], src[1], src[2]); */
+ } else {
+ awss_warn("local administered bit not set: %02x%02x%02x\r\n",
+ src[0], src[1], src[2]);
+ }
+
+ in += 1;/* eating ssid_len(1B) */
+
+ memset(tmp_ssid, 0, ZC_MAX_SSID_LEN);
+ memset(tmp_passwd, 0, ZC_MAX_PASSWD_LEN);
+
+ memcpy(tmp_ssid, in, ssid_len);
+ in += ssid_len;
+ if (passwd_len) {
+ memcpy(tmp_passwd, in, passwd_len);
+ }
+
+ awss_dict_crypt(SSID_DECODE_TABLE, tmp_ssid, ssid_len);
+
+ switch (encrypt) {
+ case P2P_ENCODE_TYPE_ENCRYPT: {
+ /* decypt passwd using aes128-cfb */
+ uint8_t passwd_cipher_len = 0;
+ uint8_t *passwd_cipher = os_zalloc(128);
+ if (passwd_cipher == NULL) {
+ return GOT_NOTHING;
+ }
+
+ decode_chinese(tmp_passwd, passwd_len, passwd_cipher, &passwd_cipher_len, 7);
+ passwd_len = passwd_cipher_len;
+ memset(tmp_passwd, 0, ZC_MAX_PASSWD_LEN);
+ aes_decrypt_string((char *)passwd_cipher, (char *)tmp_passwd, passwd_len,
+ 1, awss_get_encrypt_type(), 0, NULL);
+ HAL_Free(passwd_cipher);
+ if (is_utf8((const char *)tmp_passwd, passwd_len) == 0) {
+ /* memset(zconfig_data, 0, sizeof(*zconfig_data)); */
+ memset(zc_android_src, 0, sizeof(zconfig_data->android_src));
+ memset(zc_pre_ssid, 0, sizeof(zconfig_data->android_pre_ssid));
+ memset(zc_android_ssid, 0, sizeof(zconfig_data->android_ssid));
+ memset(zc_android_bssid, 0, sizeof(zconfig_data->android_bssid));
+
+ awss_warn("p2p decrypt passwd content err\r\n");
+ awss_event_post(IOTX_AWSS_PASSWD_ERR);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ return GOT_NOTHING;
+ }
+ break;
+ }
+ default:
+ awss_warn("p2p encypt:%d not support\r\n", encrypt);
+ memset(zconfig_data, 0, sizeof(*zconfig_data));
+ return GOT_NOTHING;
+ }
+
+ awss_debug("ssid:%s, tlen:%d\r\n", tmp_ssid, total_len);
+ if (passwd_len && !memcmp(tmp_passwd, magic_p_w_d, passwd_len)) {
+ /* Note: when v2 rollback to v1, zc_preapre_ssid will useless */
+ strncpy((char *)zc_pre_ssid, (char const *)tmp_ssid, ZC_MAX_SSID_LEN - 1);
+ return GOT_CHN_LOCK;
+ }
+ /*
+ // for ascii ssid, max length is 29(32 - 1 - 2).
+ // for utf-8 ssid, max length is 29 - 2 or 29 - 3
+ // gbk ssid also encoded as utf-8
+ // SAMSUNG S4 max name length = 22
+ */
+ if (!is_ascii_string((uint8_t *)tmp_ssid)) { /* chinese ssid */
+ ssid_truncated = 1; /* in case of gbk chinese */
+ } else if (total_len >= W_LEN - EXTRA_LEN) {
+ ssid_truncated = 1;
+ }
+
+ if (ssid_truncated) {
+ uint8_t *best_ssid;
+ int cur_ssid_len = strlen((const char *)tmp_ssid); /* current_ssid */
+ int pre_ssid_len = strlen((const char *)zc_pre_ssid); /* prepare_ssid */
+ if (pre_ssid_len && pre_ssid_len < cur_ssid_len) {
+ /* should not happen */
+ awss_warn("pre:%s < cur:%s\r\n", zc_pre_ssid, tmp_ssid);
+ best_ssid = tmp_ssid; /* current ssid */
+ } else if (pre_ssid_len) {
+ best_ssid = zc_pre_ssid; /* prepare ssid */
+ } else {
+ best_ssid = tmp_ssid; /* default use current ssid */
+ }
+
+ /* awss_debug("ssid truncated, best ssid: %s\r\n", best_ssid); */
+
+ do {
+#ifdef AWSS_SUPPORT_APLIST
+ struct ap_info *ap_info;
+ ap_info = zconfig_get_apinfo_by_ssid_suffix(best_ssid);
+ if (ap_info) {
+ awss_debug("ssid truncated, got ssid from aplist:%s\r\n", best_ssid);
+ strncpy((char *)zc_ssid, (const char *)ap_info->ssid, ZC_MAX_SSID_LEN - 1);
+ memcpy(zc_bssid, ap_info->mac, ETH_ALEN);
+ } else
+#endif
+ {
+ if (memcmp(bssid, zero_mac, ETH_ALEN) && memcmp(bssid, br_mac, ETH_ALEN)) {
+ memcpy(zc_android_bssid, bssid, ETH_ALEN);
+ }
+#ifdef AWSS_SUPPORT_APLIST
+ ap_info = zconfig_get_apinfo(zc_android_bssid);
+ if (ap_info) {
+ if (ap_info->ssid[0] == '\0') { /* hide ssid, MUST not truncate */
+ strncpy((char *)zc_android_ssid, (const char *)best_ssid, ZC_MAX_SSID_LEN - 1);
+ } else { /* not hide ssid, amend ssid according to ap list */
+ strncpy((char *)zc_android_ssid, (const char *)ap_info->ssid, ZC_MAX_SSID_LEN - 1);
+ }
+ } else
+#endif
+ if (time_elapsed_ms_since(start_time) > HAL_Awss_Get_Channelscan_Interval_Ms() * (13 + 3) * 2) {
+ start_time = 0;
+ strncpy((char *)zc_android_ssid, (const char *)best_ssid, ZC_MAX_SSID_LEN - 1);
+ }
+
+ if (zc_android_ssid[0] == '\0') {
+ return GOT_NOTHING;
+ }
+ strncpy((char *)zc_ssid, (const char *)zc_android_ssid, ZC_MAX_SSID_LEN - 1);
+ memcpy(zc_bssid, zc_android_bssid, ETH_ALEN);
+ }
+ } while (0);
+ } else {
+ strncpy((char *)zc_ssid, (char const *)tmp_ssid, ZC_MAX_SSID_LEN - 1);
+ if (memcmp(bssid, zero_mac, ETH_ALEN) && memcmp(bssid, br_mac, ETH_ALEN)) {
+ memcpy(zc_bssid, bssid, ETH_ALEN);
+ }
+ }
+
+ strncpy((char *)zc_passwd, (char const *)tmp_passwd, ZC_MAX_PASSWD_LEN - 1);
+ start_time = 0;
+
+ return GOT_SSID_PASSWD;
+}
+
+
+int awss_recv_callback_wps(struct parser_res *res)
+{
+ uint8_t *data = res->u.wps.data;
+ uint16_t len = res->u.wps.data_len;
+
+ uint8_t tods = res->tods;
+ uint8_t channel = res->channel;
+
+ int ret = get_ssid_passwd_from_w(data, len, res->src, res->bssid);
+ if (ret == GOT_CHN_LOCK) {
+ awss_debug("callback for v2:%02x%02x%02x\r\n",
+ res->src[0], res->src[1], res->src[2]);
+ goto chn_locked;
+ } else if (ret == GOT_SSID_PASSWD) {
+ goto rcv_done;
+ } else if (ret == GOT_NOTHING) {
+ return PKG_INVALID;
+ } else {
+ return PKG_INVALID;
+ }
+
+chn_locked:
+ zconfig_set_state(STATE_CHN_LOCKED_BY_P2P, tods, channel);
+ return PKG_START_FRAME;
+rcv_done:
+ AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ zconfig_set_state(STATE_RCV_DONE, tods, channel);
+ return PKG_END;
+}
+
+int awss_ieee80211_wps_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
+{
+ const uint8_t *wps_ie = NULL;
+ struct ieee80211_hdr *hdr;
+ uint8_t attr_len = 0;
+ uint16_t ieoffset;
+ int fc;
+
+ /*
+ * when device try to connect current router (include adha and aha)
+ * skip the wps packet.
+ */
+ if (mgmt_header == NULL || zconfig_finished) {
+ return ALINK_INVALID;
+ }
+
+ /*
+ * we don't process wps until user press configure button
+ */
+ if (awss_get_config_press() == 0) {
+ return ALINK_INVALID;
+ }
+
+ hdr = (struct ieee80211_hdr *)mgmt_header;
+ fc = hdr->frame_control;
+
+ if (!ieee80211_is_probe_req(fc)) {
+ return ALINK_INVALID;
+ }
+
+ ieoffset = offsetof(struct ieee80211_mgmt, u.probe_req.variable);
+ if (ieoffset > len) {
+ return ALINK_INVALID;
+ }
+ /* get wps ie */
+ wps_ie = (const uint8_t *)cfg80211_find_vendor_ie(WLAN_OUI_WPS, WLAN_OUI_TYPE_WPS,
+ mgmt_header + ieoffset, len - ieoffset);
+ if (wps_ie == NULL) {
+ return ALINK_INVALID;
+ }
+ /* get wps name in wps ie */
+ wps_ie = (const uint8_t *)get_device_name_attr_from_wps((uint8_t *)wps_ie, &attr_len);
+ if (wps_ie == NULL) {
+ return ALINK_INVALID;
+ }
+ res->u.wps.data_len = attr_len;
+ res->u.wps.data = (uint8_t *)wps_ie;
+ return ALINK_WPS;
+}
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/awss_wps.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/awss_wps.h
new file mode 100644
index 00000000..0cb7feec
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/awss_wps.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_WPS_H__
+#define __AWSS_WPS_H__
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+
+#include
+#include "os.h"
+#include "zconfig_ieee80211.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#define WLAN_OUI_MICROSOFT (0x0050F2)
+#define WLAN_OUI_WPS (0x0050F2)
+#define WLAN_OUI_TYPE_MICROSOFT_WPA (1)
+#define WLAN_OUI_TYPE_WPS (4)
+
+int awss_recv_callback_wps(struct parser_res *res);
+int awss_ieee80211_wps_process(uint8_t *mgmt_header, int len, int link_type,
+ struct parser_res *res, signed char rssi);
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif /* end AWSS_SUPPORT_SMARTCONFIG_WPS */
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/p2p_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/p2p_wrapper.h
new file mode 100644
index 00000000..8c994140
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/p2p/p2p_wrapper.h
@@ -0,0 +1,57 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+/*************************************** common hals ***************************************/
+int HAL_Timer_Stop(void *timer);
+int HAL_Timer_Delete(void *timer);
+void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
+int HAL_Timer_Start(void *timer, int ms);
+void HAL_SleepMs(uint32_t ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+uint64_t HAL_UptimeMs(void);
+void HAL_Free(void *ptr);
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+
+/*************************************** wifi provision frameworks hals ***************************************/
+/* frameworks/awss.c*/
+int HAL_Awss_Get_Timeout_Interval_Ms(void);
+int HAL_Sys_Net_Is_Ready();
+int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
+/* awss_crypt.c */
+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]);
+/* zconfig_vendor_common.c */
+void HAL_Awss_Close_Monitor(void);
+void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
+void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
+int HAL_Awss_Get_Channelscan_Interval_Ms(void);
+DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init(
+ _IN_ const uint8_t *key,
+ _IN_ const uint8_t *iv,
+ _IN_ AES_DIR_t dir);
+DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
+DLL_HAL_API int HAL_Aes128_Cbc_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t blockNum,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cfb_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t length,
+ _OU_ void *dst);
+char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
+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);
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/aha_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/aha_wrapper.h
new file mode 100644
index 00000000..ab430a58
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/aha_wrapper.h
@@ -0,0 +1,62 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+
+/*************************************** common hals ***************************************/
+int HAL_Timer_Stop(void *timer);
+int HAL_Timer_Delete(void *timer);
+void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
+int HAL_Timer_Start(void *timer, int ms);
+void HAL_SleepMs(uint32_t ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+uint64_t HAL_UptimeMs(void);
+void HAL_Free(void *ptr);
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+
+/*************************************** wifi provision frameworks hals ***************************************/
+/* frameworks/awss.c*/
+int HAL_Awss_Get_Timeout_Interval_Ms(void);
+int HAL_Sys_Net_Is_Ready();
+int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
+/* awss_crypt.c */
+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_Awss_Close_Monitor(void);
+void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
+void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
+int HAL_Awss_Get_Channelscan_Interval_Ms(void);
+/* zconfig_vendor_common.c */
+DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init(
+ _IN_ const uint8_t *key,
+ _IN_ const uint8_t *iv,
+ _IN_ AES_DIR_t dir);
+DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
+DLL_HAL_API int HAL_Aes128_Cbc_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t blockNum,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cfb_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t length,
+ _OU_ void *dst);
+char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
+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);
+
+/*************************************** phone ap specially required hals ***************************************/
+int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
+ _IN_ uint8_t *buffer, _IN_ int len);
+DLL_HAL_API int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb);
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_aha.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_aha.c
new file mode 100644
index 00000000..44bacaf9
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_aha.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#ifdef AWSS_SUPPORT_AHA
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#define AHA_SA_OFFSET (10)
+#define AHA_PROBE_PKT_LEN (49)
+#define AHA_MONITOR_TIMEOUT_MS (1 * 60 * 1000)
+
+const char *zc_default_ssid = "aha";
+const char *zc_default_passwd = "12345678";
+
+static const uint8_t aha_probe_req_frame[AHA_PROBE_PKT_LEN] = {
+ 0x40, 0x00, /* mgnt type, frame control */
+ 0x00, 0x00, /* duration */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
+ 0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
+ 0xC0, 0x79, /* seq */
+ 0x00, 0x03, 0x61, 0x68, 0x61, /* ssid, aha */
+ 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x8C, 0x92, 0x98, 0xA4, /* supported rates */
+ 0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
+ 0x3F, 0x84, 0x10, 0x9E /* FCS */
+};
+
+static void *aha_timer = NULL;
+static volatile char aha_timeout = 0;
+
+static void aha_monitor(void);
+
+static void aha_monitor(void)
+{
+ aha_timeout = 1;
+}
+
+int awss_aha_monitor_is_timeout(void)
+{
+ return aha_timeout > 0;
+}
+
+int awss_open_aha_monitor(void)
+{
+ aha_timeout = 0;
+ if (aha_timer == NULL)
+ aha_timer = (void *)HAL_Timer_Create("aha", (void (*)(void *))aha_monitor, NULL);
+ if (aha_timer == NULL)
+ return -1;
+
+ HAL_Timer_Stop(aha_timer);
+ HAL_Timer_Start(aha_timer, AHA_MONITOR_TIMEOUT_MS);
+ return 0;
+}
+
+int awss_close_aha_monitor(void)
+{
+ awss_stop_timer(aha_timer);
+ aha_timer = NULL;
+ aha_timeout = 0;
+ return 0;
+}
+
+int awss_recv_callback_aha_ssid(struct parser_res *res)
+{
+ uint8_t tods = res->tods;
+ uint8_t channel = res->channel;
+
+ awss_debug("found default ssid: %s\r\n", zc_default_ssid);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_TIME_START);
+
+ strncpy((char *)zc_ssid, zc_default_ssid, ZC_MAX_SSID_LEN - 1);
+ strncpy((char *)zc_passwd, zc_default_passwd, ZC_MAX_PASSWD_LEN - 1);
+
+ zconfig_set_state(STATE_RCV_DONE, tods, channel);
+ return PKG_END;
+}
+
+int aws_send_aha_probe_req(void)
+{
+ uint8_t probe[AHA_PROBE_PKT_LEN];
+ memcpy(probe, aha_probe_req_frame, sizeof(probe));
+ os_wifi_get_mac(&probe[AHA_SA_OFFSET]);
+ HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, probe, sizeof(probe));
+ return 0;
+}
+
+int awss_ieee80211_aha_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
+{
+ uint8_t ssid[ZC_MAX_SSID_LEN] = {0}, bssid[ETH_ALEN] = {0};
+ uint8_t auth, pairwise_cipher, group_cipher;
+ struct ieee80211_hdr *hdr;
+ int fc, ret, channel;
+
+ /*
+ * when device try to connect current router (include adha and aha)
+ * skip the new aha and process the new aha in the next scope.
+ */
+ if (mgmt_header == NULL || zconfig_finished)
+ return ALINK_INVALID;
+
+ /*
+ * we don't process aha until user press configure button
+ */
+ if (awss_get_config_press() == 0)
+ return ALINK_INVALID;
+
+ hdr = (struct ieee80211_hdr *)mgmt_header;
+ fc = hdr->frame_control;
+
+ if (!ieee80211_is_beacon(fc) && !ieee80211_is_probe_resp(fc))
+ return ALINK_INVALID;
+ ret = ieee80211_get_bssid(mgmt_header, bssid);
+ if (ret < 0)
+ return ALINK_INVALID;
+
+ ret = ieee80211_get_ssid(mgmt_header, len, ssid);
+ if (ret < 0)
+ return ALINK_INVALID;
+
+ /*
+ * skip ap which is not aha
+ */
+ if (strcmp((const char *)ssid, zc_default_ssid))
+ return ALINK_INVALID;
+
+ channel = cfg80211_get_bss_channel(mgmt_header, len);
+ rssi = rssi > 0 ? rssi - 256 : rssi;
+
+ cfg80211_get_cipher_info(mgmt_header, len, &auth,
+ &pairwise_cipher, &group_cipher);
+ awss_save_apinfo(ssid, bssid, channel, auth,
+ pairwise_cipher, group_cipher, rssi);
+ /*
+ * If user press the configure button,
+ * device just process aha, and skip all the adha.
+ */
+ if (adha_aplist->cnt > adha_aplist->try_idx) {
+ uint8_t ap_idx = adha_aplist->aplist[adha_aplist->try_idx ++];
+#ifdef AWSS_SUPPORT_APLIST
+ memcpy(zc_bssid, zconfig_aplist[ap_idx].mac, ETH_ALEN);
+#endif
+ awss_set_config_press(0);
+ return ALINK_DEFAULT_SSID;
+ }
+ return ALINK_INVALID;
+}
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_aha.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_aha.h
new file mode 100644
index 00000000..3d92cf70
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_aha.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_AHA_H__
+#define __AWSS_AHA_H__
+
+#include
+#include "os.h"
+#include "zconfig_ieee80211.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+int awss_open_aha_monitor(void);
+int awss_close_aha_monitor(void);
+int awss_aha_monitor_is_timeout(void);
+int aws_send_aha_probe_req(void);
+int awss_recv_callback_aha_ssid(struct parser_res *res);
+int awss_ieee80211_aha_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi);
+
+extern const char *zc_default_ssid;
+extern const char *zc_default_passwd;
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_wifimgr.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_wifimgr.c
new file mode 100644
index 00000000..b241f321
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_wifimgr.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+#define WIFI_APINFO_LIST_LEN (512)
+#define DEV_SIMPLE_ACK_LEN (64)
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+static char g_req_msg_id[MSG_REQ_ID_LEN];
+static platform_netaddr_t g_wifimgr_req_sa;
+
+static void *scan_req_timer = NULL;
+static void *scan_tx_wifilist_timer = NULL;
+static void wifimgr_scan_request();
+static void wifimgr_scan_tx_wifilist();
+
+static char wifi_scan_runninng = 0;
+static void *g_scan_mutex;
+
+typedef struct scan_list {
+ list_head_t entry;
+ void *data;
+} scan_list_t;
+
+static ALIYUN_LIST_HEAD(g_scan_list);
+
+int wifimgr_scan_init(void)
+{
+ if (wifi_scan_runninng)
+ return 0;
+
+ g_scan_mutex = HAL_MutexCreate();
+ INIT_LIST_HEAD(&g_scan_list);
+ wifi_scan_runninng = 1;
+ return 0;
+}
+
+static void wifimgr_scan_tx_wifilist()
+{
+ scan_list_t *item = NULL, *next = NULL;
+
+ char topic[TOPIC_LEN_MAX] = {0};
+ awss_build_topic((const char *)TOPIC_AWSS_WIFILIST, topic, TOPIC_LEN_MAX);
+
+ HAL_MutexLock(g_scan_mutex);
+ list_for_each_entry_safe(item, next, &g_scan_list, entry, scan_list_t) {
+ if (item && item->data) {
+ if (0 != awss_cmp_coap_ob_send(item->data, strlen((char *)item->data),
+ &g_wifimgr_req_sa, topic, NULL)) {
+ awss_debug("sending failed.");
+ }
+ HAL_Free(item->data);
+ }
+ list_del(&item->entry);
+ HAL_Free(item);
+ item= NULL;
+ }
+ HAL_MutexUnlock(g_scan_mutex);
+}
+
+static int awss_scan_cb(const char ssid[PLATFORM_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 last_ap)
+{
+#define ONE_AP_INFO_LEN_MAX (141)
+ static char *aplist = NULL;
+ static int msg_len = 0;
+
+ if (aplist == NULL) {
+ aplist = os_zalloc(WIFI_APINFO_LIST_LEN);
+ if (aplist == NULL)
+ return SHUB_ERR;
+
+ msg_len = 0;
+ msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1, "{\"awssVer\":%s, \"wifiList\":[", AWSS_VER);
+ }
+ if ((ssid != NULL) && (ssid[0] != '\0')) {
+ uint8_t bssid_connected[ETH_ALEN] = {0};
+ char *other_apinfo = os_zalloc(64);
+ char *encode_ssid = os_zalloc(OS_MAX_SSID_LEN * 2 + 1);
+ int ssid_len = strlen(ssid);
+ ssid_len = ssid_len > OS_MAX_SSID_LEN - 1 ? OS_MAX_SSID_LEN - 1 : ssid_len;
+
+ HAL_Wifi_Get_Ap_Info(NULL, NULL, bssid_connected);
+
+ if (other_apinfo && encode_ssid) {
+ if (memcmp(bssid_connected, bssid, ETH_ALEN) == 0) {
+ HAL_Snprintf(other_apinfo, 64 - 1, "\"auth\":\"%d\",\"connected\":\"1\"", auth);
+ } else {
+ HAL_Snprintf(other_apinfo, 64 - 1, "\"auth\":\"%d\"", auth);
+ }
+ if (is_utf8(ssid, ssid_len)) {
+ strncpy(encode_ssid, (const char *)ssid, ssid_len);
+ msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1,
+ "{\"ssid\":\"%s\",\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\"rssi\":\"%d\",%s},",
+ encode_ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
+ rssi > 0 ? rssi - 256 : rssi, other_apinfo);
+ } else {
+ utils_hex_to_str((uint8_t *)ssid, ssid_len, encode_ssid, OS_MAX_SSID_LEN * 2);
+ msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1,
+ "{\"xssid\":\"%s\",\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\"rssi\":\"%d\",%s},",
+ encode_ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
+ rssi > 0 ? rssi - 256 : rssi, other_apinfo);
+ }
+ }
+
+ if (other_apinfo) HAL_Free(other_apinfo);
+ if (encode_ssid) HAL_Free(encode_ssid);
+ }
+ awss_debug("last_ap:%u\r\n", last_ap);
+
+ if (last_ap || WIFI_APINFO_LIST_LEN < msg_len + ONE_AP_INFO_LEN_MAX + strlen(AWSS_ACK_FMT)) {
+ uint32_t tlen;
+ char *msg_aplist = NULL;
+ scan_list_t *list = NULL;
+ if (last_ap)
+ AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_SCAN_STOP);
+ if (aplist[msg_len - 1] == ',')
+ msg_len--; /* eating the last ',' */
+ msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1, "]}");
+
+ tlen = DEV_SIMPLE_ACK_LEN + msg_len;
+ msg_len = 0;
+ msg_aplist = os_zalloc(tlen + 1);
+ if (!msg_aplist) {
+ HAL_Free(aplist);
+ aplist = NULL;
+ return SHUB_ERR;
+ }
+
+ HAL_Snprintf(msg_aplist, tlen, AWSS_ACK_FMT, g_req_msg_id, 200, aplist);
+ HAL_Free(aplist);
+ aplist = NULL;
+
+ list = (scan_list_t *)os_zalloc(sizeof(scan_list_t));
+ if (!list) {
+ awss_debug("scan list fail\n");
+ HAL_Free(msg_aplist);
+ return SHUB_ERR;
+ }
+ list->data = msg_aplist;
+ HAL_MutexLock(g_scan_mutex);
+ list_add(&list->entry, &g_scan_list);
+ HAL_MutexUnlock(g_scan_mutex);
+
+ if (last_ap) {
+ if (scan_tx_wifilist_timer == NULL)
+ scan_tx_wifilist_timer = HAL_Timer_Create("wifilist", (void (*)(void *))wifimgr_scan_tx_wifilist, NULL);
+ HAL_Timer_Stop(scan_tx_wifilist_timer);
+ HAL_Timer_Start(scan_tx_wifilist_timer, 1);
+ }
+ awss_debug("sending message to app: %s\n", msg_aplist);
+ }
+
+ return 0;
+}
+
+static void wifimgr_scan_request()
+{
+ wifimgr_scan_init();
+
+ AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_SCAN_START);
+ HAL_Wifi_Scan(&awss_scan_cb);
+}
+
+/*
+ * @desc: ????getWifiList??Ϣ
+ *
+ */
+int wifimgr_process_get_wifilist_request(void *ctx, void *resource, void *remote, void *request)
+{
+ char buf[DEV_SIMPLE_ACK_LEN] = {0};
+ char *msg = NULL, *id = NULL;
+ int len = 0, id_len = 0;
+ char topic[TOPIC_LEN_MAX] = {0};
+
+ msg = awss_cmp_get_coap_payload(request, &len);
+ if (msg == NULL || len == 0)
+ return -1;
+
+ if (scan_req_timer == NULL)
+ scan_req_timer = HAL_Timer_Create("scan_req", (void (*)(void *))wifimgr_scan_request, NULL);
+ HAL_Timer_Stop(scan_req_timer);
+
+ id = json_get_value_by_name(msg, len, "id", &id_len, 0);
+ memset(g_req_msg_id, 0, sizeof(g_req_msg_id));
+ if (id && id_len < sizeof(g_req_msg_id) - 1)
+ memcpy(g_req_msg_id, id, id_len);
+
+ HAL_Snprintf(buf, DEV_SIMPLE_ACK_LEN - 1, AWSS_ACK_FMT, g_req_msg_id, 200, "\"success\"");
+
+ awss_debug("sending message to app: %s\n", buf);
+ awss_build_topic((const char *)TOPIC_AWSS_WIFILIST, topic, TOPIC_LEN_MAX);
+ memcpy(&g_wifimgr_req_sa, remote, sizeof(g_wifimgr_req_sa));
+ if (0 != awss_cmp_coap_send_resp(buf, strlen(buf), &g_wifimgr_req_sa, topic, request, NULL, NULL, 0))
+ awss_debug("sending failed.");
+
+ HAL_Timer_Start(scan_req_timer, 1);
+
+ return SHUB_OK;
+}
+
+int wifimgr_process_mcast_get_device_info(void *ctx, void *resource, void *remote, void *request)
+{
+ return process_get_device_info(ctx, resource, remote, request, 1, AWSS_NOTIFY_DEV_RAND_SIGN);
+}
+
+int wifimgr_process_ucast_get_device_info(void *ctx, void *resource, void *remote, void *request)
+{
+ return process_get_device_info(ctx, resource, remote, request, 0, AWSS_NOTIFY_DEV_RAND_SIGN);
+}
+#define WLAN_CONNECTION_TIMEOUT (30 * 1000) /* 30 seconds */
+int switch_ap_done = 0;
+
+void zconfig_force_destroy(void);
+int wifimgr_process_switch_ap_request(void *ctx, void *resource, void *remote, void *request)
+{
+ char ssid[PLATFORM_MAX_SSID_LEN * 2 + 1] = {0}, passwd[PLATFORM_MAX_PASSWD_LEN + 1] = {0};
+ int str_len = 0, success = 1, i = 0, len = 0, enc_lvl = SEC_LVL_OPEN;
+ char req_msg_id[MSG_REQ_ID_LEN] = {0};
+ char *str = NULL, *buf = NULL;
+ char bssid[ETH_ALEN] = {0};
+ char msg[128] = {0};
+ char ssid_found = 0;
+ char topic[TOPIC_LEN_MAX] = {0};
+
+ static char switch_ap_parsed = 0;
+ if (switch_ap_parsed != 0)
+ return SHUB_ERR;
+
+ switch_ap_parsed = 1;
+
+ buf = awss_cmp_get_coap_payload(request, &len);
+ str = json_get_value_by_name(buf, len, "id", &str_len, 0);
+ memcpy(req_msg_id, str, str_len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : str_len);
+ awss_debug("switch ap, len:%u, %s\r\n", len, buf);
+ buf = json_get_value_by_name(buf, len, "params", &len, 0);
+
+ do {
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, 200, "\"success\"");
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "ssid", &str_len, 0);
+ awss_debug("ssid, len:%u, %s\r\n", str_len, str != NULL ? str : "NULL");
+ if (str && (str_len < PLATFORM_MAX_SSID_LEN)) {
+ memcpy(ssid, str, str_len);
+ ssid_found = 1;
+ }
+
+ if (!ssid_found) {
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "xssid", &str_len, 0);
+ if (str && (str_len < PLATFORM_MAX_SSID_LEN * 2 - 1)) {
+ uint8_t decoded[OS_MAX_SSID_LEN] = {0};
+ int len = str_len / 2;
+ memcpy(ssid, str, str_len);
+ utils_str_to_hex(ssid, str_len, decoded, OS_MAX_SSID_LEN);
+ memcpy(ssid, (const char *)decoded, len);
+ ssid[len] = '\0';
+ } else {
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -1, "\"ssid error\"");
+ success = 0;
+ break;
+ }
+ }
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "bssid", &str_len, 0);
+ if (str) os_wifi_str2mac(str, bssid);
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "cipherType", &str_len, 0);
+ if (!str) {
+ success = 0;
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4, "\"no security level error\"");
+ break;
+ }
+
+ enc_lvl = atoi(str);
+ if (enc_lvl != awss_get_encrypt_type()) {
+ success = 0;
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4, "\"security level error\"");
+ break;
+ }
+
+ str_len = 0;
+ str = json_get_value_by_name(buf, len, "passwd", &str_len, 0);
+ /* TODO: empty passwd is allow? json parse "passwd":"" result is NULL? */
+ switch (enc_lvl) {
+ case SEC_LVL_AES256:
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4, "\"aes256 not support\"");
+ success = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (success == 0)
+ break;
+
+ if (0 == enc_lvl) {
+ if (str_len < PLATFORM_MAX_PASSWD_LEN) {
+ memcpy(passwd, str, str_len);
+ } else {
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -2, "\"passwd len error\"");
+ success = 0;
+ }
+ } else {
+ if (str_len < (PLATFORM_MAX_PASSWD_LEN * 2) - 1) {
+ char encoded[PLATFORM_MAX_PASSWD_LEN * 2 + 1] = {0};
+ memcpy(encoded, str, str_len);
+ aes_decrypt_string(encoded, passwd, str_len,
+ 0, awss_get_encrypt_type(), 1, (const char *)aes_random);
+ } else {
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -3, "\"passwd len error\"");
+ AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ success = 0;
+ }
+ }
+
+ if (success && is_utf8(passwd, strlen(passwd)) == 0) {
+ HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id,
+ enc_lvl == SEC_LVL_OPEN ? -2 : -3 , "\"passwd content error\"");
+ AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ success = 0;
+ }
+ } while (0);
+
+ awss_devinfo_notify_stop();
+ awss_dev_bind_notify_stop();
+
+ awss_debug("Sending message to app: %s", msg);
+ awss_debug("switch to ap: '%s'", ssid);
+ awss_build_topic((const char *)TOPIC_AWSS_SWITCHAP, topic, TOPIC_LEN_MAX);
+ for (i = 0; i < 5; i ++) {
+ if (0 != awss_cmp_coap_send_resp(msg, strlen(msg), remote, topic, request, NULL, NULL, 0)) {
+ awss_debug("sending failed.");
+ } else {
+ awss_debug("sending succeeded.");
+ }
+ }
+
+ HAL_SleepMs(1000);
+
+ if (!success)
+ goto SWITCH_AP_END;
+#ifdef AWSS_SUPPORT_APLIST
+ do {
+ struct ap_info * aplist = NULL;
+ aplist = zconfig_get_apinfo_by_ssid((uint8_t *)ssid);
+ awss_debug("connect '%s'", ssid);
+ if (aplist) {
+ memcpy(bssid, aplist->mac, ETH_ALEN);
+ awss_debug("bssid: %02x:%02x:%02x:%02x:%02x:%02x", \
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+ }
+ } while (0);
+#endif
+ AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_START);
+ if (0 != HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT,
+ ssid, passwd,
+ AWSS_AUTH_TYPE_INVALID,
+ AWSS_ENC_TYPE_INVALID,
+ (uint8_t *)bssid, 0)) {
+ } else {
+ AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ switch_ap_done = 1;
+ awss_close_aha_monitor();
+ HAL_MutexDestroy(g_scan_mutex);
+ g_scan_mutex = NULL;
+ wifi_scan_runninng = 0;
+ awss_stop_timer(scan_req_timer);
+ scan_req_timer = NULL;
+ awss_stop_timer(scan_tx_wifilist_timer);
+ scan_tx_wifilist_timer = NULL;
+
+ zconfig_force_destroy();
+
+ produce_random(aes_random, sizeof(aes_random));
+ }
+ awss_debug("connect '%s' %s\r\n", ssid, switch_ap_done == 1 ? "success" : "fail");
+
+SWITCH_AP_END:
+ switch_ap_parsed = 0;
+ return SHUB_OK;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_wifimgr.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_wifimgr.h
new file mode 100644
index 00000000..19d41967
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/phone_ap/awss_wifimgr.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_WIFIMGR_H__
+#define __AWSS_WIFIMGR_H__
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+
+enum {
+ SHUB_ERR,
+ SHUB_OK
+};
+
+int wifimgr_process_get_wifilist_request(void *ctx, void *resource, void *remote, void *request);
+int wifimgr_process_mcast_get_device_info(void *ctx, void *resource, void *remote, void *request);
+int wifimgr_process_ucast_get_device_info(void *ctx, void *resource, void *remote, void *request);
+int wifimgr_process_switch_ap_request(void *ctx, void *resource, void *remote, void *request);
+
+#endif
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/router_ap/awss_adha.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/router_ap/awss_adha.c
new file mode 100644
index 00000000..ae637f46
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/router_ap/awss_adha.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+struct adha_info *adha_aplist = NULL;
+
+const char *zc_adha_ssid = "adha";
+const char *zc_adha_passwd = "08d9f22c60157fd01f57645d791a0b610fe0a558c104d6a1f9d9c0a9913c";
+
+#ifdef AWSS_SUPPORT_ADHA
+
+#define ADHA_WORK_CYCLE (5 * 1000)
+#define ADHA_PROBE_PKT_LEN (50)
+#define ADHA_SA_OFFSET (10)
+
+static const uint8_t adha_probe_req_frame[ADHA_PROBE_PKT_LEN] = {
+ 0x40, 0x00, /* mgnt type, frame control */
+ 0x00, 0x00, /* duration */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
+ 0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
+ 0xC0, 0x79, /* seq */
+ 0x00, 0x04, 0x61, 0x64, 0x68, 0x61, /* ssid, adha */
+ 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x8C, 0x92, 0x98, 0xA4, /*supported rates */
+ 0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
+ 0x3F, 0x84, 0x10, 0x9E /* FCS */
+};
+
+static void *adha_timer = NULL;
+static volatile char adha_switch = 0;
+
+static void adha_monitor(void);
+
+static void adha_monitor(void)
+{
+ adha_switch = 1;
+}
+
+int awss_is_ready_switch_next_adha(void)
+{
+ return adha_switch > 0;
+}
+
+int awss_open_adha_monitor(void)
+{
+ adha_switch = 0;
+ if (adha_timer == NULL)
+ adha_timer = (void *)HAL_Timer_Create("adha", (void (*)(void *))adha_monitor, NULL);
+ if (adha_timer == NULL)
+ return -1;
+
+ HAL_Timer_Stop(adha_timer);
+ HAL_Timer_Start(adha_timer, ADHA_WORK_CYCLE);
+ return 0;
+}
+
+int awss_close_adha_monitor(void)
+{
+ awss_stop_timer(adha_timer);
+ adha_timer = NULL;
+ adha_switch = 0;
+ return 0;
+}
+
+int awss_recv_callback_adha_ssid(struct parser_res *res)
+{
+ uint8_t tods = res->tods;
+ uint8_t channel = res->channel;
+
+ AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_START);
+ awss_debug("found adha ssid: %s\r\n", zc_adha_ssid);
+
+ strncpy((char *)zc_ssid, zc_adha_ssid, ZC_MAX_SSID_LEN - 1);
+ strncpy((char *)zc_passwd, zc_adha_passwd, ZC_MAX_PASSWD_LEN - 1);
+
+ zconfig_set_state(STATE_RCV_DONE, tods, channel);
+ return PKG_END;
+}
+
+int aws_send_adha_probe_req(void)
+{
+ uint8_t probe[ADHA_PROBE_PKT_LEN];
+ memcpy(probe, adha_probe_req_frame, sizeof(probe));
+ os_wifi_get_mac(&probe[ADHA_SA_OFFSET]);
+ HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, probe, sizeof(probe));
+ return 0;
+}
+
+int awss_ieee80211_adha_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
+{
+ uint8_t ssid[ZC_MAX_SSID_LEN] = {0}, bssid[ETH_ALEN] = {0};
+ uint8_t auth, pairwise_cipher, group_cipher;
+ struct ieee80211_hdr *hdr;
+ int fc, ret, channel;
+
+ /*
+ * when device try to connect current router (include adha and aha)
+ * skip the new aha and process the new aha in the next scope.
+ */
+ if (mgmt_header == NULL || zconfig_finished)
+ return ALINK_INVALID;
+
+ /*
+ * if user press configure button, drop all adha
+ */
+ if (awss_get_config_press())
+ return ALINK_INVALID;
+
+ hdr = (struct ieee80211_hdr *)mgmt_header;
+ fc = hdr->frame_control;
+
+ if (!ieee80211_is_beacon(fc) && !ieee80211_is_probe_resp(fc))
+ return ALINK_INVALID;
+ ret = ieee80211_get_bssid(mgmt_header, bssid);
+ if (ret < 0)
+ return ALINK_INVALID;
+
+ ret = ieee80211_get_ssid(mgmt_header, len, ssid);
+ if (ret < 0)
+ return ALINK_INVALID;
+ /*
+ * skip ap which is not adha
+ */
+ if (strcmp((const char *)ssid, zc_adha_ssid))
+ return ALINK_INVALID;
+
+ channel = cfg80211_get_bss_channel(mgmt_header, len);
+ rssi = rssi > 0 ? rssi - 256 : rssi;
+
+ cfg80211_get_cipher_info(mgmt_header, len, &auth,
+ &pairwise_cipher, &group_cipher);
+#ifdef AWSS_SUPPORT_APLIST
+ awss_save_apinfo(ssid, bssid, channel, auth,
+ pairwise_cipher, group_cipher, rssi);
+#endif
+ /*
+ * If user press the configure button,
+ * skip all the adha.
+ */
+ if (adha_aplist->cnt > adha_aplist->try_idx) {
+ uint8_t ap_idx = adha_aplist->aplist[adha_aplist->try_idx ++];
+#ifdef AWSS_SUPPORT_APLIST
+ memcpy(zc_bssid, zconfig_aplist[ap_idx].mac, ETH_ALEN);
+#endif
+ return ALINK_ADHA_SSID;
+ }
+ return ALINK_INVALID;
+}
+
+#endif
+
+int awss_init_adha_aplist(void)
+{
+ if (adha_aplist)
+ return 0;
+ adha_aplist = (struct adha_info *)os_zalloc(sizeof(struct adha_info));
+ if (adha_aplist == NULL)
+ return -1;
+ return 0;
+}
+
+int awss_deinit_adha_aplist(void)
+{
+ if (adha_aplist == NULL)
+ return 0;
+
+ HAL_Free(adha_aplist);
+ adha_aplist = NULL;
+ return 0;
+}
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/router_ap/awss_adha.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/router_ap/awss_adha.h
new file mode 100644
index 00000000..68730518
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/router_ap/awss_adha.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_ADHA_H__
+#define __AWSS_ADHA_H__
+
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+
+#include "zconfig_lib.h"
+#include "zconfig_protocol.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+struct adha_info {
+ uint8_t try_idx;
+ uint8_t cnt;
+ uint8_t aplist[MAX_APLIST_NUM];
+};
+
+int awss_init_adha_aplist(void);
+int awss_deinit_adha_aplist(void);
+extern struct adha_info *adha_aplist;
+extern const char *zc_adha_passwd;
+extern const char *zc_adha_ssid;
+
+#ifdef AWSS_SUPPORT_ADHA
+int awss_open_adha_monitor(void);
+int awss_close_adha_monitor(void);
+int aws_send_adha_probe_req(void);
+
+int awss_is_ready_switch_next_adha(void);
+int awss_recv_callback_adha_ssid(struct parser_res *res);
+int awss_ieee80211_adha_process(uint8_t *mgmt_header, int len, int link_type,
+ struct parser_res *res, signed char rssi);
+#endif
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+#endif /* end AWSS_SUPPORT_ADHA || AWSS_SUPPORT_AHA */
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/smartconfig/awss_smartconfig.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/smartconfig/awss_smartconfig.c
new file mode 100644
index 00000000..90f3b87d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/smartconfig/awss_smartconfig.c
@@ -0,0 +1,1206 @@
+#include "wifi_provision_internal.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+/* following is broadcast protocol related code */
+uint8_t is_start_frame(uint16_t len)
+{
+ return (len == START_FRAME);
+}
+
+uint8_t is_group_frame(uint16_t len)
+{
+ /* is group frame? */
+ return (len > GROUP_FRAME && len <= GROUP_FRAME_END);
+}
+
+uint8_t is_data_frame(uint16_t len)
+{
+ uint8_t group_frame, index;
+ /* is start frame */
+ if (is_start_frame(len)) {
+ return 0;
+ }
+
+ /* is group frame? */
+ group_frame = is_group_frame(len);
+ if (group_frame) {
+ return 0;
+ }
+
+ index = (len >> PAYLOAD_BITS_CNT) & 0xF;
+ return (index >= ZC_GRP_PKT_IDX_START && index <= ZC_GRP_PKT_IDX_END);
+}
+
+uint8_t get_group_index(uint16_t len)
+{
+ if (is_start_frame(len)) {
+ return 0;
+ }
+
+ return (len - GROUP_FRAME) * GROUP_NUMBER;
+}
+
+uint8_t get_data_index(uint16_t len)
+{
+ uint8_t index = (len >> PAYLOAD_BITS_CNT) & 0xF; /* from 2 to 9 */
+ return index - (ZC_GRP_PKT_IDX_START - 1); /* adjust, from 1 to 8 */
+}
+
+#define sn_minus(a,b) (((a) - (b)) & 0xfff)
+
+/* a, b must be serial seq number */
+static int sn_compare(uint16_t a, uint16_t b)
+{
+ /*
+ case1: sn = 3, sn_prev = 5; a < b
+ case2: sn = 0, sn_prev = 0xfff; a > b
+ case3: sn = 4, sn_prev = 3; a > b
+ */
+ uint16_t res = sn_minus(a, b);
+
+ return res < 1000 ? res : -1;
+}
+
+/*
+ * zconfig_get_data_len()
+ * here we guess the total_len of protocl message,
+ * base on the score of tods and fromds side.
+ */
+int zconfig_get_data_len(void)
+{
+ uint8_t len; /* total len, include len(1B) & crc(2B) */
+ uint8_t score;
+
+ /* tods > fromds */
+ if (zconfig_data->pkg[1][1].score > zconfig_data->pkg[0][1].score) {
+ len = zconfig_data->pkg[1][1].len & PAYLOAD_BITS_MASK;
+ score = zconfig_data->pkg[1][1].score;
+ } else {
+ len = zconfig_data->pkg[0][1].len & PAYLOAD_BITS_MASK;
+ score = zconfig_data->pkg[0][1].score;
+ }
+
+ if (len && score > score_mid) {
+ /* awss_debug("zconfig_get_data_len = %d\r\n", len); */
+ goto out;
+ }
+
+ if (zconfig_data->data[1].max_pos > zconfig_data->data[0].max_pos) {
+ len = zconfig_data->data[1].max_pos;
+ } else {
+ len = zconfig_data->data[0].max_pos;
+ }
+out:
+ if (len < GROUP_NUMBER) {
+ return GROUP_NUMBER;
+ } else {
+ return len >= MAX_PKG_NUMS ? (MAX_PKG_NUMS - GROUP_NUMBER - 1) : len;
+ }
+}
+
+/* check recv completed or not */
+int zconfig_recv_completed(uint8_t tods)
+{
+ int i;
+ uint8_t len, flag, ssid_len, passwd_len;
+ /*
+ byte: 0 1 2 3 4 5 6
+ name: total_len flag ssid_len passwd_len ssid ...
+ index: 0x100 0x180 0x200 0x280 0x300 0x380
+ */
+ len = pkg_len(1) & PAYLOAD_BITS_MASK;/* total len, include len(1B) & crc(2B) */
+ flag = pkg_len(2) & PAYLOAD_BITS_MASK;
+ if (flag & SSID_EXIST_MASK) {/* ssid exist */
+ ssid_len = pkg_len(3) & PAYLOAD_BITS_MASK;
+ passwd_len = pkg_len(4) & PAYLOAD_BITS_MASK;
+ } else {
+ ssid_len = 0;
+ passwd_len = pkg_len(3) & PAYLOAD_BITS_MASK;
+ }
+
+ if (!len || pkg_score(1) <= score_min) {
+ /* awss_trace("len=%d, pkg_score(1)=%d\r\n", len, pkg_score(1));*/
+ return 0;
+ }
+
+#ifndef DISABLE_SSID_AUTO_COMPLETE
+#define SSID_AUTO_COMPLETE_SCORE (score_max + 1)
+ /* ssid atuo-completion */
+ if (zc_ssid[0] != '\0' && (flag & SSID_EXIST_MASK)
+ && pkg_score(2) < SSID_AUTO_COMPLETE_SCORE
+ && pkg_score(3) > score_mid
+ && !zc_ssid_auto_complete_disable) {
+
+ /* over-written ssid_len here */
+ ssid_len = strlen((char const *)zc_ssid);
+ if (ssid_len > ZC_MAX_SSID_LEN - 1) {
+ ssid_len = ZC_MAX_SSID_LEN - 1;
+ }
+
+ if (!(flag & SSID_ENCODE_MASK)) {/* ASCLL ssid */
+ if ((ssid_len | 0x200) != pkg_len(3)) {
+ awss_warn("ssid len not match! ssid:%s != %d\r\n",
+ zc_ssid, (pkg_len(3) & ~0x200));
+ zc_ssid_auto_complete_disable = 1;
+ goto skip_ssid_auto_complete;
+ }
+
+ awss_trace("ssid auto-complete: %s\r\n", zc_ssid);
+ pkg_score(2) = SSID_AUTO_COMPLETE_SCORE;
+
+ pkg_len(3) = ssid_len | 0x200; /* 0x200 is the index 3 */
+ pkg_score(3) = SSID_AUTO_COMPLETE_SCORE;
+
+ for (i = 5; i < ssid_len + 5; i ++) {
+ pkg_len(i) = (zc_ssid[i - 5] - 32) | (0x100 + 0x80 * ((i - 1) % GROUP_NUMBER));
+ pkg_score(i) = SSID_AUTO_COMPLETE_SCORE;
+ }
+ } else if ((flag & SSID_ENCODE_MASK)) { /* include chinese ssid */
+ uint8_t *buf, buf_len = 0;
+
+ uint8_t ssid_encode_len = (ssid_len * 8 + 5) / 6;
+
+ /*
+ * for GBK encoded chinese, ssid auto-completion lead to crc error.
+ * because Android APP may send utf8 encoded ssid.
+ */
+ if ((ssid_encode_len | 0x200) != pkg_len(3)) {
+ zc_ssid_is_gbk = 1;
+ zc_ssid_auto_complete_disable = 1;
+ goto skip_ssid_auto_complete;
+ } else {
+ zc_ssid_is_gbk = 0;
+ }
+
+ buf = os_zalloc(ssid_encode_len + 1);
+ if (buf == NULL) {
+ awss_crit("malloc failed!\r\n");
+ return 0;
+ }
+
+ awss_trace("chinese ssid auto-complete: %s\r\n", zc_ssid);
+ encode_chinese(zc_ssid, ssid_len, buf, &buf_len, 6);
+
+ pkg_score(2) = SSID_AUTO_COMPLETE_SCORE;
+
+ pkg_len(3) = buf_len | 0x200; /* 0x200 is the index 3 */
+ pkg_score(3) = SSID_AUTO_COMPLETE_SCORE;
+
+ for (i = 5; i < buf_len + 5; i ++) {
+ pkg_len(i) = buf[i - 5] | (0x100 + 0x80 * ((i - 1) % GROUP_NUMBER));
+ pkg_score(i) = SSID_AUTO_COMPLETE_SCORE;
+ }
+ HAL_Free(buf);
+ }
+ }
+#endif
+
+skip_ssid_auto_complete:
+ /* awss_debug("expect len = %d, max len = %d\r\n", len, zc_max_pos); */
+ if (zc_max_pos < len) {
+ return 0; /* receive all the packets */
+ }
+
+ for (i = 1; i <= len; i ++) { /* check score for all the packets */
+ if (pkg_score(i) <= score_min) {
+ return 0;
+ }
+ }
+
+ /* 4 for total_len, flag, ssid_len, passwd_len, 2 for crc */
+ if (flag & SSID_EXIST_MASK) { /* ssid exist */
+ if (len != ssid_len + passwd_len + 4 + 2) {
+ return 0;
+ }
+ } else if (len != passwd_len + 3 + 2) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int zconfig_get_ssid_passwd(uint8_t tods)
+{
+ int i, ssid_len, package_num, passwd_len, ret;
+ uint8_t *buf, *pbuf, *tmp, flag, passwd_encrypt, passwd_cipher_len = 0;
+ uint16_t crc, cal_crc;
+ uint8_t data, score;
+ uint8_t tods_tmp;
+
+ if (!zconfig_recv_completed(tods)) {
+ return -1;
+ }
+
+ buf = os_zalloc(256);
+ if (NULL == buf) {
+ awss_crit("malloc failed!\r\n");
+ return -1;
+ }
+ tmp = os_zalloc(128);
+ if (NULL == tmp) {
+ HAL_Free(buf);
+ awss_crit("malloc failed!\r\n");
+ return -1;
+ }
+
+ /* package num */
+ package_num = pkg_len(1) & PAYLOAD_BITS_MASK;/* total len, include len(1B) & crc(2B) */
+
+ awss_trace("\r\n");
+ for (i = 1; i <= package_num; i ++) {
+ data = pkg_len(i);
+ score = pkg_score(i);
+ buf[i - 1] = data & PAYLOAD_BITS_MASK;
+ tmp[i - 1] = score;
+ }
+
+ dump_hex(&tmp[0], package_num, GROUP_NUMBER);
+ awss_trace("\r\n");
+ dump_hex(&buf[0], package_num, GROUP_NUMBER);
+ awss_trace("\r\n");
+
+ crc = os_get_unaligned_be16(&buf[package_num - 2]);
+
+ pbuf = &buf[0]; /* len @ [0] */
+
+ flag = pbuf[1]; /* flag @ [1] */
+ pbuf += 2; /* 2B for total_len, flag */
+
+ passwd_encrypt = (flag & PASSWD_ENCRYPT_MASK) >> PASSWD_ENCRYPT_BIT_OFFSET;
+
+ if (passwd_encrypt == PASSWD_ENCRYPT_CIPHER || passwd_encrypt == PASSWD_ENCRYPT_OPEN) {
+ awss_trace("!aes128-cfb is not support: flag 0x%x\r\n", flag);
+ ret = -1;
+ goto exit;
+ } else {
+ cal_crc = zconfig_checksum_v3(buf, package_num - 2);
+ }
+
+ if (crc != cal_crc) {
+ awss_trace("crc error: recv 0x%x != 0x%x\r\n", crc, cal_crc);
+ /* memset(zconfig_data, 0, sizeof(*zconfig_data)); */
+ tods_tmp = tods;
+ for (tods = 0; tods < 2; tods ++) {
+ for (i = 1; i <= package_num; i ++) {
+ score = pkg_score(i);
+ if (score > 0x60) {
+ pkg_score(i) = 0x60;
+ } else {
+ pkg_score(i) = score >> 1;
+ }
+ }
+ }
+ tods = tods_tmp;
+ ret = -1;
+ awss_event_post(IOTX_AWSS_CS_ERR);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_SM_IDX, AWSS_STATIS_TYPE_CRC_ERR);
+ goto exit;
+ }
+
+ if (flag & SSID_EXIST_MASK) {/* ssid exist */
+ ssid_len = pbuf[0];
+ passwd_len = pbuf[1];
+ pbuf += 2; /* 2B for ssid_len, passwd_len */
+
+ if (!(flag & SSID_ENCODE_MASK)) { /* ascii */
+ /* CAN'T use snprintf here, because of SPACE char */
+ memcpy((char *)tmp, pbuf, ssid_len);
+ tmp[ssid_len] = '\0';
+ for (i = 0; i < ssid_len; i ++) {
+ tmp[i] += 32;
+ }
+ } else {/* chinese format */
+ decode_chinese(pbuf, ssid_len, tmp, NULL, 6);
+ /* make sure 'tmp' is null-terminated */
+ }
+ pbuf += ssid_len; /* ssid */
+
+ if (zc_ssid[0] == '\0' || zc_ssid_auto_complete_disable) {
+ strncpy((char *)zc_ssid, (const char *)tmp, ZC_MAX_SSID_LEN - 1);
+ awss_trace("SSID0: [%s]\r\n", zc_ssid);
+ } else {
+ if (!strncmp((const char *)tmp, (char *)zc_ssid, ZC_MAX_SSID_LEN - 1)) {
+ awss_trace("SSID1: [%s]\r\n", zc_ssid);
+ } else {
+ awss_trace("gbk%s SSID:[%s]\r\n", zc_ssid_is_gbk ? "" : "?", zc_ssid);
+ }
+ }
+#ifdef AWSS_SUPPORT_APLIST
+ do { /* amend SSID automatically */
+ struct ap_info *ap = NULL;
+ ap = zconfig_get_apinfo(zc_bssid);
+ if (ap == NULL || ap->ssid[0] == '\0') {
+ break;
+ }
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ if (strncmp(ap->ssid, zc_adha_ssid, ZC_MAX_SSID_LEN) == 0 ||
+ strncmp(ap->ssid, zc_default_ssid, ZC_MAX_SSID_LEN) == 0) {
+ memset(zc_bssid, 0, ETH_ALEN);
+ break;
+ }
+#endif
+ strncpy((char *)zc_ssid, (const char *)ap->ssid, ZC_MAX_SSID_LEN - 1);
+ } while (0);
+#endif
+ } else {
+ passwd_len = pbuf[0];
+ pbuf += 1; /* 1B for passwd_len */
+ }
+
+ /* CAN'T use snprintf here, because of SPACE char */
+ if (passwd_encrypt > PASSWD_ENCRYPT_CIPHER) {
+ /* decypt passwd using aes128-cfb */
+ decode_chinese(pbuf, passwd_len, tmp, &passwd_cipher_len, 6);
+ passwd_len = passwd_cipher_len;
+ memset(zc_passwd, 0, ZC_MAX_PASSWD_LEN);
+ aes_decrypt_string((char *)tmp, (char *)zc_passwd, passwd_len,
+ 1, awss_get_encrypt_type(), 0, NULL);
+ if (is_utf8((const char *)zc_passwd, passwd_len) == 0) {
+ awss_trace("passwd err\r\n");
+ memset(zconfig_data, 0, sizeof(*zconfig_data));
+ awss_event_post(IOTX_AWSS_PASSWD_ERR);
+ AWSS_UPDATE_STATIS(AWSS_STATIS_SM_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ ret = -1;
+ goto exit;
+ }
+ } else {
+ memcpy((void *)tmp, (const void *)pbuf, passwd_len);
+ tmp[passwd_len] = '\0';
+ for (i = 0; i < passwd_len; i ++) {
+ tmp[i] += 32;
+ }
+ strncpy((char *)zc_passwd, (const char *)tmp, ZC_MAX_PASSWD_LEN - 1);
+
+ awss_trace("encrypt:%d not support\r\n", passwd_encrypt);
+ memset(zconfig_data, 0, sizeof(*zconfig_data));
+ ret = -1;
+ goto exit;
+ }
+
+
+ /* awss_debug("PASSWD: [%s]\r\n", zc_passwd); */
+ pbuf += passwd_len; /* passwd */
+ ret = 0;
+exit:
+ HAL_Free(buf);
+ HAL_Free(tmp);
+
+ return ret;
+}
+
+int package_cmp(uint8_t *package, uint8_t *src, uint8_t *dst, uint8_t tods, uint16_t len)
+{
+ struct package *pkg = (struct package *)package;
+
+ if (pkg->len != len) {
+ return 1;
+ }
+ return 0;
+}
+
+int package_save(uint8_t *package, uint8_t *src, uint8_t *dst, uint8_t tods, uint16_t len)
+{
+ struct package *pkg = (struct package *)package;
+
+ pkg->len = len;
+ return 0;
+}
+
+/* len -= (rth->it_len + hdrlen); see ieee80211.c */
+const uint8_t zconfig_fixed_offset[ZC_ENC_TYPE_MAX + 1][2] = {
+ { /* open, none, ip(20) + udp(8) + 8(LLC) */
+ 36, 36
+ },
+ { /* wep, + iv(4) + data + ICV(4) */
+ 44, 44 /* feixun, wep64(10byte), wep128(26byte) */
+ },
+ { /* tkip, + iv/keyID(4) + Ext IV(4) + data + MIC(8) + ICV(4) */
+ 56, 56 /* tkip(10byte, 20byte), wpa2+tkip(20byte) */
+ },
+ { /* aes, + ccmp header(8) + data + MIC(8) + ICV(4) */
+ 52, 52
+ },
+ { /* tkip-aes */
+ 56, 52 /* fromDs==tkip,toDs==aes */
+ }
+};
+
+const uint16_t zconfig_hint_frame[] = {/* GROUP_FRAME is not used, gourp 0 - 7 */
+ START_FRAME, GROUP_FRAME + 1, GROUP_FRAME + 2, GROUP_FRAME + 3, GROUP_FRAME + 4,
+ GROUP_FRAME + 5, GROUP_FRAME + 6, GROUP_FRAME + 7,
+ 0 /* NULL terminated */
+};
+
+/*
+ * is_hint_frame()
+ *
+ * start frame or group frame can be used as a hint frame
+ *
+ * @Return:
+ * 1/is start or group frame, otherwise return 0.
+ */
+int is_hint_frame(uint8_t encry, int len, uint8_t *bssid, uint8_t *src,
+ uint8_t channel, uint8_t tods, uint16_t sn)
+{
+ int i;
+
+ if (encry > ZC_ENC_TYPE_MAX) {
+ return 0;
+ }
+
+ len -= zconfig_fixed_offset[encry][0]; /* dont't care about tkip-aes */
+
+ for (i = 0; zconfig_hint_frame[i]; i++) {
+ if (zconfig_hint_frame[i] == len) {
+ goto found_match;
+ }
+ }
+
+ return 0;
+
+found_match:
+ /* tods/fromds already locked? */
+ if (!memcmp(zc_bssid, zero_mac, ETH_ALEN)) {
+ /* zero mac means not locked */
+ memcpy(zc_bssid, bssid, ETH_ALEN);
+ memcpy(zc_src_mac, src, ETH_ALEN);
+ } else {
+ /*
+ * 1) src not equal, bssid equal, interference
+ * 2) src not equal, bssid not equal, interference
+ * 3) src equal, bssid equal, good, go on
+ * 4) src equal, bssid not equal
+ * if tods is true, replace old ssid in case of WDS
+ * if fromds is true, APP change the AP?? or WDS??
+ * in this situation, zc_bssid is set by tods,
+ * in WDS case, zc_bssid should be unchanged
+ */
+
+ if (memcmp(zc_src_mac, src, ETH_ALEN)) {/* case 1,2 */
+ /* someone must be working in aws at the same time */
+ awss_warn("%c interference src:"MAC_FORMAT", bssid:"MAC_FORMAT"\r\n",
+ flag_tods(tods), MAC_VALUE(src), MAC_VALUE(bssid));
+ return 0;
+ } else {
+ if (memcmp(zc_bssid, bssid, ETH_ALEN)) {/* case 4 */
+ if (tods) {
+ memcpy(zc_bssid, bssid, ETH_ALEN);
+ memcpy(zc_src_mac, src, ETH_ALEN);
+ /* TODO: clear previous buffer, channel lock state? */
+ if (zconfig_data->data[0].state_machine == STATE_CHN_LOCKED_BY_BR) {
+ zconfig_data->data[0].state_machine = STATE_CHN_SCANNING;
+ }
+ awss_warn("%c WDS! bssid:"MAC_FORMAT" -> bssid:"MAC_FORMAT"\r\n",
+ flag_tods(tods), MAC_VALUE(zc_bssid),
+ MAC_VALUE(bssid));
+ } else {
+ awss_trace("%c WDS? src:"MAC_FORMAT" -> bssid:"MAC_FORMAT"\r\n",
+ flag_tods(tods), MAC_VALUE(src),
+ MAC_VALUE(bssid));
+ return 0;
+ }
+ } /* else case */
+ }
+ }
+
+ zc_frame_offset = zconfig_fixed_offset[encry][0];/* delta, len(80211) - len(8023) */
+ zc_group_pos = i * GROUP_NUMBER;
+ zc_cur_pos = zc_group_pos;
+ zc_group_sn = sn;
+ zc_prev_sn = sn;
+ zc_score_uplimit = score_max;
+
+ memset(zc_ssid, 0, ZC_MAX_SSID_LEN);
+#ifdef AWSS_SUPPORT_APLIST
+ /* fix channel with apinfo if exist, otherwise return anyway. */
+ do {
+ struct ap_info *ap_info = zconfig_get_apinfo(bssid);
+ extern void aws_set_dst_chan(int channel);
+ if (ap_info && ap_info->encry[tods] > ZC_ENC_TYPE_MAX) {
+ awss_warn("invalid apinfo ssid:%s\r\n", ap_info->ssid);
+ }
+
+ if (ap_info && ap_info->encry[tods] == encry && ap_info->channel) {
+ if (channel != ap_info->channel) {
+ awss_info("fix channel from %d to %d\r\n", channel, ap_info->channel);
+ zc_channel = ap_info->channel; /* fix by ap_info channel */
+ aws_set_dst_chan(zc_channel);
+ }
+ } else {
+ /* warning: channel may eq 0! */
+ };
+
+ if (ap_info) { /* save ssid */
+ strncpy((char *)zc_ssid, (const char *)ap_info->ssid, ZC_MAX_SSID_LEN - 1);
+ }
+ } while (0);
+#endif
+
+ return 1;
+}
+
+/*
+ * get_data_score()
+ *
+ * calc package score
+ *
+ * @Return:
+ * score between [0, 100]
+ */
+uint8_t get_data_score(uint16_t group_sn, uint16_t sn_now, uint16_t sn_last,
+ uint8_t index_now, uint8_t index_last, uint8_t tods)
+{
+ /*
+ example: 1
+ 8+3 250 0 d0e cc:fa:00:c8:cf:d2 > ff:ff:ff:ff:ff:ff
+ 8+4 2bf 0 d15 cc:fa:00:c8:cf:d2 > ff:ff:ff:ff:ff:ff //两个包index_delta=1, sn_delta=7
+
+ example: 2
+ 8+0, 3e1, 9a5
+ 8+1, 13f, 9a7
+ group_sn=9a7, sn=9ab-9a7, pos=e-9, len=3ce //here, index_delta=5, sn_delta=4
+ group_sn=9a7, sn=9ac-9ab, pos=f-9, len=454
+ group_sn=9a7, sn=9ad-9ac, pos=10-9, len=4d2
+ example: 3
+ 8+3, 225, a32
+ 8+6, 3c7, a39 //此处应该是16+6, index_delta=3, sn_delta=7
+ example: 4
+ 0+0, 4e0, da5
+ 0+7, 441, dab //此处应该是8+7, index_delta=7, sn_delta=6
+ 0+0, 4e0, d89
+ 0+8, 4c2, d8f //此处应该是8+8, index_delta=8, sn_delta=6
+
+ //example: 4
+ 0+0 [100] 294 0 4e0
+ 0+1 [60] 2a2 0 11a
+ 0+2 [40] 2aa 0 181
+ group_sn:2aa, sn:2b8-2aa=14, pos:3-2, len:20a
+ group_sn:2aa, sn:2bc-2b8=18, pos:4-2, len:28a
+ group_sn:2aa, sn:2c0-2bc=22, pos:5-2, len:310
+ group_sn:2aa, sn:2c4-2c0=26, pos:6-2, len:391
+ group_sn:2aa, sn:2c8-2c4=30, pos:7-2, len:412
+ group_sn:2aa, sn:2cc-2c8=34, pos:8-2, len:493
+ */
+ static const uint16_t score_level[][2] = {
+ {0, 0},
+ {1, 2}, /* include, example 1, 3 */
+ {4, 8},
+ {8, 16},/* example 1 */
+ {15, 30},
+ {40, 40},
+ {0xFFFF, score_max} /* the end missing seq, example 2 */
+ };
+
+ uint16_t sn_delta = sn_minus(sn_now, group_sn) - 1;
+ uint16_t index_delta = (index_now - index_last) - 1;
+ uint16_t delta = sn_delta + index_delta;
+
+ uint8_t i = 0;
+ uint8_t res;
+
+ /* suppose: sn > zc_prev_sn, pos > zc_cur_pos */
+ if (sn_compare(sn_now, group_sn) <= 0 || sn_compare(sn_now, zc_prev_sn) <= 0) {
+ return score_min;
+ } else if (index_now <= index_last) {
+ return score_min;
+ }
+
+ while (delta > score_level[i][0]) { /* include */
+ i ++;
+ }
+
+ res = score_level[i][1];
+
+ if (zc_score_uplimit > res) {
+ return zc_score_uplimit - res;
+ } else {
+ return score_low;
+ }
+}
+
+/*
+ 遍历所有分组,找到最多匹配的分组: 分组号,匹配的起止位置,匹配的最小score
+ 遍历分两步:遍历相等的数量 和 遍历空位置的数量
+ guess_pos: 根据前后位置确定的pos
+ match_pos: 根据匹配计算的pos
+
+ 1) 如果guess_pos && match_pos存在,且相等,则score += 5, pos = match_pos
+ 2) 不相等,则score -= 5, pos = match_pos
+ 3) 只有guess_pos存在,则score = 2
+ 4) 只有match_pos存在,则score不变
+*/
+int try_to_sync_pos(uint8_t tods, uint16_t last_sn, uint8_t sn,
+ int last_group_pos, int group_pos)
+{
+ int ret = -1, empty_match = 0, reason = 0;
+ int guess_pos = -1, final_pos = -1;
+
+ int max_match = 0, match_group = -1, match_end = GROUP_NUMBER, match_score = 0;
+ int match, i, j, score; /* loop variable */
+
+retry:
+ for (i = 0; i <= zconfig_get_data_len(); i += GROUP_NUMBER) {
+ for (match = 0, score = score_max, j = 1; j <= GROUP_NUMBER; j ++) {
+ if (!tmp_score(j)) {
+ continue;
+ }
+
+ if (empty_match) {
+ if (pkg_score(i + j) <= 1) {
+ match++;
+ score = 1;
+ }
+ } else {
+ if (!pkg_len(i + j)) {
+ continue;
+ }
+ if (pkg_len(i + j) == tmp_len(j)) {
+ match ++;
+ score = (score > pkg_score(i + j)) ? pkg_score(i + j) : score;
+ } else {/* encounter first unmatch */
+ awss_trace("[%d]=%x, [%d]=%x\r\n", i + j, pkg_len(i + j), j, tmp_len(j));
+ break;
+ }
+ }
+ }
+ if (match > max_match) {
+ max_match = match;
+ match_group = i;
+ match_end = j - 1;
+ match_score = score;
+ awss_trace("match=%d, match_group=%d, match_end=%d\r\n",
+ match, match_group, match_end);
+ }
+ }
+
+ if (!max_match && !empty_match) {/* retry empty place match */
+ empty_match = 1;
+ goto retry;
+ }
+
+ if (group_pos != -1) {/* 根据后位置确定 */
+ guess_pos = group_pos - GROUP_NUMBER;/* 前一组 */
+ if (guess_pos < 0) {
+ guess_pos = (zconfig_get_data_len() / GROUP_NUMBER) * GROUP_NUMBER;
+ }
+
+ if (!max_match || empty_match) {/* case 3 */
+ match_score = 2;
+ final_pos = guess_pos;
+ reason = 3;
+ goto replace;
+ /* can not del goto, cause guess_pos has higher priority than empty match */
+ }
+ }
+ /* 前位置 有效性难以判断,忽略 */
+
+ if (max_match > 0) {
+ if (max_match == 1) {
+ match_score = match_score > 10 ? 10 : match_score;
+ } else if (max_match == 2) {
+ match_score = match_score > 20 ? 20 : match_score;
+ } else if (max_match <= GROUP_NUMBER) {
+ match_score = match_score > 30 ? 30 : match_score;
+ } else {
+ goto clear;
+ }
+
+ if (guess_pos != -1) {
+ if (guess_pos == match_group) {/* case 1 */
+ match_end = GROUP_NUMBER;
+ match_score += 2;/*bonus */
+ final_pos = match_group;
+ reason = 1;
+ } else {/*case 2*/
+ match_score -= 0;/*bonus*/
+ if (max_match >= 2 && !empty_match) {
+ final_pos = match_group;
+ } else {
+ final_pos = guess_pos;
+ }
+ reason = 2;
+ }
+ } else {/*case 4: 只有match_pos存在*/
+ final_pos = match_group;
+
+ reason = 4;
+ }
+ } else {
+ goto clear;
+ }
+
+replace:
+ if (final_pos != -1) {
+ reason = reason;
+ awss_trace("\tX = %d, score=%d, match=%d, reason=%d\r\n", final_pos, match_score, max_match, reason);
+ if (match_end != GROUP_NUMBER) {
+ awss_trace("\t match from [1-%d]\r\n", match_end);
+ }
+ for (i = final_pos + 1, j = 1; i <= final_pos + match_end; i++, j++) {
+ if (j > GROUP_NUMBER || i >= MAX_PKG_NUMS) {
+ break;
+ }
+ if (pkg_score(i) < match_score && tmp_score(j)) {
+ pkg_len(i) = tmp_len(j);
+ pkg_score(i) = (match_score > tmp_score(j) - 1) ?
+ (match_score - (tmp_score(j) - 1)) : match_score;/*TODO*/
+ awss_trace("\t%d+%d [%d] %c %-3x\r\n", final_pos, j, pkg_score(i), flag_tods(tods), tmp_len(j));
+
+ zc_replace = 1;
+ if (zc_max_pos < i) {
+ zc_max_pos = i;
+ }
+
+ ret = 0;
+ }
+ }
+ }
+
+clear:
+ zc_pos_unsync = 0;
+ memset((uint8_t *)tmp(0), 0, sizeof(zconfig_data->tmp_pkg[0]));
+ return ret;
+}
+
+/*
+ 判断同一个位置是否应发生替换
+ 调用该函数的前提: 同一个位置pos, 相同的得分score, 不同的数据
+ 替换条件: 在各分组相同位置下,旧的数据有重复,新的数据无重复
+*/
+int try_to_replace_same_pos(int tods, int pos, int new_len)
+{
+ int replace = 0, i, old_match = 0, new_match = 0;
+
+ for (i = pos % GROUP_NUMBER; i <= zconfig_get_data_len();
+ i += GROUP_NUMBER) {
+ if (i != pos && pkg_len(i) == pkg_len(pos)) {
+ old_match = 1;
+ }
+
+ if (pkg_len(i) == new_len) {
+ new_match = 1;
+ }
+ }
+
+ if ((old_match && !new_match) || tods == 0) {
+ replace = 1;
+ pkg_len(pos) = new_len;
+ }
+
+ return replace;
+}
+
+int awss_ieee80211_smartconfig_process(uint8_t *ieee80211, int len, int link_type, struct parser_res *res,
+ signed char rssi)
+{
+ int hdrlen, fc, seq_ctrl;
+ struct ieee80211_hdr *hdr;
+ uint8_t *data, *bssid_mac, *dst_mac;
+ uint8_t encry = ZC_ENC_TYPE_INVALID;
+ uint8_t tods;
+
+ /*
+ * when device try to connect current router (include adha and aha)
+ * skip the new packet.
+ */
+ if (ieee80211 == NULL || zconfig_finished) {
+ return ALINK_INVALID;
+ }
+
+ /*
+ * we don't process smartconfig until user press configure button
+ */
+ if (awss_get_config_press() == 0) {
+ return ALINK_INVALID;
+ }
+
+ hdr = (struct ieee80211_hdr *)ieee80211;
+ fc = hdr->frame_control;
+ seq_ctrl = hdr->seq_ctrl;
+
+ /*
+ * for smartconfig with bcast of data
+ */
+ if (!ieee80211_is_data_exact(fc)) {
+ return ALINK_INVALID;
+ }
+
+ /* tods = 1, fromds = 0 || tods = 0, fromds = 1 */
+ if (ieee80211_has_tods(fc) == ieee80211_has_fromds(fc)) {
+ return ALINK_INVALID;
+ }
+ /* drop frag, more, order*/
+ if (ieee80211_has_frags(fc)) {
+ return ALINK_INVALID;
+ }
+
+ dst_mac = (uint8_t *)ieee80211_get_DA(hdr);
+ if (memcmp(dst_mac, br_mac, ETH_ALEN)) {
+ return ALINK_INVALID; /* only handle br frame */
+ }
+
+ bssid_mac = (uint8_t *)ieee80211_get_BSSID(hdr);
+
+ /*
+ * payload len = frame.len - (radio_header + wlan_hdr)
+ */
+ hdrlen = ieee80211_hdrlen(fc);
+ if (hdrlen > len) {
+ return ALINK_INVALID;
+ }
+
+#ifdef _PLATFORM_QCOM_
+ /* Note: http://stackoverflow.com/questions/17688710/802-11-qos-data-frames */
+ hdrlen = (hdrlen + 3) & 0xFC;/* align header to 32bit boundary */
+#endif
+
+ res->u.br.data_len = len - hdrlen; /* eating the hdr */
+ res->u.br.sn = IEEE80211_SEQ_TO_SN(os_le16toh(seq_ctrl));
+
+ data = ieee80211 + hdrlen; /* eating the hdr */
+ tods = ieee80211_has_tods(fc);
+
+ do {
+#ifdef AWSS_SUPPORT_APLIST
+ struct ap_info *ap_info;
+ ap_info = zconfig_get_apinfo(bssid_mac);
+ if (ap_info && ZC_ENC_TYPE_INVALID != ap_info->encry[tods]) {
+ encry = ap_info->encry[tods];
+ } else
+#endif
+ {
+ if (!ieee80211_has_protected(fc)) {
+ encry = ZC_ENC_TYPE_NONE;
+ } else {
+ /* Note: avoid empty null data */
+ if (len < 8) { /* IV + ICV + DATA >= 8 */
+ return ALINK_INVALID;
+ }
+ if (!(data[3] & 0x3F)) {
+ encry = ZC_ENC_TYPE_WEP;
+ } else if (data[3] & (1 << 5)) {/* Extended IV */
+ if (data[1] == ((data[0] | 0x20) & 0x7F)) { /* tkip, WEPSeed = (TSC1 | 0x20 ) & 0x7F */
+ encry = ZC_ENC_TYPE_TKIP;
+ }
+ if (data[2] == 0 && (!(data[3] & 0x0F))) {
+ encry = ZC_ENC_TYPE_AES;
+ }
+
+ /*
+ * Note: above code use if(tkip) and if(ase)
+ * instead of if(tkip) else if(aes)
+ * beacause two condition may bother match.
+ */
+ }
+ }
+ }
+ } while (0);
+
+ if (encry == ZC_ENC_TYPE_INVALID) {
+ awss_warn("invalid encry type!\r\n");
+ }
+ res->u.br.encry_type = encry;
+
+ /* convert IEEE 802.11 header + possible LLC headers into Ethernet header
+ * IEEE 802.11 address fields:
+ * ToDS FromDS Addr1 Addr2 Addr3 Addr4
+ * 0 0 DA SA BSSID n/a
+ * 0 1 DA BSSID SA n/a
+ * 1 0 BSSID SA DA n/a
+ * 1 1 RA TA DA SA
+ */
+ res->src = ieee80211_get_SA(hdr);
+ res->dst = ieee80211_get_DA(hdr);
+ res->bssid = ieee80211_get_BSSID(hdr);
+ res->tods = ieee80211_has_tods(fc);
+
+ return ALINK_BROADCAST;
+}
+
+int awss_recv_callback_smartconfig(struct parser_res *res)
+{
+ static char statis = 0;
+ uint32_t timestamp = os_get_time_ms();
+
+ uint8_t *src = res->src;
+ uint8_t *dst = res->dst;
+ uint8_t *bssid = res->bssid;
+ uint8_t tods = res->tods;
+ uint8_t channel = res->channel;
+
+ uint16_t sn = res->u.br.sn;
+ uint16_t len = res->u.br.data_len;
+ uint8_t encry_type = res->u.br.encry_type;
+
+ int ret, pkg_type = PKG_INVALID;
+ uint8_t score = 0, timeout = 0, equal = 0;
+
+ uint16_t pos = 0, index = 0;
+
+ awss_flow("len=%d, %c, sn=%d, enc=%d, chn=%d, src=%02x%02x%02x%02x%02x%02x\r\n",
+ len, flag_tods(tods), sn, encry_type, channel,
+ src[0], src[1], src[2], src[3], src[4], src[5]);
+ /*
+ * STATE_CHN_LOCKED_BY_P2P is set by v2 wps/action frame, which means
+ * APP is sending v2, but if v2 is fail, APP will rollback to v1,
+ * so still need to parse br frame here
+ * even zc_state == STATE_CHN_LOCKED_BY_P2P.
+ */
+ if (zc_state == STATE_CHN_LOCKED_BY_P2P ||
+ zc_state == STATE_CHN_SCANNING) {
+ if (is_hint_frame(encry_type, len, bssid, src, channel, tods, sn)) {
+ if (statis == 0) {
+ statis = 1;
+ AWSS_UPDATE_STATIS(AWSS_STATIS_SM_IDX, AWSS_STATIS_TYPE_TIME_START);
+ }
+ awss_trace("hint frame: offset:%d, %c, sn:%x\r\n",
+ zc_frame_offset, flag_tods(tods), sn);
+
+ awss_trace("src:%02x%02x%02x%02x%02x%02x, bssid:%02x%02x%02x%02x%02x%02x\r\n",
+ src[0], src[1], src[2], src[3], src[4], src[5],
+ bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+
+ pkg_type = PKG_START_FRAME;
+ zconfig_set_state(STATE_CHN_LOCKED_BY_BR, tods, channel);
+
+ goto update_sn;
+ } else if (!memcmp(zc_android_src, src, ETH_ALEN)) {
+#ifdef AWSS_SUPPORT_APLIST
+ struct ap_info *ap_info = zconfig_get_apinfo(bssid);
+ if (ap_info) {
+ if (ap_info->ssid[0] != 0x00 && ap_info->ssid[0] != 0xFF) {
+ strncpy((char *)zc_android_ssid, (const char *)ap_info->ssid, ZC_MAX_SSID_LEN - 1);
+ }
+ memcpy(zc_android_bssid, bssid, ETH_ALEN);
+ awss_trace("src %02x%02x%02x match %02x%02x%02x\r\n",
+ zc_android_src[0], zc_android_src[1], zc_android_src[2],
+ zc_android_bssid[0], zc_android_bssid[1], zc_android_bssid[2]);
+ }
+#endif
+ }
+ } else if (zc_state == STATE_CHN_LOCKED_BY_BR) {
+ /* same src mac & br & bssid */
+ if (memcmp(&src[0], zc_src_mac, ETH_ALEN) ||
+ memcmp(&dst[0], br_mac, sizeof(br_mac)) ||
+ memcmp(bssid, zc_bssid, ETH_ALEN)) { /* in case of WDS */
+ goto drop;
+ }
+
+ if (timestamp - zc_timestamp > time_interval) {
+ awss_debug("\t\t\t\t\ttimestamp = %d\r\n", timestamp - zc_timestamp);
+ timeout = 1;
+ }
+
+ ret = sn_compare(sn, zc_prev_sn);
+ if (ret <= 0) { /* retry packet, update timestamp */
+ zc_timestamp = timestamp;
+ }
+ if (ret == 0) {
+ awss_debug("drop: %3x == %3x\r\n", sn, zc_prev_sn);/* log level, too many retry pkg */
+ goto drop;
+ } else if (ret < 0 && !timeout) {/* if timeout, goto pos_unsync */
+ awss_debug("drop: %3x < %3x\r\n", sn, zc_prev_sn);/* TODO: better not drop */
+ goto update_sn;/* FIXME: update sn??? */
+ }
+
+ /* assert(sn > zc_prev_sn && !timeout); */
+
+ if (len <= zc_frame_offset) { /* length invalid */
+ goto drop;
+ }
+
+ len -= zc_frame_offset;
+
+ if (is_data_frame(len)) {
+ pkg_type = PKG_DATA_FRAME;
+ index = get_data_index(len);
+ pos = zc_group_pos + index;
+
+ if (index > GROUP_NUMBER || pos >= MAX_PKG_NUMS) {
+ goto drop;
+ }
+ /*
+ * pos_unsync: 进入条件,任一条
+ * case1: index rollback
+ * case2: index equal but len not equal
+ * case3: data frame & timeout
+ * 退出条件:
+ * case1: 进入条件同时也是退出条件
+ * case2: 收到同步帧
+ */
+ if (index < zc_last_index ||
+ (index == zc_last_index && len != zc_last_len) || timeout) {
+ if (zc_pos_unsync) {/* already in pos_unsync state */
+ awss_trace("\texit try_to_sync_pos: re-enter!\r\n");
+ try_to_sync_pos(tods, zc_prev_sn, sn, zc_group_pos, -1);
+ }
+ zc_pos_unsync = 1;/* also a new start */
+ if (index < zc_last_index) {
+ awss_trace("\tenter try_to_sync_pos: rollback \r\n");
+ } else if (timeout) {
+ awss_trace("\tenter try_to_sync_pos: timeout \r\n");
+ } else {
+ awss_trace("\tenter try_to_sync_pos: != \r\n");
+ }
+ }
+pos_unsync:
+ if (zc_pos_unsync) {/* tmp save */
+ package_save((uint8_t *)tmp(index), src, dst, tods, len);
+ if (zc_pos_unsync == 1) {
+ tmp_score(index) = 1;
+ } else {
+ tmp_score(index) = (sn - zc_prev_sn); /* TODO: index? last_tmp_score */
+ }
+ zc_pos_unsync ++; /* unsync pkg counter */
+ awss_trace("\tX+%d [%d] %-3x %c %-3x\r\n", index, tmp_score(index), sn, flag_tods(tods), len);
+ goto update_sn;/* FIXME: update prev_sn or not? */
+ }
+
+ /* assert(sn > zc_prev_sn && pos > zc_cur_pos) */
+ score = get_data_score(zc_group_sn, sn, zc_prev_sn, pos, zc_cur_pos, tods);
+ if (score == score_min) {/* better not drop any pkg here */
+ awss_trace("\t drop: group_sn:%x, sn:%x-%x=%x, pos:%d-%d, len:%x\r\n",
+ zc_group_sn, sn, zc_prev_sn, sn_minus(sn, zc_group_sn), pos, zc_cur_pos, len);
+ goto update_sn;
+ } else {
+ if (zc_score_uplimit > score) {
+ zc_score_uplimit = score; /* inherit last limit */
+ }
+
+ zc_group_sn = sn;/* TODO */
+ awss_trace("%d+%d [%d] %-3x %c %-3x\r\n", zc_group_pos, index, score, sn, flag_tods(tods), len);
+ }
+ } else {
+ if (is_start_frame(len) || is_group_frame(len)) {
+ uint8_t group = get_group_index(len);
+
+ if (zc_pos_unsync) {
+ awss_trace("\texit try_to_sync_pos: group frame\r\n");
+ try_to_sync_pos(tods, zc_prev_sn, sn, zc_group_pos, group);
+ }
+
+ zc_cur_pos = group;
+ zc_group_pos = group;
+ zc_group_sn = sn;
+ zc_score_uplimit = score_max;
+
+ awss_trace("%d+%d [%d] %-3x %c %-3x\r\n", group, 0, zc_score_uplimit, sn, flag_tods(tods), len);
+
+ /* ignore PKG_GROUP_FRAME here */
+ pkg_type = PKG_START_FRAME;
+
+ /*
+ * keep calling zconfig_set_state(), see Note about
+ * zconfig_callback_channel_locked()
+ */
+ zconfig_set_state(STATE_CHN_LOCKED_BY_BR, tods, channel);
+
+ /* zc_replace may happen in try_to_sync_pos(), so goto is_recv_completed */
+ goto is_recv_completed;
+ } else {
+ awss_trace("\t invalid len = %d\r\n", len + zc_frame_offset);
+ goto drop;
+ }
+ }
+
+ /* start from pkg(1), leave pkg(0) for start frame */
+ if (pos >= MAX_PKG_NUMS || pos <= 0) {
+ awss_warn("msg index(%d) out of range!\r\n", pos);
+ goto drop;
+ }
+
+ zc_cur_pos = pos;
+
+ /*
+ score now > last:
+ 1) data equal: pkg_score = now
+ 2) not equal: pkg_score = now, data replace
+ score now == last:
+ 1) data equal: pkg_score++ and ???
+ 2) not equal: pkg_score cut down & give warning & try_to_replace
+ score now < last:
+ 1) data equal: score_uplimit up???
+ 2) not equal: goto pos_unsync
+ */
+ for (tods = 0; tods < 2; tods ++) {
+ equal = !package_cmp((uint8_t *)pkg(pos), src, dst, tods, len);
+
+ if (score > pkg_score(pos)) {
+ pkg_score(pos) = score; /* update score first */
+ if (equal) {
+ continue;
+ }
+ /* not equal */
+ zc_replace = 1;
+ package_save((uint8_t *)pkg(pos), src, dst, tods, len);
+ } else if (score == pkg_score(pos)) {/* range check ? */
+ int replace;
+ if (equal) {
+ pkg_score(pos) ++;
+ continue;
+ }
+ /* not equal */
+ replace = try_to_replace_same_pos(tods, pos, len);
+ if (replace) {
+ awss_trace("\t replace @ %d, len=%x\r\n", pos, len);
+ continue;
+ }
+ pkg_score(pos) /= 2;
+ if (score >= score_mid) /* better not happen */
+ awss_warn("xxxxxxxx warn: pos=%d, score=[%d], %x != %x\r\n",
+ pos, score, pkg_len(pos), len);
+
+ } else if (tods == res->tods) {/* pkg_score(pos) > score */
+ if (!equal) {/* data not equal */
+ if (zc_pos_unsync) {
+ continue;
+ }
+ zc_pos_unsync = 1;
+ awss_trace("\tenter try_to_sync_pos: data mismatch\r\n");
+ tods = res->tods;
+ goto pos_unsync;
+ } else if (zc_score_uplimit >= score_mid && pkg_score(pos) - score < 10) { /* data equal */
+ uint8_t uplimit = (zc_score_uplimit + pkg_score(pos)) / 2;
+ if (zc_score_uplimit != uplimit) {
+ awss_trace("\t\t\t uplimit [%d] -> [%d]\r\n", zc_score_uplimit, uplimit);
+ }
+ zc_score_uplimit = uplimit;
+ }
+ }
+ }
+ tods = res->tods;
+
+is_recv_completed:
+ zc_max_pos = (zc_max_pos < zc_cur_pos) ? zc_cur_pos : zc_max_pos;
+ if (zc_replace && zconfig_recv_completed(tods)) {
+ zc_replace = 0;
+ memcpy(zc_bssid, res->bssid, ETH_ALEN);
+ if (!zconfig_get_ssid_passwd(tods)) {
+ /* we got it! */
+ AWSS_UPDATE_STATIS(AWSS_STATIS_SM_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+ statis = 0;
+ zconfig_set_state(STATE_RCV_DONE, tods, channel);
+ return PKG_END;
+ }
+ }
+ }
+
+update_sn:
+ zc_prev_sn = sn;
+
+ zc_timestamp = timestamp;
+ zc_last_index = index;
+ zc_last_len = len;
+
+ return pkg_type;
+
+drop:
+ return PKG_INVALID;
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/smartconfig/smartconfig_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/smartconfig/smartconfig_wrapper.h
new file mode 100644
index 00000000..8c994140
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/smartconfig/smartconfig_wrapper.h
@@ -0,0 +1,57 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+/*************************************** common hals ***************************************/
+int HAL_Timer_Stop(void *timer);
+int HAL_Timer_Delete(void *timer);
+void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
+int HAL_Timer_Start(void *timer, int ms);
+void HAL_SleepMs(uint32_t ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+uint64_t HAL_UptimeMs(void);
+void HAL_Free(void *ptr);
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+
+/*************************************** wifi provision frameworks hals ***************************************/
+/* frameworks/awss.c*/
+int HAL_Awss_Get_Timeout_Interval_Ms(void);
+int HAL_Sys_Net_Is_Ready();
+int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
+/* awss_crypt.c */
+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]);
+/* zconfig_vendor_common.c */
+void HAL_Awss_Close_Monitor(void);
+void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
+void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
+int HAL_Awss_Get_Channelscan_Interval_Ms(void);
+DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init(
+ _IN_ const uint8_t *key,
+ _IN_ const uint8_t *iv,
+ _IN_ AES_DIR_t dir);
+DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
+DLL_HAL_API int HAL_Aes128_Cbc_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t blockNum,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cfb_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t length,
+ _OU_ void *dst);
+char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
+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);
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/wifi_provision_api.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/wifi_provision_api.h
new file mode 100644
index 00000000..d6038c65
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/wifi_provision_api.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_H__
+#define __AWSS_H__
+
+#include
+#include "infra_defs.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+#ifndef _IN_
+ #define _IN_
+#endif
+
+DLL_IOT_API int awss_start(void);
+
+/**
+ * @brief stop wifi setup service
+ *
+ * @retval -1 : failure
+ * @retval 0 : sucess
+ * @note
+ * if awss_stop is called before exit of awss_start, awss and notify will stop.
+ */
+DLL_IOT_API int awss_stop(void);
+
+/**
+ * @brief make sure user touches device belong to themselves
+ *
+ * @retval -1 : failure
+ * @retval 0 : sucess
+ * @note: AWSS doesn't parse awss packet until user touches deivce use this api.
+ */
+DLL_IOT_API int awss_config_press(void);
+
+/**
+ * @brief get the awss config press status in realtime.
+ *
+ * @retval 1 : user has touched device
+ * @retval 0 : user don't touch device
+ */
+DLL_IOT_API uint8_t awss_get_config_press(void);
+DLL_IOT_API void awss_set_config_press(uint8_t press);
+
+/**
+ * @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);
+
+/**
+ * @brief start awss dev softap mode.
+ *
+ * @retval -1 : failure
+ * @retval 0 : sucess
+ * @note
+ * Start softap mode to get wifi ssid and password.
+ */
+DLL_IOT_API int awss_dev_ap_start(void);
+
+/**
+ * @brief stop awss dev softap mode.
+ *
+ * @retval -1 : failure
+ * @retval 0 : sucess
+ * @note
+ * Stop softap mode.
+ */
+DLL_IOT_API int awss_dev_ap_stop(void);
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/wifi_provision_internal.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/wifi_provision_internal.h
new file mode 100644
index 00000000..c5163713
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/wifi_provision_internal.h
@@ -0,0 +1,84 @@
+#include "infra_config.h"
+#include
+#include
+#include "aws_lib.h"
+#include "awss_aplist.h"
+#include "zconfig_lib.h"
+#include "zconfig_utils.h"
+#include "zconfig_protocol.h"
+#include "zconfig_ieee80211.h"
+#include "awss_event.h"
+#include "awss_timer.h"
+#include "awss_main.h"
+#include "iot_import_awss.h"
+#include "os.h"
+#include "infra_compat.h"
+#include "awss_smartconfig.h"
+#include "infra_sha1.h"
+#include "passwd.h"
+#include "awss_utils.h"
+#include "awss_statis.h"
+#include "awss_packet.h"
+#include "awss_notify.h"
+#include "awss_cmp.h"
+#include "wifi_provision_api.h"
+#include "awss_cmp.h"
+#include "awss_crypt.h"
+#include "sha256.h"
+#include
+#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 "awss_aplist.h"
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+#include "awss_wps.h"
+#endif
+
+#ifdef AWSS_SUPPORT_HT40
+#include "awss_ht40.h"
+#endif
+
+#if defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_ADHA)
+#include "awss_wifimgr.h"
+#endif
+
+#ifndef AWSS_DISABLE_ENROLLEE
+ #include "awss_enrollee.h"
+#endif
+
+#if defined(AWSS_SUPPORT_AHA)
+ #include "awss_aha.h"
+#endif
+#if defined(AWSS_SUPPORT_ADHA)
+ #include "awss_adha.h"
+#endif
+
+#if defined(WIFI_PROVISION_ENABLED) || defined(DEV_BIND_ENABLED)
+ #include "coap_api.h"
+ #include "iotx_coap.h"
+#endif
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
+#include "p2p_wrapper.h"
+#endif
+
+#ifdef AWSS_SUPPORT_SMARTCONFIG
+#include "smartconfig_wrapper.h"
+#endif
+
+#ifdef AWSS_SUPPORT_ZEROCONFIG
+#include "zeroconfig_wrapper.h"
+#endif
+
+#ifdef AWSS_SUPPORT_AHA
+#include "aha_wrapper.h"
+#endif
+
+#ifdef AWSS_SUPPORT_DEV_AP
+#include "dev_ap_wrapper.h"
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_enrollee.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_enrollee.c
new file mode 100644
index 00000000..2cbb0e2d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_enrollee.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#ifndef AWSS_DISABLE_ENROLLEE
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+const uint8_t probe_req_frame[ZC_PROBE_LEN] = {
+ 0x40, 0x00, /* mgnt type, frame control */
+ 0x00, 0x00, /* duration */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
+ 0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
+ 0xC0, 0x79, /* seq */
+ 0x00, 0x00, /* hide ssid, */
+ 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x8C, 0x92, 0x98, 0xA4, /* supported rates */
+ 0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
+ 0x3F, 0x84, 0x10, 0x9E /* FCS */
+};
+
+static uint8_t *g_dev_sign; /* pointer to dev_name_len start pos */
+static uint8_t *g_product_key; /* pointer to model_len start pos */
+static uint8_t *enrollee_frame;
+static uint16_t enrollee_frame_len;
+
+static int decrypt_ssid_passwd(uint8_t *ie, uint8_t ie_len,
+ uint8_t out_ssid[OS_MAX_SSID_LEN],
+ uint8_t out_passwd[OS_MAX_PASSWD_LEN],
+ uint8_t out_bssid[ETH_ALEN]);
+
+void awss_init_enrollee_info(void) /* void enrollee_raw_frame_init(void) */
+{
+ char *pk = NULL, *dev_name = NULL, *text = NULL;
+ uint8_t sign[ENROLLEE_SIGN_SIZE + 1] = {0};
+ char key[OS_DEVICE_SECRET_LEN + 1] = {0};
+ int dev_name_len, pk_len;
+ int len, ie_len;
+
+ if (enrollee_frame_len)
+ return;
+
+ dev_name = os_zalloc(OS_DEVICE_NAME_LEN + 1);
+ if (NULL == dev_name) {
+ return;
+ }
+ pk = os_zalloc(OS_PRODUCT_KEY_LEN + 1);
+ if (NULL == pk) {
+ HAL_Free(dev_name);
+ return;
+ }
+
+ HAL_GetProductKey(pk);
+ pk_len = strlen(pk);
+
+ HAL_GetDeviceName(dev_name);
+ dev_name_len = strlen(dev_name);
+
+ len = RANDOM_MAX_LEN + dev_name_len + pk_len;
+ text = os_zalloc(len + 1); /* +1 for string print */
+
+ awss_build_sign_src(text, &len);
+
+ if (awss_get_encrypt_type() == 3) { /* aes-key per product */
+ HAL_GetProductSecret(key);
+ } else { /* aes-key per device */
+ HAL_GetDeviceSecret(key);
+ }
+ produce_signature(sign, (uint8_t *)text, len, key);
+
+ HAL_Free(text);
+
+ ie_len = pk_len + dev_name_len + ENROLLEE_IE_FIX_LEN;
+ enrollee_frame_len = sizeof(probe_req_frame) + ie_len;
+
+ enrollee_frame = os_zalloc(enrollee_frame_len);
+
+ /* construct the enrollee frame right now */
+ len = sizeof(probe_req_frame) - FCS_SIZE;
+ memcpy(enrollee_frame, probe_req_frame, len);
+
+ enrollee_frame[len ++] = 221; /* vendor ie */
+ enrollee_frame[len ++] = ie_len - 2; /* exclude 221 & len */
+ enrollee_frame[len ++] = 0xD8;
+ enrollee_frame[len ++] = 0x96;
+ enrollee_frame[len ++] = 0xE0;
+ enrollee_frame[len ++] = 0xAA;/* OUI type */
+ enrollee_frame[len ++] = DEVICE_TYPE_VERSION;/* version & dev type */
+
+ enrollee_frame[len ++] = dev_name_len;/* dev name len*/
+ memcpy(&enrollee_frame[len], dev_name, dev_name_len);
+ len += dev_name_len;
+
+ enrollee_frame[len ++] = ENROLLEE_FRAME_TYPE;/* frame type */
+
+ g_product_key = &enrollee_frame[len]; /* pointer to pk len, see decrypt func */
+ enrollee_frame[len ++] = pk_len;
+ memcpy(&enrollee_frame[len], pk, pk_len);
+ len += pk_len;
+
+ enrollee_frame[len ++] = RANDOM_MAX_LEN;
+ memcpy(&enrollee_frame[len], aes_random, RANDOM_MAX_LEN);
+ len += RANDOM_MAX_LEN;
+
+ enrollee_frame[len ++] = awss_get_encrypt_type(); /*encrypt type */
+ enrollee_frame[len ++] = 0; /* signature method, 0: hmacsha1, 1: hmacsha256 */
+ enrollee_frame[len ++] = ENROLLEE_SIGN_SIZE; /* signature length */
+ g_dev_sign = &enrollee_frame[len];
+ memcpy(&enrollee_frame[len], sign, ENROLLEE_SIGN_SIZE);
+ len += ENROLLEE_SIGN_SIZE;
+
+ memcpy(&enrollee_frame[len],
+ &probe_req_frame[sizeof(probe_req_frame) - FCS_SIZE], FCS_SIZE);
+
+ /* update probe request frame src mac */
+ os_wifi_get_mac(enrollee_frame + SA_POS);
+
+ HAL_Free(pk);
+ HAL_Free(dev_name);
+}
+
+void awss_destroy_enrollee_info(void)
+{
+ if (enrollee_frame_len) {
+ if (NULL != enrollee_frame) {
+ HAL_Free(enrollee_frame);
+ }
+ enrollee_frame_len = 0;
+ enrollee_frame = NULL;
+ g_dev_sign = NULL;
+ g_product_key = NULL;
+ }
+}
+
+void awss_broadcast_enrollee_info(void)
+{
+ if (enrollee_frame_len == 0 || enrollee_frame == NULL)
+ return;
+
+ HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, enrollee_frame,
+ enrollee_frame_len);
+}
+
+/* return 0 for success, -1 dev_name not match, otherwise return -2 */
+static int decrypt_ssid_passwd(
+ uint8_t *ie, uint8_t ie_len,
+ uint8_t out_ssid[OS_MAX_SSID_LEN],
+ uint8_t out_passwd[OS_MAX_PASSWD_LEN],
+ uint8_t out_bssid[ETH_ALEN])
+{
+ uint8_t tmp_ssid[OS_MAX_SSID_LEN + 1] = {0}, tmp_passwd[OS_MAX_PASSWD_LEN + 1] = {0};
+ uint8_t *p_dev_name_sign = NULL, *p_ssid = NULL, *p_passwd = NULL, *p_bssid = NULL;
+
+ /* ignore ie hdr: 221, len, oui[3], type(0xAB) */
+#define REGISTRAR_IE_HDR (6)
+ ie += REGISTRAR_IE_HDR;
+ if (ie[0] != DEVICE_TYPE_VERSION) {
+ awss_debug("registrar(devtype/ver=%d not supported!", ie[0]);
+ return -1;
+ }
+
+ ie ++; /* skip version */
+ p_dev_name_sign = ie;
+
+ if (!g_dev_sign || memcmp(g_dev_sign, p_dev_name_sign + 1, p_dev_name_sign[0])) {
+ p_dev_name_sign[p_dev_name_sign[0]] = '\0';
+ awss_debug("dev_name not match, expect:");
+ if (g_dev_sign) dump_hex(g_dev_sign, p_dev_name_sign[0], 16);
+ awss_debug("\r\nbut recv:");
+ dump_hex(p_dev_name_sign + 1, p_dev_name_sign[0], 16);
+ return -2;
+ }
+ ie += ie[0] + 1; /* eating device name sign length & device name sign[n] */
+
+ if (ie[0] != REGISTRAR_FRAME_TYPE) {
+ awss_debug("registrar(frametype=%d not supported!", ie[0]);
+ return -1;
+ }
+
+ ie ++; /* eating frame type */
+ p_ssid = ie;
+ if (ie[0] >= OS_MAX_SSID_LEN) {
+ awss_debug("registrar(ssidlen=%d invalid!", ie[0]);
+ return -1;
+ }
+ memcpy(tmp_ssid, &p_ssid[1], p_ssid[0]);
+ awss_debug("Registrar ssid:%s", tmp_ssid);
+
+ ie += ie[0] + 1; /* eating ssid_len & ssid[n] */
+
+ p_passwd = ie;
+ if (p_passwd[0] >= OS_MAX_PASSWD_LEN) {
+ awss_debug("registrar(passwdlen=%d invalid!", p_passwd[0]);
+ return -1;
+ }
+
+ ie += ie[0] + 1; /* eating passwd_len & passwd */
+
+ p_bssid = ie;
+ ie += ETH_ALEN; /* eating bssid len */
+
+ AWSS_UPDATE_STATIS(AWSS_STATIS_ZCONFIG_IDX, AWSS_STATIS_TYPE_TIME_START);
+
+ aes_decrypt_string((char *)p_passwd + 1, (char *)tmp_passwd, p_passwd[0],
+ 1, awss_get_encrypt_type(), 0, (const char *)aes_random); /* aes128 cfb */
+ if (is_utf8((const char *)tmp_passwd, p_passwd[0]) != 1) {
+ awss_debug("registrar(passwd invalid!");
+ AWSS_UPDATE_STATIS(AWSS_STATIS_ZCONFIG_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
+ return -1;
+ }
+ awss_debug("ssid:%s\r\n", tmp_ssid);
+
+ strncpy((char *)out_passwd, (const char *)tmp_passwd, OS_MAX_PASSWD_LEN - 1);
+ strncpy((char *)out_ssid, (const char *)tmp_ssid, OS_MAX_SSID_LEN - 1);
+ memcpy((char *)out_bssid, (char *)p_bssid, ETH_ALEN);
+
+ return 0;/* success */
+}
+
+int awss_ieee80211_zconfig_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
+{
+ const uint8_t *registrar_ie = NULL;
+ struct ieee80211_hdr *hdr;
+ uint16_t ieoffset;
+ int fc;
+
+ /*
+ * when device try to connect current router (include adha and aha)
+ * skip the new aha and process the new aha in the next scope.
+ */
+ if (mgmt_header == NULL || zconfig_finished)
+ return ALINK_INVALID;
+ /*
+ * we don't process zconfig used by enrollee until user press configure button
+ */
+ if (awss_get_config_press() == 0)
+ return ALINK_INVALID;
+
+ hdr = (struct ieee80211_hdr *)mgmt_header;
+ fc = hdr->frame_control;
+
+ if (!ieee80211_is_probe_req(fc) && !ieee80211_is_probe_resp(fc))
+ return ALINK_INVALID;
+
+ ieoffset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ if (ieoffset > len)
+ return ALINK_INVALID;
+
+ registrar_ie = (const uint8_t *)cfg80211_find_vendor_ie(WLAN_OUI_ALIBABA,
+ WLAN_OUI_TYPE_REGISTRAR, mgmt_header + ieoffset, len - ieoffset);
+ if (registrar_ie == NULL)
+ return ALINK_INVALID;
+
+ res->u.ie.alink_ie_len = len - (registrar_ie - mgmt_header);
+ res->u.ie.alink_ie = (uint8_t *)registrar_ie;
+
+ return ALINK_ZERO_CONFIG;
+}
+
+int awss_recv_callback_zconfig(struct parser_res *res)
+{
+ uint8_t tods = res->tods;
+ uint8_t channel = res->channel;
+
+ uint8_t *ie = res->u.ie.alink_ie;
+ uint8_t ie_len = ie[1];
+ int ret;
+
+ if (res->u.ie.alink_ie_len < ie_len)
+ return PKG_INVALID;
+
+ ret = decrypt_ssid_passwd(ie, ie_len, zc_ssid, zc_passwd, zc_bssid);
+ if (ret)
+ return PKG_INVALID;
+
+ zconfig_set_state(STATE_RCV_DONE, tods, channel);
+
+ AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_SUC);
+
+ return PKG_END;
+}
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_enrollee.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_enrollee.h
new file mode 100644
index 00000000..884da241
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_enrollee.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __AWSS_ENROLLEE_H__
+#define __AWSS_ENROLLEE_H__
+
+#include
+#include "infra_sha1.h"
+#include "infra_sha256.h"
+#include "passwd.h"
+#include "os.h"
+#include "zconfig_ieee80211.h"
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C"
+{
+#endif
+
+/* enrollee/registrar doc see following
+ * http://docs.alibaba-inc.com/pages/viewpage.action?pageId=450855381
+ */
+/* ie oui def. */
+#define WLAN_OUI_ALIBABA (0xD896E0)
+#define WLAN_OUI_TYPE_ENROLLEE (0xAA)
+#define WLAN_OUI_TYPE_REGISTRAR (0xAB)
+
+#define DEVICE_TYPE_VERSION (1)
+#define ENROLLEE_FRAME_TYPE (0)
+#define REGISTRAR_FRAME_TYPE (1)
+#define REGISTRAR_IDLE_DUTY (1)
+
+struct ieee80211_enrollee_alibaba_ie {
+ uint8_t element_id; /* 221 */
+ uint8_t len; /* len of this struct, exclude element id & len field */
+ uint8_t oui[3]; /* D896E0 */
+ uint8_t oui_type; /* 0xAA, device request */
+
+ uint8_t version:4; /* bit7 - bit4 */
+ uint8_t dev_type:4; /* bit3 - bit0; alink=0, alink_cloud=1, yoc=8 */
+ uint8_t dn_len; /* device name length*/
+#ifdef __GNUC__
+ uint8_t dev_name[0]; /* device name, unique name for device */
+#endif
+ uint8_t frame_type; /* frame_type = 0 */
+
+ uint8_t pk_len; /* product key length */
+#ifdef __GNUC__
+ uint8_t pk[0]; /* product key */
+#endif
+ uint8_t rand_len; /* random length */
+#ifdef __GNUC__
+ uint8_t random[0]; /* random salt */
+#endif
+ uint8_t security; /* securation type, per product(3) or device(4) or manufacture(5) */
+ uint8_t sign_method; /* 0: hmacsha1, 1:hmacsha256 */
+ uint8_t sign_len; /* signature length */
+#ifdef __GNUC__
+ uint8_t sign[0]; /* sign = hmacsha1(secret, random+dev_name+product_key) */
+#endif
+};
+
+/* len = 17 + sign[n] + ssid[n] + passwd[n] */
+struct ieee80211_registrar_alibaba_ie {
+ uint8_t element_id; /* 221 */
+ uint8_t len; /* len of this struct, exclude element id & len field */
+ uint8_t oui[3]; /* D896E0 */
+ uint8_t oui_type; /* 0xAB, device response */
+
+ uint8_t version:4; /* bit7 - bit4 */
+ uint8_t dev_type:4; /* bit3 - bit0; alink=0, alink_cloud=1, yoc=8 */
+ uint8_t sign_len; /* signature length */
+#ifdef __GNUC__
+ uint8_t sign[0]; /* sign = hmacsha1(secret, random+dev_name+product_key)*/
+#endif
+ uint8_t frame_type; /* frame_type = 0 */
+
+ uint8_t ssid_len; /* AP's SSID length */
+#ifdef __GNUC__
+ uint8_t ssid[0]; /* SSID of AP */
+#endif
+ uint8_t passwd_len; /* AP's PASSWORD length */
+#ifdef __GNUC__
+ uint8_t passwd[0]; /* PASSWORD of AP */
+#endif
+ uint8_t bssid[6]; /* BSSID of AP */
+};
+
+#define MAX_DEV_NAME_LEN (64)
+#define MAX_PK_LEN (20)
+#define MAX_KEY_LEN (32)
+#define MAX_TOKEN_LEN (32)
+#define ZC_PROBE_LEN (46)
+#define ENROLLEE_SIGN_SIZE (SHA1_DIGEST_SIZE)
+#define ENROLLEE_IE_FIX_LEN (sizeof(struct ieee80211_enrollee_alibaba_ie) + RANDOM_MAX_LEN + ENROLLEE_SIGN_SIZE)
+#define REGISTRAR_IE_FIX_LEN (sizeof(struct ieee80211_registrar_alibaba_ie))
+#define ENROLLEE_INFO_HDR_SIZE (ENROLLEE_IE_FIX_LEN - 6 + MAX_DEV_NAME_LEN + 1 + MAX_PK_LEN + 1)
+
+#ifndef AWSS_DISABLE_REGISTRAR
+struct enrollee_info {
+ uint8_t dev_type_ver;
+ uint8_t dev_name_len;
+ uint8_t dev_name[MAX_DEV_NAME_LEN + 1];
+ uint8_t frame_type;
+
+ uint8_t pk_len;
+ uint8_t pk[MAX_PK_LEN + 1];
+ uint8_t rand_len;
+ uint8_t random[RANDOM_MAX_LEN];
+ uint8_t security; /* encryption per product(3) or device(4) or manufacture(5) */
+ uint8_t sign_method; /* 0:hmacsha1, 1:hmacsha256 */
+ uint8_t sign_len;
+ uint8_t sign[ENROLLEE_SIGN_SIZE];
+
+ signed char rssi;
+
+ uint8_t key[MAX_KEY_LEN + 1]; /* aes key */
+
+ uint8_t state; /* free or not */
+ uint8_t checkin_priority; /* smaller means high pri */
+ uint32_t checkin_timestamp;
+ uint32_t report_timestamp;
+ uint32_t interval; /* report timeout */
+ uint32_t checkin_timeout;
+};
+#endif
+/* registrar configuration */
+#define MAX_ENROLLEE_NUM (5) /* Note: max enrollee num supported */
+
+/*
+ * ENR_FREE --producer--> ENR_IN_QUEUE
+ * ENR_IN_QUEUE --cloud-----> ENR_CHECKIN_ENABLE
+ * ENR_CHECKIN_ENABLE --consumer--> ENR_CHECKIN_ONGOING --> ENR_CHECKIN_END/ENR_FREE
+ * *any state* --consumer--> ENR_FREE
+ */
+enum enrollee_state {
+ ENR_FREE = 0,
+ ENR_IN_QUEUE,
+ ENR_FOUND,
+ ENR_CHECKIN_ENABLE,
+ ENR_CHECKIN_CIPHER,
+ ENR_CHECKIN_ONGOING,
+ ENR_CHECKIN_END,
+ /* ENR_OUTOFDATE = 0 */
+};
+
+#define AES_KEY_LEN (16)
+/* return 0 for success, -1 dev_name not match, otherwise return -2 */
+extern const uint8_t probe_req_frame[ZC_PROBE_LEN];
+#define SA_POS (10) /* source mac pos */
+#define FCS_SIZE (4)
+
+/* enrollee API */
+#ifdef AWSS_DISABLE_ENROLLEE
+#if 0
+static inline void awss_init_enrollee_info(void) { }
+static inline void awss_broadcast_enrollee_info(void) { }
+static inline void awss_destroy_enrollee_info(void) { }
+#endif
+#else
+void awss_init_enrollee_info(void);
+void awss_broadcast_enrollee_info(void);
+void awss_destroy_enrollee_info(void);
+int awss_recv_callback_zconfig(struct parser_res *res);
+int awss_ieee80211_zconfig_process(uint8_t *mgmt_header, int len, int link_type,
+ struct parser_res *res, signed char rssi);
+#endif
+
+/* registrar API */
+#ifdef AWSS_DISABLE_REGISTRAR
+#if 0
+static inline void awss_registrar_deinit(void) { }
+static inline void awss_registrar_init(void) { }
+#endif
+#else
+void awss_registrar_init(void);
+void awss_registrar_deinit(void);
+#endif
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_registrar.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_registrar.c
new file mode 100644
index 00000000..7e11dc91
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/awss_registrar.c
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+#include "wifi_provision_internal.h"
+
+#ifndef AWSS_DISABLE_REGISTRAR
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#define AWSS_JSON_DEV_NAME "deviceName"
+#define AWSS_JSON_PK "productKey"
+#define AWSS_JSON_DEV_LIST "data"
+#define AWSS_JSON_PERIOD "timeout"
+#define AWSS_JSON_CIPHER "secret"
+#define AWSS_REPORT_PKT_LEN (512)
+#define AWSS_REPORT_PARAM_FMT "{\"awssVer\":%s,\"type\":0,\"ssid\":\"%s\",\"bssid\":\"%s\",\"rssi\":%d,\"payload\":[\"%s\"]}"
+
+static void awss_wifi_mgnt_frame_callback(uint8_t *buffer, int length, signed char rssi, int buffer_type);
+static void registrar_raw_frame_init(struct enrollee_info *enr);
+static void registrar_raw_frame_send(void);
+static void registrar_raw_frame_destroy(void);
+static void enrollee_report(void);
+static int enrollee_checkin(void);
+static int enrollee_enable_somebody_checkin(char *key, char *dev_name, int timeout);
+static int awss_enrollee_get_dev_info(char *payload, int payload_len, char *product_key,
+ char *dev_name, char *cipher, int *timeout);
+
+/* registrar send pkt interval in ms */
+#define REGISTRAR_TIMEOUT (60)
+#define REGISTRAR_WORK_TIME (16 * 400)
+
+static struct enrollee_info enrollee_info[MAX_ENROLLEE_NUM];
+static char registrar_sched_cnt = 0;
+static char registrar_inited = 0;
+static char registrar_id = 0;
+
+static void *checkin_timer = NULL;
+static void *enrollee_report_timer = NULL;
+static void *registrar_sched_timer = NULL;
+
+#define ALIBABA_OUI {0xD8, 0x96, 0xE0}
+#ifdef REGISTRAR_IDLE_DUTY
+#if REGISTRAR_IDLE_DUTY > 0
+void registrar_schedule(void *param)
+{
+ uint8_t alibaba_oui[3] = ALIBABA_OUI;
+ char last_open = registrar_sched_cnt & 0x01;
+ unsigned int idle_duty = REGISTRAR_IDLE_DUTY;
+
+ HAL_Timer_Stop(registrar_sched_timer);
+ registrar_sched_cnt ++;
+
+ if (last_open) { /* need to close */
+ HAL_Wifi_Enable_Mgmt_Frame_Filter(FRAME_BEACON_MASK | FRAME_PROBE_REQ_MASK,
+ (uint8_t *)alibaba_oui, NULL);
+ HAL_Timer_Start(registrar_sched_timer, REGISTRAR_WORK_TIME * idle_duty);
+ } else {
+ HAL_Wifi_Enable_Mgmt_Frame_Filter(FRAME_BEACON_MASK | FRAME_PROBE_REQ_MASK,
+ (uint8_t *)alibaba_oui, awss_wifi_mgnt_frame_callback);
+ HAL_Timer_Start(registrar_sched_timer, REGISTRAR_WORK_TIME);
+ }
+}
+#endif
+#endif
+
+void awss_registrar_init(void)
+{
+ uint8_t alibaba_oui[3] = ALIBABA_OUI;
+ if (registrar_inited) {
+ return;
+ }
+
+ memset(enrollee_info, 0, sizeof(enrollee_info));
+ registrar_inited = 1;
+
+
+ /*
+ * if idle duty is zero, don't need to care about power consumption
+ */
+#ifdef REGISTRAR_IDLE_DUTY
+#if REGISTRAR_IDLE_DUTY > 0
+ if (registrar_sched_timer == NULL) {
+ registrar_sched_timer = HAL_Timer_Create("sched", (void (*)(void *))registrar_schedule, NULL);
+ }
+ if (registrar_sched_timer) {
+ registrar_sched_cnt ++;
+ HAL_Timer_Stop(registrar_sched_timer);
+ HAL_Timer_Start(registrar_sched_timer, REGISTRAR_WORK_TIME);
+ }
+#endif
+#endif
+
+ HAL_Wifi_Enable_Mgmt_Frame_Filter(FRAME_BEACON_MASK | FRAME_PROBE_REQ_MASK,
+ (uint8_t *)alibaba_oui, awss_wifi_mgnt_frame_callback);
+}
+
+void awss_registrar_deinit(void)
+{
+ uint8_t alibaba_oui[3] = ALIBABA_OUI;
+ HAL_Wifi_Enable_Mgmt_Frame_Filter(FRAME_BEACON_MASK | FRAME_PROBE_REQ_MASK,
+ (uint8_t *)alibaba_oui, NULL);
+
+ registrar_inited = 0;
+ registrar_sched_cnt = 0;
+ awss_stop_timer(checkin_timer);
+ checkin_timer = NULL;
+ awss_stop_timer(enrollee_report_timer);
+ enrollee_report_timer = NULL;
+ awss_stop_timer(registrar_sched_timer);
+ registrar_sched_timer = NULL;
+}
+
+int online_dev_bind_monitor(void *ctx, void *resource, void *remote, void *request)
+{
+ uint8_t i;
+ char *payload = NULL;
+ int payload_len = 0, dev_info_len = 0;
+ char *key = NULL, *dev_name = NULL, *dev_info = NULL;
+
+ payload = awss_cmp_get_coap_payload(request, &payload_len);
+ if (payload == NULL || payload_len == 0) {
+ goto CONNECTAP_MONITOR_END;
+ }
+
+ dev_info = json_get_value_by_name(payload, payload_len, AWSS_JSON_PARAM, &dev_info_len, NULL);
+ if (dev_info == NULL || dev_info_len == 0) {
+ goto CONNECTAP_MONITOR_END;
+ }
+
+ dev_name = os_zalloc(MAX_DEV_NAME_LEN + 1);
+ key = os_zalloc(MAX_PK_LEN + 1);
+
+ if (!dev_name || !key) {
+ goto CONNECTAP_MONITOR_END;
+ }
+
+ if (awss_enrollee_get_dev_info(dev_info, dev_info_len, key, dev_name, NULL, NULL) < 0) {
+ goto CONNECTAP_MONITOR_END;
+ }
+
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ if (enrollee_info[i].state != ENR_CHECKIN_ONGOING) {
+ continue;
+ }
+
+ if (strlen(dev_name) == enrollee_info[i].dev_name_len &&
+ 0 == memcmp(dev_name, enrollee_info[i].dev_name, enrollee_info[i].dev_name_len) &&
+ strlen(key) == enrollee_info[i].pk_len &&
+ 0 == memcmp(key, enrollee_info[i].pk, enrollee_info[i].pk_len)) {
+ enrollee_info[i].state = ENR_FREE;
+ }
+ }
+
+CONNECTAP_MONITOR_END:
+ if (dev_name) {
+ HAL_Free(dev_name);
+ }
+ if (key) {
+ HAL_Free(key);
+ }
+ return 0;
+}
+
+void awss_enrollee_checkin(void *pcontext, void *pclient, void *msg)
+{
+#define CHECK_IN_RSP_LEN (64)
+ char *packet = NULL;
+ int len = 0, timeout = 0;
+ int packet_len = CHECK_IN_RSP_LEN, dev_info_len = 0;
+ char *key = NULL, *dev_name = NULL, *dev_info = NULL;
+ uint32_t payload_len;
+ char *payload;
+ int ret;
+ char reply[TOPIC_LEN_MAX] = {0};
+
+ ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
+
+ if (ret != 0) {
+ goto CHECKIN_FAIL;
+ }
+
+ if (payload == NULL || payload_len == 0) {
+ goto CHECKIN_FAIL;
+ }
+
+ dev_name = os_zalloc(MAX_DEV_NAME_LEN + 1);
+ packet = os_zalloc(CHECK_IN_RSP_LEN + 1);
+ key = os_zalloc(MAX_PK_LEN + 1);
+
+ if (!dev_name || !key || !packet) {
+ goto CHECKIN_FAIL;
+ }
+
+ awss_debug("checkin len:%u, payload:%s\r\n", payload_len, payload);
+
+ dev_info = json_get_value_by_name(payload, payload_len, AWSS_JSON_PARAM, &dev_info_len, NULL);
+ if (dev_info == NULL || dev_info_len == 0) {
+ goto CHECKIN_FAIL;
+ }
+
+ if (awss_enrollee_get_dev_info(dev_info, dev_info_len, key, dev_name, NULL, &timeout) < 0) {
+ goto CHECKIN_FAIL;
+ }
+
+ enrollee_enable_somebody_checkin(key, dev_name, timeout);
+
+ {
+ 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_CHECKIN, "{}", 200, packet, &packet_len);
+ }
+
+ awss_build_topic(TOPIC_ZC_CHECKIN_REPLY, reply, TOPIC_LEN_MAX);
+ awss_cmp_mqtt_send(reply, packet, packet_len, 1);
+
+ HAL_Free(dev_name);
+ HAL_Free(packet);
+ HAL_Free(key);
+ return;
+
+CHECKIN_FAIL:
+ if (dev_name) {
+ HAL_Free(dev_name);
+ }
+ if (packet) {
+ HAL_Free(packet);
+ }
+ if (key) {
+ HAL_Free(key);
+ }
+
+ awss_warn("alink checkin failed");
+ return;
+}
+
+static int enrollee_enable_somebody_cipher(char *key, char *dev_name, char *cipher)
+{
+ int i;
+
+ awss_debug("key:%s, dev_name:%s, cipher:%s\r\n", key, dev_name, cipher);
+
+ if (strlen(key) > MAX_PK_LEN ||
+ strlen(dev_name) > MAX_DEV_NAME_LEN) {
+ goto out;
+ }
+
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ awss_debug("enrollee[%d] state %d", i, enrollee_info[i].state);
+ if (enrollee_info[i].state != ENR_CHECKIN_ENABLE) {
+ continue;
+ }
+ if (strlen(dev_name) == enrollee_info[i].dev_name_len &&
+ 0 == memcmp(dev_name, enrollee_info[i].dev_name, enrollee_info[i].dev_name_len) &&
+ strlen(key) == enrollee_info[i].pk_len &&
+ 0 == memcmp(key, enrollee_info[i].pk, enrollee_info[i].pk_len)) {
+
+ uint8_t *key_byte = os_zalloc(MAX_KEY_LEN + 1);
+ if (NULL == key_byte) {
+ goto out;
+ }
+
+ utils_str_to_hex(cipher, strlen(cipher), key_byte, MAX_KEY_LEN);
+
+ memcpy((char *)&enrollee_info[i].key[0], key_byte, AES_KEY_LEN);
+
+ HAL_Free(key_byte);
+
+ awss_debug("enrollee[%d] state %d->%d", i, enrollee_info[i].state,
+ ENR_CHECKIN_CIPHER);
+ enrollee_info[i].state = ENR_CHECKIN_CIPHER;
+
+ HAL_Timer_Stop(checkin_timer);
+ HAL_Timer_Start(checkin_timer, 1);
+ return 1;/* match */
+ }
+ }
+
+out:
+ return 0;/* mismatch */
+}
+
+static int enrollee_enable_somebody_checkin(char *key, char *dev_name, int timeout)
+{
+ int i;
+
+ awss_debug("key:%s, dev_name:%s, timeout:%u\r\n", key, dev_name, timeout);
+ if (strlen(key) > MAX_PK_LEN ||
+ strlen(dev_name) > MAX_DEV_NAME_LEN) {
+ goto out;
+ }
+
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ awss_debug("len:%u---%lu, name:%s---%s\r\n",
+ enrollee_info[i].dev_name_len, strlen(dev_name),
+ enrollee_info[i].dev_name, dev_name);
+ awss_debug("enrollee[%d] state %d", i, enrollee_info[i].state);
+ if (enrollee_info[i].state != ENR_FOUND) {
+ continue;
+ }
+
+ if (strlen(dev_name) == enrollee_info[i].dev_name_len &&
+ 0 == memcmp(dev_name, enrollee_info[i].dev_name, enrollee_info[i].dev_name_len) &&
+ strlen(key) == enrollee_info[i].pk_len &&
+ 0 == memcmp(key, enrollee_info[i].pk, enrollee_info[i].pk_len)) {
+
+ enrollee_info[i].state = ENR_CHECKIN_ENABLE;
+ enrollee_info[i].checkin_priority = 1; /* TODO: not implement yet */
+ enrollee_info[i].checkin_timeout = timeout <= 0 ? REGISTRAR_TIMEOUT : timeout;
+ enrollee_info[i].checkin_timestamp = os_get_time_ms();
+
+ HAL_Timer_Stop(checkin_timer);
+ HAL_Timer_Start(checkin_timer, 1);
+ return 1;/* match */
+ }
+ }
+
+out:
+ return 0;/* mismatch */
+}
+
+static int awss_request_cipher_key(int i)
+{
+ int packet_len = AWSS_REPORT_PKT_LEN - 1;
+ char topic[TOPIC_LEN_MAX] = {0};
+ char *param = NULL;
+ char *packet = NULL;
+ if (i < 0) {
+ return -1;
+ }
+#define AWSS_DEV_CIPHER_FMT "{\"awssVer\":%s,\"productKey\":\"%s\",\"deviceName\":\"%s\",\"cipherType\":%d, \"random\":\"%s\"}"
+
+ param = os_zalloc(AWSS_REPORT_PKT_LEN);
+ packet = os_zalloc(AWSS_REPORT_PKT_LEN);
+ if (param == NULL || packet == NULL) {
+ goto REQ_CIPHER_ERR;
+ }
+
+ {
+ char id[MSG_REQ_ID_LEN] = {0};
+ char rand_str[(RANDOM_MAX_LEN << 1) + 1] = {0};
+
+ utils_hex_to_str(enrollee_info[i].random, RANDOM_MAX_LEN, rand_str, sizeof(rand_str));
+ HAL_Snprintf(id, MSG_REQ_ID_LEN - 1, "\"%u\"", registrar_id ++);
+ HAL_Snprintf(param, AWSS_REPORT_PKT_LEN - 1, AWSS_DEV_CIPHER_FMT,
+ AWSS_VER, enrollee_info[i].pk, enrollee_info[i].dev_name, enrollee_info[i].security, rand_str);
+ awss_build_packet(AWSS_CMP_PKT_TYPE_REQ, id, ILOP_VER, METHOD_EVENT_ZC_CIPHER, param, 0, packet, &packet_len);
+ HAL_Free(param);
+ }
+
+ awss_build_topic(TOPIC_ZC_CIPHER, topic, TOPIC_LEN_MAX);
+ awss_cmp_mqtt_send(topic, packet, packet_len, 1);
+
+ HAL_Free(packet);
+
+ return 0;
+
+REQ_CIPHER_ERR:
+ if (param) {
+ HAL_Free(param);
+ }
+ if (packet) {
+ HAL_Free(packet);
+ }
+
+ return -1;
+}
+
+void awss_get_cipher_reply(void *pcontext, void *pclient, void *msg)
+{
+ int dev_info_len = 0;
+ char *key = NULL, *dev_name = NULL, *dev_info = NULL, *cipher = NULL;
+ uint32_t payload_len;
+ char *payload;
+ int ret;
+
+ ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
+
+ if (ret != 0) {
+ goto CIPHER_ERR;
+ }
+
+ if (payload == NULL || payload_len == 0) {
+ goto CIPHER_ERR;
+ }
+
+ dev_name = os_zalloc(MAX_DEV_NAME_LEN + 1);
+ cipher = os_zalloc(RANDOM_MAX_LEN * 2 + 1);
+ key = os_zalloc(MAX_PK_LEN + 1);
+
+ if (!dev_name || !key || !cipher) {
+ goto CIPHER_ERR;
+ }
+
+ awss_debug("cipher len:%u, payload:%s\r\n", payload_len, payload);
+
+ dev_info = json_get_value_by_name(payload, payload_len, AWSS_JSON_DEV_LIST, &dev_info_len, NULL);
+ if (dev_info == NULL || dev_info_len == 0) {
+ goto CIPHER_ERR;
+ }
+
+ if (awss_enrollee_get_dev_info(dev_info, dev_info_len, key, dev_name, cipher, NULL) < 0) {
+ goto CIPHER_ERR;
+ }
+
+ enrollee_enable_somebody_cipher(key, dev_name, cipher);
+
+ HAL_Free(dev_name);
+ HAL_Free(cipher);
+ HAL_Free(key);
+
+ return;
+CIPHER_ERR:
+ if (dev_name) {
+ HAL_Free(dev_name);
+ }
+ if (cipher) {
+ HAL_Free(cipher);
+ }
+ if (key) {
+ HAL_Free(key);
+ }
+ return;
+}
+
+/* 1 -- checkin onging, 0 -- idle */
+static int enrollee_checkin(void)
+{
+ int pri = 65536;
+ uint8_t i, check = 0;
+ uint8_t checkin_new = 0xff, get_cipher = 0xff;
+
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ switch (enrollee_info[i].state) {
+ case ENR_CHECKIN_ENABLE:
+ if (pri > enrollee_info[i].checkin_priority) {
+ pri = enrollee_info[i].checkin_priority;
+ checkin_new = i;
+ check = 1;
+ }
+ break;
+ case ENR_CHECKIN_CIPHER:
+ get_cipher = i;
+ check = 1;
+ break;
+ case ENR_CHECKIN_ONGOING:
+ goto ongoing;
+ default:
+ break;
+ }
+ }
+
+ awss_debug("cn:%d, ci:%d, c:%d\r\n", checkin_new, get_cipher, check);
+ /* no device need to setup */
+ if (check == 0) {
+ return 0;
+ }
+
+ if (get_cipher != 0xff) {
+ goto checkin_ongoing;
+ }
+
+ /* request cipher */
+ awss_request_cipher_key(checkin_new);
+ return 1;
+
+ /* checkin_new: */
+checkin_ongoing:
+ awss_debug("enrollee[%d] state %d->%d", get_cipher,
+ enrollee_info[get_cipher].state, ENR_CHECKIN_ONGOING);
+ enrollee_info[get_cipher].state = ENR_CHECKIN_ONGOING;
+ enrollee_info[get_cipher].checkin_timestamp = os_get_time_ms();
+ registrar_raw_frame_init(&enrollee_info[get_cipher]);
+ i = get_cipher;
+
+ /* undergoing */
+ongoing:
+ registrar_raw_frame_send();
+ awss_debug("registrar_raw_frame_send");
+ if (time_elapsed_ms_since(enrollee_info[i].checkin_timestamp) > enrollee_info[i].checkin_timeout * 1000) {
+ memset(&enrollee_info[i], 0, sizeof(enrollee_info[0]));
+ awss_debug("enrollee[%d] state %d->%d", i,
+ enrollee_info[i].state, ENR_CHECKIN_END);
+ enrollee_info[i].state = ENR_CHECKIN_END;/* FIXME: remove this state? */
+ awss_debug("enrollee[%d] state %d->%d", i,
+ enrollee_info[i].state, ENR_FREE);
+ enrollee_info[i].state = ENR_FREE;
+ registrar_raw_frame_destroy();
+ }
+
+ HAL_Timer_Stop(checkin_timer);
+ HAL_Timer_Start(checkin_timer, HAL_Awss_Get_Channelscan_Interval_Ms() * 15 / 16);
+
+ return 1;
+}
+
+int awss_report_set_interval(char *key, char *dev_name, int interval)
+{
+ int i;
+
+ awss_debug("key:%s, dev_name:%s, interval:%u\r\n", key, dev_name, interval);
+ if (strlen(key) > MAX_PK_LEN ||
+ strlen(dev_name) > MAX_DEV_NAME_LEN) {
+ return -1;
+ }
+
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ if (enrollee_info[i].state != ENR_FOUND) {
+ continue;
+ }
+
+ if (strlen(dev_name) == enrollee_info[i].dev_name_len &&
+ 0 == memcmp(dev_name, enrollee_info[i].dev_name, enrollee_info[i].dev_name_len) &&
+ strlen(key) == enrollee_info[i].pk_len &&
+ 0 == memcmp(key, enrollee_info[i].pk, enrollee_info[i].pk_len)) {
+
+ enrollee_info[i].interval = interval <= 0 ? REGISTRAR_TIMEOUT : interval;
+ if (checkin_timer == NULL) {
+ checkin_timer = HAL_Timer_Create("checkin", (void (*)(void *))enrollee_checkin, NULL);
+ }
+ HAL_Timer_Stop(checkin_timer);
+ HAL_Timer_Start(checkin_timer, 1);
+ return 0;/* match */
+ }
+ }
+
+ return -1;
+
+}
+
+static int awss_enrollee_get_dev_info(char *payload, int payload_len,
+ char *product_key, char *dev_name,
+ char *cipher, int *timeout)
+{
+ char *elem = NULL;
+ int len = 0;
+ if (product_key == NULL || dev_name == NULL) {
+ return -1;
+ }
+
+ elem = json_get_value_by_name(payload, payload_len, AWSS_JSON_PK, &len, NULL);
+ if (len > MAX_PK_LEN || elem == NULL) {
+ return -1;
+ }
+
+ memcpy(product_key, elem, len);
+
+ len = 0;
+ elem = json_get_value_by_name(payload, payload_len, AWSS_JSON_DEV_NAME, &len, NULL);
+ if (len > MAX_DEV_NAME_LEN || elem == NULL) {
+ return -1;
+ }
+
+ memcpy(dev_name, elem, len);
+
+ len = 0;
+ elem = json_get_value_by_name(payload, payload_len, AWSS_JSON_PERIOD, &len, NULL);
+ if (elem && timeout) {
+ *timeout = atoi(elem);
+ }
+
+ len = 0;
+ elem = json_get_value_by_name(payload, payload_len, AWSS_JSON_CIPHER, &len, NULL);
+ if (elem && cipher && len <= RANDOM_MAX_LEN * 2) {
+ memcpy(cipher, elem, len);
+ }
+
+ return 0;
+}
+
+void awss_report_enrollee_reply(void *pcontext, void *pclient, void *msg)
+{
+ int interval = 0;
+ int dev_list_len = 0;
+ char *dev_list = NULL;
+ char *key = NULL, *dev_name = NULL;
+ uint32_t payload_len;
+ char *payload;
+ int ret;
+ char *str_pos, *entry;
+ int entry_len, type;
+
+ ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
+
+ if (ret != 0) {
+ goto REPORT_REPLY_FAIL;
+ }
+
+ if (payload == NULL || payload_len == 0) {
+ goto REPORT_REPLY_FAIL;
+ }
+
+ awss_debug("found reply:%s\r\n", payload);
+ dev_name = os_zalloc(MAX_DEV_NAME_LEN + 1);
+ key = os_zalloc(MAX_PK_LEN + 1);
+
+ if (!dev_name || !key) {
+ goto REPORT_REPLY_FAIL;
+ }
+
+ dev_list = json_get_value_by_name(payload, payload_len, AWSS_JSON_DEV_LIST, &dev_list_len, NULL);
+ if (dev_list == NULL) {
+ goto REPORT_REPLY_FAIL;
+ }
+
+ json_array_for_each_entry(dev_list, dev_list_len, str_pos, entry, entry_len, type) {
+ memset(dev_name, 0, MAX_DEV_NAME_LEN + 1);
+ memset(key, 0, MAX_PK_LEN + 1);
+ if (awss_enrollee_get_dev_info(entry, entry_len, key, dev_name, NULL, &interval) < 0) {
+ continue;
+ }
+
+ awss_report_set_interval(key, dev_name, interval);
+ }
+
+ HAL_Free(dev_name);
+ HAL_Free(key);
+ return;
+
+REPORT_REPLY_FAIL:
+ if (dev_name) {
+ HAL_Free(dev_name);
+ }
+ if (key) {
+ HAL_Free(key);
+ }
+
+ awss_warn("ilop report enrollee failed");
+ return;
+}
+
+int awss_report_enrollee(uint8_t *payload, int payload_len, signed char rssi)
+{
+ int i;
+ char *payload_str = NULL;
+ char *param = NULL, *packet = NULL;
+ int packet_len = AWSS_REPORT_PKT_LEN - 1;
+ char topic[TOPIC_LEN_MAX] = {0};
+
+ payload_str = os_zalloc(payload_len * 2 + 1);
+ param = os_zalloc(AWSS_REPORT_PKT_LEN);
+ packet = os_zalloc(AWSS_REPORT_PKT_LEN);
+ if (!payload_str || !param || !packet) {
+ goto REPORT_FAIL;
+ }
+
+ {
+ char id[MSG_REQ_ID_LEN] = {0};
+ uint8_t bssid[OS_ETH_ALEN] = {0};
+ char ssid[OS_MAX_SSID_LEN + 1] = {0};
+ char bssid_str[OS_ETH_ALEN * 2 + 6] = {0};
+
+ HAL_Wifi_Get_Ap_Info(ssid, NULL, bssid);
+ sprintf(bssid_str, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+
+ for (i = 0; i < payload_len; i ++) {
+ sprintf(&payload_str[i * 2], "%02X", payload[i]);
+ }
+
+ payload_str[payload_len * 2] = '\0'; /* sprintf not add '\0' in the end of string in qcom */
+
+ HAL_Snprintf(id, MSG_REQ_ID_LEN - 1, "\"%u\"", registrar_id ++);
+
+ HAL_Snprintf(param, AWSS_REPORT_PKT_LEN - 1, AWSS_REPORT_PARAM_FMT,
+ AWSS_VER, ssid, bssid_str, rssi > 0 ? rssi - 256 : rssi, payload_str);
+ HAL_Free(payload_str);
+ awss_build_packet(AWSS_CMP_PKT_TYPE_REQ, id, ILOP_VER, METHOD_EVENT_ZC_ENROLLEE, param, 0, packet, &packet_len);
+ HAL_Free(param);
+ }
+
+ awss_build_topic(TOPIC_ZC_ENROLLEE, topic, TOPIC_LEN_MAX);
+ awss_debug("topic:%s, packet:%s, method:%s\r\n", topic, packet, METHOD_EVENT_ZC_ENROLLEE);
+
+ awss_cmp_mqtt_send(topic, packet, packet_len, 1);
+
+ HAL_Free(packet);
+ return 0;
+
+REPORT_FAIL:
+ if (payload_str) {
+ HAL_Free(payload_str);
+ }
+ if (packet) {
+ HAL_Free(packet);
+ }
+ if (param) {
+ HAL_Free(param);
+ }
+
+ return -1;
+}
+
+/* consumer */
+static void enrollee_report(void)
+{
+ int i;
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ char ssid[OS_MAX_SSID_LEN + 1] = {0};
+ HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
+ if (!strcmp(ssid, DEFAULT_SSID) || !strcmp(ssid, ADHA_SSID)) {
+ return; /* ignore enrollee in 'aha' or 'adha' mode */
+ }
+#endif
+
+ /* evict timeout enrollee */
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ struct enrollee_info *enrollee = &enrollee_info[i];
+ switch (enrollee->state) {
+ case ENR_FOUND: {
+ if (time_elapsed_ms_since(enrollee->report_timestamp) > enrollee->interval * 1000) {
+ memset(enrollee, 0, sizeof(enrollee_info[0]));
+ enrollee->state = ENR_FREE;
+ }
+ break;
+ }
+ case ENR_IN_QUEUE: {
+ uint16_t idx = 0;
+ int ret = -1;
+ uint16_t payload_len = 1 + enrollee->dev_name_len + 1 + enrollee->pk_len +
+ 1 + enrollee->rand_len + 3 + enrollee->sign_len;
+ uint8_t *payload = HAL_Malloc(payload_len + 1);
+ if (payload == NULL) {
+ break;
+ }
+
+ payload[idx ++] = enrollee->dev_name_len;
+ memcpy(&payload[idx], enrollee->dev_name, enrollee->dev_name_len);
+ idx += enrollee->dev_name_len;
+
+ payload[idx ++] = enrollee->pk_len;
+ memcpy(&payload[idx], enrollee->pk, enrollee->pk_len);
+ idx += enrollee->pk_len;
+
+ payload[idx ++] = enrollee->rand_len;
+ memcpy(&payload[idx], &enrollee->random, enrollee->rand_len);
+ idx += enrollee->rand_len;
+
+ payload[idx ++] = enrollee->security;
+ payload[idx ++] = enrollee->sign_method;
+ payload[idx ++] = enrollee->sign_len;
+ memcpy(&payload[idx], &enrollee->sign, enrollee->sign_len);
+ idx += enrollee->sign_len;
+
+ ret = awss_report_enrollee(payload, idx, enrollee->rssi);
+
+ enrollee->state = ENR_FOUND;
+ enrollee->report_timestamp = os_get_time_ms();
+
+ awss_trace("enrollee report result:%s, period:%dms\n",
+ ret == 0 ? "success" : "failed",
+ enrollee->interval * 1000);
+
+ HAL_Free(payload);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+int enrollee_put(struct enrollee_info *in);
+
+int process_enrollee_ie(const uint8_t *ie, signed char rssi)
+{
+ struct enrollee_info tmp_enrollee = {0};
+ /* suppose enrollee_ie is complete */
+#define ENROLLEE_IE_HDR (6)
+ /* copy to tmp_enrollee */
+ ie += ENROLLEE_IE_HDR;
+
+ if (ie[0] != DEVICE_TYPE_VERSION) {
+ awss_warn("enrollee(devtype/ver=%d not supported!", ie[0]);
+ return -1;
+ }
+ tmp_enrollee.dev_type_ver = ie[0];
+ ie ++;/* eating dev_type_ver */
+
+ if (ie[0] > MAX_DEV_NAME_LEN) {
+ awss_warn("enrollee(dev_name_len=%d out of range!\r\n", ie[0]);
+ return -1;
+ }
+ tmp_enrollee.dev_name_len = ie[0];
+ memcpy(tmp_enrollee.dev_name, &ie[1], ie[0]);
+ ie += ie[0] + 1; /* eating dev_name[n], dev_name_len */
+
+ if (ie[0] != ENROLLEE_FRAME_TYPE) {
+ awss_warn("enrollee(frametype=%d invalid!\r\n", ie[0]);
+ return -1;
+ }
+ tmp_enrollee.frame_type = ie[0];
+ ie ++;/* eating frame type */
+
+ if (ie[0] > MAX_PK_LEN) {
+ awss_warn("enrollee(pk_len=%d invalid!\r\n", ie[0]);
+ return -1;
+ }
+ tmp_enrollee.pk_len = ie[0];
+ memcpy(tmp_enrollee.pk, &ie[1], ie[0]);
+ ie += ie[0] + 1; /* eating pk[n], pk_len */
+
+ if (ie[0] != RANDOM_MAX_LEN) {
+ awss_warn("enrollee(rand_len=%d invalid!\r\n", ie[0]);
+ return -1;
+ }
+ tmp_enrollee.rand_len = ie[0];
+ memcpy(tmp_enrollee.random, &ie[1], RANDOM_MAX_LEN);
+ ie += ie[0] + 1; /* eating random[n], rand_len */
+
+ if (ie[0] > 5 || ie[0] < 3) {
+ awss_warn("enrollee(security=%d invalid!\r\n", ie[0]);
+ return -1;
+ }
+ if (ie[1] > 1) {
+ awss_warn("enrollee(sign_method=%d invalid!\r\n", ie[1]);
+ return -1;
+ }
+ if (ie[2] != ENROLLEE_SIGN_SIZE) {
+ awss_warn("enrollee(sign_len=%d invalid!\r\n", ie[2]);
+ return -1;
+ }
+ tmp_enrollee.security = ie[0];
+ tmp_enrollee.sign_method = ie[1];
+ tmp_enrollee.sign_len = ie[2];
+
+ memcpy(tmp_enrollee.sign, &ie[3], ie[2]);
+ ie += ie[2] + 3; /* eating signature[n], security, sign_method, sign_len */
+
+ tmp_enrollee.rssi = rssi;
+
+ enrollee_put(&tmp_enrollee);
+
+ return 0;
+}
+
+/* producer */
+/*
+ * 1: already saved, update timestamp
+ * 0: new saved
+ * -1: no slot to save, drop
+ */
+int enrollee_put(struct enrollee_info *in)
+{
+ uint8_t i, empty_slot = MAX_ENROLLEE_NUM;
+ do {
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ char ssid[OS_MAX_SSID_LEN + 1] = {0};
+#endif
+ /* reduce stack used */
+ if (in == NULL || !HAL_Sys_Net_Is_Ready()) { /* not ready to work as registerar */
+ return -1;
+ }
+#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
+ HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
+ if (!strcmp(ssid, DEFAULT_SSID) || !strcmp(ssid, ADHA_SSID)) {
+ return -1; /* ignore enrollee in 'aha' or 'adha' mode */
+ }
+#endif
+ } while (0);
+
+ for (i = 0; i < MAX_ENROLLEE_NUM; i++) {
+ if (enrollee_info[i].state) {
+ if (in->dev_name_len == enrollee_info[i].dev_name_len &&
+ 0 == memcmp(in->dev_name, enrollee_info[i].dev_name, enrollee_info[i].dev_name_len) &&
+ in->pk_len == enrollee_info[i].pk_len &&
+ 0 == memcmp(in->pk, enrollee_info[i].pk, enrollee_info[i].pk_len)) {
+ if (enrollee_info[i].state == ENR_FOUND &&
+ time_elapsed_ms_since(enrollee_info[i].report_timestamp) > enrollee_info[i].interval * 1000) {
+ if (enrollee_report_timer == NULL) {
+ enrollee_report_timer = HAL_Timer_Create("enrollee", (void (*)(void *))enrollee_report, NULL);
+ }
+ HAL_Timer_Stop(enrollee_report_timer);
+ HAL_Timer_Start(enrollee_report_timer, 1);
+ }
+ if (enrollee_info[i].state != ENR_IN_QUEUE) { /* already reported */
+ return 1;
+ }
+ memcpy(&enrollee_info[i], in, ENROLLEE_INFO_HDR_SIZE);
+ enrollee_info[i].rssi = (2 * enrollee_info[i].rssi + in->rssi) / 3;
+ return 1;/* wait for report */
+ }
+ } else if (enrollee_info[i].state == ENR_FREE && empty_slot >= MAX_ENROLLEE_NUM) {
+ empty_slot = i;
+ }
+ }
+
+ if (empty_slot >= MAX_ENROLLEE_NUM) {
+ return -1; /* no slot to save */
+ }
+
+ /* new enrollee */
+ memset(&enrollee_info[empty_slot], 0, sizeof(struct enrollee_info));
+ memcpy(&enrollee_info[empty_slot], in, ENROLLEE_INFO_HDR_SIZE);
+ enrollee_info[empty_slot].rssi = in->rssi;
+ enrollee_info[empty_slot].state = ENR_IN_QUEUE;
+ enrollee_info[empty_slot].checkin_priority = 1; /* smaller means high pri */
+ enrollee_info[empty_slot].interval = REGISTRAR_TIMEOUT;
+ enrollee_info[empty_slot].checkin_timeout = REGISTRAR_TIMEOUT;
+ awss_debug("new enrollee[%d] dev_name:%s time:%x",
+ empty_slot, in->dev_name, os_get_time_ms());
+
+ if (enrollee_report_timer == NULL) {
+ enrollee_report_timer = HAL_Timer_Create("enrollee", (void (*)(void *))enrollee_report, NULL);
+ }
+ HAL_Timer_Stop(enrollee_report_timer);
+ HAL_Timer_Start(enrollee_report_timer, 1);
+
+ return 0;
+}
+
+extern const uint8_t *cfg80211_find_vendor_ie(
+ uint32_t oui, uint8_t oui_type,
+ const uint8_t *ies, int len);
+/**
+ * @brief management frame handler
+ *
+ * @param[in] buffer @n 80211 raw frame or ie(information element) buffer
+ * @param[in] len @n buffer length
+ * @param[in] buffer_type @n 0 when buffer is a 80211 frame,
+ * 1 when buffer only contain IE info
+ * @return None.
+ * @see None.
+ * @note None.
+ */
+void awss_wifi_mgnt_frame_callback(uint8_t *buffer, int length, signed char rssi, int buffer_type)
+{
+#define MGMT_BEACON (0x80)
+#define MGMT_PROBE_REQ (0x40)
+#define MGMT_PROBE_RESP (0x50)
+
+ /* fc(2) + dur(2) + da(6) + sa(6) + bssid(6) + seq(2) */
+#define MGMT_HDR_LEN (24)
+
+ int type = buffer[0], len = 0, eid;
+ const uint8_t *ie;
+
+ if (buffer_type) {
+ ie = buffer;
+ goto ie_handler;
+ }
+
+ switch (type) {
+ case MGMT_BEACON:
+ /* awss_trace("beacon"); */
+ buffer += MGMT_HDR_LEN + 12;/* hdr(24) + 12(timestamp, beacon_interval, cap) */
+ length -= MGMT_HDR_LEN + 12;
+
+ eid = buffer[0];
+ len = buffer[1];
+ if (eid != 0) {
+ /* awss_warn("error eid, should be 0!"); */
+ return;
+ }
+
+ /* skip ssid */
+ buffer += 2;
+ buffer += len;
+ length -= len;
+
+ goto find_ie;
+ break;
+ case MGMT_PROBE_REQ:
+ /* awss_trace("probe req\n"); */
+ buffer += MGMT_HDR_LEN;
+ length -= MGMT_HDR_LEN;
+
+find_ie:
+ ie = cfg80211_find_vendor_ie((uint32_t)WLAN_OUI_ALIBABA,
+ (uint8_t)WLAN_OUI_TYPE_ENROLLEE,
+ (const uint8_t *)buffer, (int)length);
+ if (ie) {
+ie_handler:
+ /* awss_trace("ie found to be processed\n"); */
+ process_enrollee_ie(ie, rssi);
+ }
+ break;
+ case MGMT_PROBE_RESP:
+ /* awss_trace("probe resp"); */
+ break;
+ default:
+ /* awss_trace("frame (%d): %02x \n", length, type); */
+ break;
+ }
+}
+
+static uint8_t *registrar_frame;
+static int registrar_frame_len;
+
+static void registrar_raw_frame_init(struct enrollee_info *enr)
+{
+ int len, ie_len;
+
+ char passwd[OS_MAX_PASSWD_LEN + 1] = {0};
+ char ssid[OS_MAX_SSID_LEN + 1] = {0};
+ uint8_t bssid[OS_ETH_ALEN] = {0};
+ int ssid_len, passwd_len;
+
+ HAL_Wifi_Get_Ap_Info(ssid, passwd, bssid);
+ ssid_len = strlen(ssid);
+ if (ssid_len > OS_MAX_SSID_LEN - 1) {
+ ssid_len = OS_MAX_SSID_LEN - 1;
+ }
+
+ passwd_len = strlen(passwd);
+ if (passwd_len > OS_MAX_PASSWD_LEN - 1) {
+ passwd_len = OS_MAX_PASSWD_LEN - 1;
+ }
+
+ ie_len = ENROLLEE_SIGN_SIZE + ssid_len + passwd_len + REGISTRAR_IE_FIX_LEN;
+ registrar_frame_len = sizeof(probe_req_frame) + ie_len;
+
+ registrar_frame = HAL_Malloc(registrar_frame_len);
+ if (!registrar_frame) {
+ awss_err("error: malloc size %d faild\r\n", registrar_frame_len);
+ return;
+ }
+
+ /* construct the registrar frame right now */
+ len = sizeof(probe_req_frame) - FCS_SIZE;
+ memcpy(registrar_frame, probe_req_frame, len);
+
+ registrar_frame[len ++] = 221; /* vendor ie */
+ registrar_frame[len ++] = ie_len - 2; /* exclude 221 & len */
+ registrar_frame[len ++] = 0xD8;
+ registrar_frame[len ++] = 0x96;
+ registrar_frame[len ++] = 0xE0;
+ registrar_frame[len ++] = 0xAB;/* OUI type */
+ registrar_frame[len ++] = DEVICE_TYPE_VERSION;/* version & dev type */
+ registrar_frame[len ++] = enr->sign_len;/* dev signature len*/
+ memcpy(®istrar_frame[len], enr->sign, enr->sign_len);
+ len += enr->sign_len;
+ registrar_frame[len ++] = REGISTRAR_FRAME_TYPE;/* frame type */
+
+ registrar_frame[len ++] = ssid_len;
+ memcpy(®istrar_frame[len], ssid, ssid_len);
+ len += ssid_len;
+
+ registrar_frame[len ++] = passwd_len;
+
+ {
+ p_aes128_t aes = HAL_Aes128_Init(&enr->key[0], enr->random, PLATFORM_AES_ENCRYPTION);
+ HAL_Aes128_Cfb_Encrypt(aes, (uint8_t *)passwd, passwd_len, (uint8_t *)®istrar_frame[len]);
+ HAL_Aes128_Destroy(aes);
+ }
+
+ len += passwd_len;
+
+ memcpy(®istrar_frame[len], bssid, ETH_ALEN);
+ len += ETH_ALEN;
+
+ memcpy(®istrar_frame[len],
+ &probe_req_frame[sizeof(probe_req_frame) - FCS_SIZE], FCS_SIZE);
+
+ /* update probe request frame src mac */
+ os_wifi_get_mac(registrar_frame + SA_POS);
+
+ {
+ /* dump registrar info */
+ awss_debug("dump registrar info:");
+ dump_hex(registrar_frame, registrar_frame_len, 16);
+ }
+}
+
+static void registrar_raw_frame_destroy(void)
+{
+ if (registrar_frame_len) {
+ HAL_Free(registrar_frame);
+ registrar_frame = NULL;
+ registrar_frame_len = 0;
+ }
+}
+
+static void registrar_raw_frame_send(void)
+{
+ /* suppose registrar_frame was ready
+ * @see enrollee_checkin()
+ */
+ int ret = HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, registrar_frame,
+ registrar_frame_len);
+ if (ret) {
+ awss_warn("send failed");
+ }
+}
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/zeroconfig_wrapper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/zeroconfig_wrapper.h
new file mode 100644
index 00000000..31d295ff
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/iotkit-embedded/wifi_provision/zero_config/zeroconfig_wrapper.h
@@ -0,0 +1,77 @@
+#include "infra_types.h"
+#include "infra_defs.h"
+#include "wrappers_defs.h"
+/*************************************** common hals ***************************************/
+int HAL_Timer_Stop(void *timer);
+int HAL_Timer_Delete(void *timer);
+void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
+int HAL_Timer_Start(void *timer, int ms);
+void HAL_SleepMs(uint32_t ms);
+void *HAL_Malloc(uint32_t size);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+uint64_t HAL_UptimeMs(void);
+void HAL_Free(void *ptr);
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+
+/*************************************** wifi provision frameworks hals ***************************************/
+/* frameworks/awss.c*/
+int HAL_Awss_Get_Timeout_Interval_Ms(void);
+int HAL_Sys_Net_Is_Ready();
+int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
+/* awss_crypt.c */
+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]);
+
+/* zconfig_vendor_common.c */
+void HAL_Awss_Close_Monitor(void);
+void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
+void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
+int HAL_Awss_Get_Channelscan_Interval_Ms(void);
+DLL_HAL_API p_HAL_Aes128_t HAL_Aes128_Init(
+ _IN_ const uint8_t *key,
+ _IN_ const uint8_t *iv,
+ _IN_ AES_DIR_t dir);
+
+DLL_HAL_API int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
+DLL_HAL_API int HAL_Aes128_Cbc_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t blockNum,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cfb_Decrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t length,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cbc_Encrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t blockNum,
+ _OU_ void *dst);
+DLL_HAL_API int HAL_Aes128_Cfb_Encrypt(
+ _IN_ p_HAL_Aes128_t aes,
+ _IN_ const void *src,
+ _IN_ size_t length,
+ _OU_ void *dst);
+char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
+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);
+
+/*************************************** zero-config special hals ***************************************/
+int HAL_Wifi_Enable_Mgmt_Frame_Filter(
+ _IN_ uint32_t filter_mask,
+ _IN_OPT_ uint8_t vendor_oui[3],
+ _IN_ awss_wifi_mgmt_frame_cb_t callback);
+int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
+ _IN_ uint8_t *buffer, _IN_ int len);
+
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/cJSON.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/cJSON.c
new file mode 100644
index 00000000..47fb5c32
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/cJSON.c
@@ -0,0 +1,2283 @@
+/*
+Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+Permission is hereby granted, 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.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#ifdef __GNUC__
+ #pragma GCC visibility push(default)
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __GNUC__
+ #pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#define true ((cJSON_bool)1)
+#define false ((cJSON_bool)0)
+
+typedef struct {
+ const unsigned char *json;
+ size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+ return (const char *)(global_error.json + global_error.position);
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 3)
+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char *) cJSON_Version(void)
+{
+ static char version[15];
+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+ return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
+{
+ if ((string1 == NULL) || (string2 == NULL)) {
+ return 1;
+ }
+
+ if (string1 == string2) {
+ return 0;
+ }
+
+ for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
+ if (*string1 == '\0') {
+ return 0;
+ }
+ }
+
+ return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks {
+ void *(*allocate)(uint32_t size);
+ void(*deallocate)(void *pointer);
+ void *(*reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+extern void *HAL_Malloc(uint32_t size);
+extern void HAL_Free(void *ptr);
+static internal_hooks global_hooks = { HAL_Malloc, HAL_Free, realloc };
+
+static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks)
+{
+ size_t length = 0;
+ unsigned char *copy = NULL;
+
+ if (string == NULL) {
+ return NULL;
+ }
+
+ length = strlen((const char *)string) + sizeof("");
+ if (!(copy = (unsigned char *)hooks->allocate(length))) {
+ return NULL;
+ }
+ memcpy(copy, string, length);
+
+ return copy;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks *const hooks)
+{
+ cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON));
+ if (node) {
+ memset(node, '\0', sizeof(cJSON));
+ }
+
+ return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+ cJSON *next = NULL;
+ while (item != NULL) {
+ next = item->next;
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
+ cJSON_Delete(item->child);
+ }
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
+ global_hooks.deallocate(item->valuestring);
+ }
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
+ global_hooks.deallocate(item->string);
+ }
+ global_hooks.deallocate(item);
+ item = next;
+ }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+ struct lconv *lconv = localeconv();
+ return (unsigned char)lconv->decimal_point[0];
+}
+
+typedef struct {
+ const unsigned char *content;
+ size_t length;
+ size_t offset;
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+ internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+#define cannot_read(buffer, size) (!can_read(buffer, size))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer)
+{
+ double number = 0;
+ unsigned char *after_end = NULL;
+ unsigned char number_c_string[64];
+ unsigned char decimal_point = get_decimal_point();
+ size_t i = 0;
+
+ if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
+ return false;
+ }
+
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
+ * of the current locale (for strtod)
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
+ switch (buffer_at_offset(input_buffer)[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case 'e':
+ case 'E':
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
+ break;
+
+ case '.':
+ number_c_string[i] = decimal_point;
+ break;
+
+ default:
+ goto loop_end;
+ }
+ }
+loop_end:
+ number_c_string[i] = '\0';
+
+ number = strtod((const char *)number_c_string, (char **)&after_end);
+ if (number_c_string == after_end) {
+ return false; /* parse_error */
+ }
+
+ item->valuedouble = number;
+
+ /* use saturation in case of overflow */
+ if (number >= INT_MAX) {
+ item->valueint = INT_MAX;
+ } else if (number <= INT_MIN) {
+ item->valueint = INT_MIN;
+ } else {
+ item->valueint = (int)number;
+ }
+
+ item->type = cJSON_Number;
+
+ input_buffer->offset += (size_t)(after_end - number_c_string);
+ return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+ if (number >= INT_MAX) {
+ object->valueint = INT_MAX;
+ } else if (number <= INT_MIN) {
+ object->valueint = INT_MIN;
+ } else {
+ object->valueint = (int)number;
+ }
+
+ return object->valuedouble = number;
+}
+
+typedef struct {
+ unsigned char *buffer;
+ size_t length;
+ size_t offset;
+ size_t depth; /* current nesting depth (for formatted printing) */
+ cJSON_bool noalloc;
+ cJSON_bool format; /* is this print a formatted print */
+ internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char *ensure(printbuffer *const p, size_t needed)
+{
+ unsigned char *newbuffer = NULL;
+ size_t newsize = 0;
+
+ if ((p == NULL) || (p->buffer == NULL)) {
+ return NULL;
+ }
+
+ if ((p->length > 0) && (p->offset >= p->length)) {
+ /* make sure that offset is valid */
+ return NULL;
+ }
+
+ if (needed > INT_MAX) {
+ /* sizes bigger than INT_MAX are currently not supported */
+ return NULL;
+ }
+
+ needed += p->offset + 1;
+ if (needed <= p->length) {
+ return p->buffer + p->offset;
+ }
+
+ if (p->noalloc) {
+ return NULL;
+ }
+
+ /* calculate new buffer size */
+ if (needed > (INT_MAX / 2)) {
+ /* overflow of int, use INT_MAX if possible */
+ if (needed <= INT_MAX) {
+ newsize = INT_MAX;
+ } else {
+ return NULL;
+ }
+ } else {
+ newsize = needed * 2;
+ }
+
+ if (p->hooks.reallocate != NULL) {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize);
+ } else {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char *)p->hooks.allocate(newsize);
+ if (!newbuffer) {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ if (newbuffer) {
+ memcpy(newbuffer, p->buffer, p->offset + 1);
+ }
+ p->hooks.deallocate(p->buffer);
+ }
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer *const buffer)
+{
+ const unsigned char *buffer_pointer = NULL;
+ if ((buffer == NULL) || (buffer->buffer == NULL)) {
+ return;
+ }
+ buffer_pointer = buffer->buffer + buffer->offset;
+
+ buffer->offset += strlen((const char *)buffer_pointer);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ double d = item->valuedouble;
+ int length = 0;
+ size_t i = 0;
+ unsigned char number_buffer[26]; /* temporary buffer to print the number into */
+ unsigned char decimal_point = get_decimal_point();
+ double test;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* This checks for NaN and Infinity */
+ if ((d * 0) != 0) {
+ length = sprintf((char *)number_buffer, "null");
+ } else {
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+ length = sprintf((char *)number_buffer, "%1.15g", d);
+
+ /* Check whether the original double can be recovered */
+ if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || ((double)test != d)) {
+ /* If not, print with 17 decimal places of precision */
+ length = sprintf((char *)number_buffer, "%1.17g", d);
+ }
+ }
+
+ /* sprintf failed or buffer overrun occured */
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
+ return false;
+ }
+
+ /* reserve appropriate space in the output */
+ output_pointer = ensure(output_buffer, (size_t)length);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ /* copy the printed number to the output and replace locale
+ * dependent decimal point with '.' */
+ for (i = 0; i < ((size_t)length); i++) {
+ if (number_buffer[i] == decimal_point) {
+ output_pointer[i] = '.';
+ continue;
+ }
+
+ output_pointer[i] = number_buffer[i];
+ }
+ output_pointer[i] = '\0';
+
+ output_buffer->offset += (size_t)length;
+
+ return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char *const input)
+{
+ unsigned int h = 0;
+ size_t i = 0;
+
+ for (i = 0; i < 4; i++) {
+ /* parse digit */
+ if ((input[i] >= '0') && (input[i] <= '9')) {
+ h += (unsigned int)input[i] - '0';
+ } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
+ h += (unsigned int)10 + input[i] - 'A';
+ } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
+ h += (unsigned int)10 + input[i] - 'a';
+ } else { /* invalid */
+ return 0;
+ }
+
+ if (i < 3) {
+ /* shift left to make place for the next nibble */
+ h = h << 4;
+ }
+ }
+
+ return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+* A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer,
+ const unsigned char *const input_end, unsigned char **output_pointer)
+{
+ long unsigned int codepoint = 0;
+ unsigned int first_code = 0;
+ const unsigned char *first_sequence = input_pointer;
+ unsigned char utf8_length = 0;
+ unsigned char utf8_position = 0;
+ unsigned char sequence_length = 0;
+ unsigned char first_byte_mark = 0;
+
+ if ((input_end - first_sequence) < 6) {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ /* get the first utf16 sequence */
+ first_code = parse_hex4(first_sequence + 2);
+
+ /* check that the code is valid */
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
+ goto fail;
+ }
+
+ /* UTF16 surrogate pair */
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
+ const unsigned char *second_sequence = first_sequence + 6;
+ unsigned int second_code = 0;
+ sequence_length = 12; /* \uXXXX\uXXXX */
+
+ if ((input_end - second_sequence) < 6) {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
+ /* missing second half of the surrogate pair */
+ goto fail;
+ }
+
+ /* get the second utf16 sequence */
+ second_code = parse_hex4(second_sequence + 2);
+ /* check that the code is valid */
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
+ /* invalid second half of the surrogate pair */
+ goto fail;
+ }
+
+
+ /* calculate the unicode codepoint from the surrogate pair */
+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+ } else {
+ sequence_length = 6; /* \uXXXX */
+ codepoint = first_code;
+ }
+
+ /* encode as UTF-8
+ * takes at maximum 4 bytes to encode:
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ if (codepoint < 0x80) {
+ /* normal ascii, encoding 0xxxxxxx */
+ utf8_length = 1;
+ } else if (codepoint < 0x800) {
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
+ utf8_length = 2;
+ first_byte_mark = 0xC0; /* 11000000 */
+ } else if (codepoint < 0x10000) {
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 3;
+ first_byte_mark = 0xE0; /* 11100000 */
+ } else if (codepoint <= 0x10FFFF) {
+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 4;
+ first_byte_mark = 0xF0; /* 11110000 */
+ } else {
+ /* invalid unicode codepoint */
+ goto fail;
+ }
+
+ /* encode as utf8 */
+ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
+ /* 10xxxxxx */
+ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
+ codepoint >>= 6;
+ }
+ /* encode first byte */
+ if (utf8_length > 1) {
+ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
+ } else {
+ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
+ }
+
+ *output_pointer += utf8_length;
+
+ return sequence_length;
+
+fail:
+ return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer)
+{
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+ unsigned char *output_pointer = NULL;
+ unsigned char *output = NULL;
+
+ /* not a string */
+ if (buffer_at_offset(input_buffer)[0] != '\"') {
+ goto fail;
+ }
+
+ {
+ /* calculate approximate size of the output (overestimate) */
+ size_t allocation_length = 0;
+ size_t skipped_bytes = 0;
+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
+ /* is escape sequence */
+ if (input_end[0] == '\\') {
+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
+ /* prevent buffer overflow when last input character is a backslash */
+ goto fail;
+ }
+ skipped_bytes++;
+ input_end++;
+ }
+ input_end++;
+ }
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
+ goto fail; /* string ended unexpectedly */
+ }
+
+ /* This is at most how much we need for the output */
+ allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+ output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+ if (output == NULL) {
+ goto fail; /* allocation failure */
+ }
+ }
+
+ output_pointer = output;
+ /* loop through the string literal */
+ while (input_pointer < input_end) {
+ if (*input_pointer != '\\') {
+ *output_pointer++ = *input_pointer++;
+ }
+ /* escape sequence */
+ else {
+ unsigned char sequence_length = 2;
+ if ((input_end - input_pointer) < 1) {
+ goto fail;
+ }
+
+ switch (input_pointer[1]) {
+ case 'b':
+ *output_pointer++ = '\b';
+ break;
+ case 'f':
+ *output_pointer++ = '\f';
+ break;
+ case 'n':
+ *output_pointer++ = '\n';
+ break;
+ case 'r':
+ *output_pointer++ = '\r';
+ break;
+ case 't':
+ *output_pointer++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *output_pointer++ = input_pointer[1];
+ break;
+
+ /* UTF-16 literal */
+ case 'u':
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+ if (sequence_length == 0) {
+ /* failed to convert UTF16-literal to UTF-8 */
+ goto fail;
+ }
+ break;
+
+ default:
+ goto fail;
+ }
+ input_pointer += sequence_length;
+ }
+ }
+
+ /* zero terminate the output */
+ *output_pointer = '\0';
+
+ item->type = cJSON_String;
+ item->valuestring = (char *)output;
+
+ input_buffer->offset = (size_t)(input_end - input_buffer->content);
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (output != NULL) {
+ input_buffer->hooks.deallocate(output);
+ }
+
+ if (input_pointer != NULL) {
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+ }
+
+ return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer)
+{
+ const unsigned char *input_pointer = NULL;
+ unsigned char *output = NULL;
+ unsigned char *output_pointer = NULL;
+ size_t output_length = 0;
+ /* numbers of additional characters needed for escaping */
+ size_t escape_characters = 0;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* empty string */
+ if (input == NULL) {
+ output = ensure(output_buffer, sizeof("\"\""));
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "\"\"");
+
+ return true;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (input_pointer = input; *input_pointer; input_pointer++) {
+ switch (*input_pointer) {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ /* one character escape sequence */
+ escape_characters++;
+ break;
+ default:
+ if (*input_pointer < 32) {
+ /* UTF-16 escape sequence uXXXX */
+ escape_characters += 5;
+ }
+ break;
+ }
+ }
+ output_length = (size_t)(input_pointer - input) + escape_characters;
+
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
+ if (output == NULL) {
+ return false;
+ }
+
+ /* no characters have to be escaped */
+ if (escape_characters == 0) {
+ output[0] = '\"';
+ memcpy(output + 1, input, output_length);
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+ }
+
+ output[0] = '\"';
+ output_pointer = output + 1;
+ /* copy the string */
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
+ /* normal character, copy */
+ *output_pointer = *input_pointer;
+ } else {
+ /* character needs to be escaped */
+ *output_pointer++ = '\\';
+ switch (*input_pointer) {
+ case '\\':
+ *output_pointer = '\\';
+ break;
+ case '\"':
+ *output_pointer = '\"';
+ break;
+ case '\b':
+ *output_pointer = 'b';
+ break;
+ case '\f':
+ *output_pointer = 'f';
+ break;
+ case '\n':
+ *output_pointer = 'n';
+ break;
+ case '\r':
+ *output_pointer = 'r';
+ break;
+ case '\t':
+ *output_pointer = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf((char *)output_pointer, "u%04x", *input_pointer);
+ output_pointer += 4;
+ break;
+ }
+ }
+ }
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON *const item, printbuffer *const p)
+{
+ return print_string_ptr((unsigned char *)item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer);
+static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer);
+static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer);
+static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer);
+static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer);
+static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL)) {
+ return NULL;
+ }
+
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
+ buffer->offset++;
+ }
+
+ if (buffer->offset == buffer->length) {
+ buffer->offset--;
+ }
+
+ return buffer;
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
+ cJSON_bool require_null_terminated)
+{
+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
+ cJSON *item = NULL;
+
+ /* reset error position */
+ global_error.json = NULL;
+ global_error.position = 0;
+
+ if (value == NULL) {
+ goto fail;
+ }
+
+ buffer.content = (const unsigned char *)value;
+ buffer.length = strlen((const char *)value) + sizeof("");
+ buffer.offset = 0;
+ buffer.hooks = global_hooks;
+
+ item = cJSON_New_Item(&global_hooks);
+ if (item == NULL) { /* memory fail */
+ goto fail;
+ }
+
+ if (!parse_value(item, buffer_skip_whitespace(&buffer))) {
+ /* parse failure. ep is set. */
+ goto fail;
+ }
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated) {
+ buffer_skip_whitespace(&buffer);
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
+ goto fail;
+ }
+ }
+ if (return_parse_end) {
+ *return_parse_end = (const char *)buffer_at_offset(&buffer);
+ }
+
+ return item;
+
+fail:
+ if (item != NULL) {
+ cJSON_Delete(item);
+ }
+
+ if (value != NULL) {
+ error local_error;
+ local_error.json = (const unsigned char *)value;
+ local_error.position = 0;
+
+ if (buffer.offset < buffer.length) {
+ local_error.position = buffer.offset;
+ } else if (buffer.length > 0) {
+ local_error.position = buffer.length - 1;
+ }
+
+ if (return_parse_end != NULL) {
+ *return_parse_end = (const char *)local_error.json + local_error.position;
+ } else {
+ global_error = local_error;
+ }
+ }
+
+ return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+#define cjson_min(a, b) ((a < b) ? a : b)
+
+static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks)
+{
+ printbuffer buffer[1];
+ unsigned char *printed = NULL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* create buffer */
+ buffer->buffer = (unsigned char *)hooks->allocate(256);
+ buffer->format = format;
+ buffer->hooks = *hooks;
+ if (buffer->buffer == NULL) {
+ goto fail;
+ }
+
+ /* print the value */
+ if (!print_value(item, buffer)) {
+ goto fail;
+ }
+ update_offset(buffer);
+
+ /* check if reallocate is available */
+ if (hooks->reallocate != NULL) {
+ printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->length);
+ buffer->buffer = NULL;
+ if (printed == NULL) {
+ goto fail;
+ }
+ } else { /* otherwise copy the JSON over to a new buffer */
+ printed = (unsigned char *)hooks->allocate(buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+ printed[buffer->offset] = '\0'; /* just to be sure */
+
+ /* free the buffer */
+ hooks->deallocate(buffer->buffer);
+ }
+
+ return printed;
+
+fail:
+ if (buffer->buffer != NULL) {
+ hooks->deallocate(buffer->buffer);
+ }
+
+#if 0
+ if (printed != NULL) {
+ hooks->deallocate(printed);
+ }
+#endif
+
+ return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+ return (char *)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+ return (char *)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if (prebuffer < 0) {
+ return NULL;
+ }
+
+ p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer);
+ if (!p.buffer) {
+ return NULL;
+ }
+
+ p.length = (size_t)prebuffer;
+ p.offset = 0;
+ p.noalloc = false;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ if (!print_value(item, &p)) {
+ return NULL;
+ }
+
+ return (char *)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if (len < 0) {
+ return false;
+ }
+
+ p.buffer = (unsigned char *)buf;
+ p.length = (size_t)len;
+ p.offset = 0;
+ p.noalloc = true;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer)
+{
+ if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
+ return false; /* no input */
+ }
+
+ /* parse the different types of values */
+ /* null */
+ if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
+ item->type = cJSON_NULL;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* false */
+ if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
+ item->type = cJSON_False;
+ input_buffer->offset += 5;
+ return true;
+ }
+ /* true */
+ if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* string */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
+ return parse_string(item, input_buffer);
+ }
+ /* number */
+ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-')
+ || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
+ return parse_number(item, input_buffer);
+ }
+ /* array */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
+ return parse_array(item, input_buffer);
+ }
+ /* object */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
+ return parse_object(item, input_buffer);
+ }
+
+
+ return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output = NULL;
+
+ if ((item == NULL) || (output_buffer == NULL)) {
+ return false;
+ }
+
+ switch ((item->type) & 0xFF) {
+ case cJSON_NULL:
+ output = ensure(output_buffer, 5);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "null");
+ return true;
+
+ case cJSON_False:
+ output = ensure(output_buffer, 6);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "false");
+ return true;
+
+ case cJSON_True:
+ output = ensure(output_buffer, 5);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char *)output, "true");
+ return true;
+
+ case cJSON_Number:
+ return print_number(item, output_buffer);
+
+ case cJSON_Raw: {
+ size_t raw_length = 0;
+ if (item->valuestring == NULL) {
+ if (!output_buffer->noalloc) {
+ output_buffer->hooks.deallocate(output_buffer->buffer);
+ }
+ return false;
+ }
+
+ raw_length = strlen(item->valuestring) + sizeof("");
+ output = ensure(output_buffer, raw_length);
+ if (output == NULL) {
+ return false;
+ }
+ memcpy(output, item->valuestring, raw_length);
+ return true;
+ }
+
+ case cJSON_String:
+ return print_string(item, output_buffer);
+
+ case cJSON_Array:
+ return print_array(item, output_buffer);
+
+ case cJSON_Object:
+ return print_object(item, output_buffer);
+
+ default:
+ return false;
+ }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer)
+{
+ cJSON *head = NULL; /* head of the linked list */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (buffer_at_offset(input_buffer)[0] != '[') {
+ /* not an array */
+ goto fail;
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
+ /* empty array */
+ goto success;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0)) {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL) {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL) {
+ /* start the linked list */
+ current_item = head = new_item;
+ } else {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse next value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer)) {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
+ goto fail; /* expected end of array */
+ }
+
+success:
+ input_buffer->depth--;
+
+ item->type = cJSON_Array;
+ item->child = head;
+
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (head != NULL) {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_element = item->child;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* Compose the output array. */
+ /* opening square bracket */
+ output_pointer = ensure(output_buffer, 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ *output_pointer = '[';
+ output_buffer->offset++;
+ output_buffer->depth++;
+
+ while (current_element != NULL) {
+ if (!print_value(current_element, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+ if (current_element->next) {
+ length = (size_t)(output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ',';
+ if (output_buffer->format) {
+ *output_pointer++ = ' ';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+ }
+ current_element = current_element->next;
+ }
+
+ output_pointer = ensure(output_buffer, 2);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ']';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer)
+{
+ cJSON *head = NULL; /* linked list head */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
+ goto fail; /* not an object */
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
+ goto success; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0)) {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL) {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL) {
+ /* start the linked list */
+ current_item = head = new_item;
+ } else {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse the name of the child */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_string(current_item, input_buffer)) {
+ goto fail; /* faile to parse name */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* swap valuestring and string, because we parsed the name */
+ current_item->string = current_item->valuestring;
+ current_item->valuestring = NULL;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
+ goto fail; /* invalid object */
+ }
+
+ /* parse the value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer)) {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
+ goto fail; /* expected end of object */
+ }
+
+success:
+ input_buffer->depth--;
+
+ item->type = cJSON_Object;
+ item->child = head;
+
+ input_buffer->offset++;
+ return true;
+
+fail:
+ if (head != NULL) {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_item = item->child;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* Compose the output: */
+ length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ *output_pointer++ = '{';
+ output_buffer->depth++;
+ if (output_buffer->format) {
+ *output_pointer++ = '\n';
+ }
+ output_buffer->offset += length;
+
+ while (current_item) {
+ if (output_buffer->format) {
+ size_t i;
+ output_pointer = ensure(output_buffer, output_buffer->depth);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ for (i = 0; i < output_buffer->depth; i++) {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += output_buffer->depth;
+ }
+
+ /* print key */
+ if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ length = (size_t)(output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ':';
+ if (output_buffer->format) {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += length;
+
+ /* print value */
+ if (!print_value(current_item, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ /* print comma if not last */
+ length = (size_t)((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ if (current_item->next) {
+ *output_pointer++ = ',';
+ }
+
+ if (output_buffer->format) {
+ *output_pointer++ = '\n';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+
+ current_item = current_item->next;
+ }
+
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ if (output_buffer->format) {
+ size_t i;
+ for (i = 0; i < (output_buffer->depth - 1); i++) {
+ *output_pointer++ = '\t';
+ }
+ }
+ *output_pointer++ = '}';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+ cJSON *c = array->child;
+ size_t i = 0;
+ while (c) {
+ i++;
+ c = c->next;
+ }
+
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+ return (int)i;
+}
+
+static cJSON *get_array_item(const cJSON *array, size_t index)
+{
+ cJSON *current_child = NULL;
+
+ if (array == NULL) {
+ return NULL;
+ }
+
+ current_child = array->child;
+ while ((current_child != NULL) && (index > 0)) {
+ index--;
+ current_child = current_child->next;
+ }
+
+ return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+ if (index < 0) {
+ return NULL;
+ }
+
+ return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive)
+{
+ cJSON *current_element = NULL;
+
+ if ((object == NULL) || (name == NULL)) {
+ return NULL;
+ }
+
+ current_element = object->child;
+ if (case_sensitive) {
+ while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) {
+ current_element = current_element->next;
+ }
+ } else {
+ while ((current_element != NULL)
+ && (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
+ current_element = current_element->next;
+ }
+ }
+
+ return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string)
+{
+ return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string)
+{
+ return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
+{
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks)
+{
+ cJSON *ref = cJSON_New_Item(hooks);
+ if (!ref) {
+ return NULL;
+ }
+ memcpy(ref, item, sizeof(cJSON));
+ ref->string = NULL;
+ ref->type |= cJSON_IsReference;
+ ref->next = ref->prev = NULL;
+ return ref;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ cJSON *child = NULL;
+
+ if ((item == NULL) || (array == NULL)) {
+ return;
+ }
+
+ child = array->child;
+
+ if (child == NULL) {
+ /* list is empty, start new one */
+ array->child = item;
+ } else {
+ /* append to the end */
+ while (child->next) {
+ child = child->next;
+ }
+ suffix_object(child, item);
+ }
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ /* call cJSON_AddItemToObjectCS for code reuse */
+ cJSON_AddItemToObjectCS(object, (char *)cJSON_strdup((const unsigned char *)string, &global_hooks), item);
+ /* remove cJSON_StringIsConst flag */
+ item->type &= ~cJSON_StringIsConst;
+}
+
+#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+ #pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+ if (!item) {
+ return;
+ }
+ if (!(item->type & cJSON_StringIsConst) && item->string) {
+ global_hooks.deallocate(item->string);
+ }
+ item->string = (char *)string;
+ item->type |= cJSON_StringIsConst;
+ cJSON_AddItemToArray(object, item);
+}
+#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic pop
+#endif
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ cJSON_AddItemToArray(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item)
+{
+ if ((parent == NULL) || (item == NULL)) {
+ return NULL;
+ }
+
+ if (item->prev != NULL) {
+ /* not the first element */
+ item->prev->next = item->next;
+ }
+ if (item->next != NULL) {
+ /* not the last element */
+ item->next->prev = item->prev;
+ }
+
+ if (item == parent->child) {
+ /* first element */
+ parent->child = item->next;
+ }
+ /* make sure the detached item doesn't point anywhere anymore */
+ item->prev = NULL;
+ item->next = NULL;
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ if (which < 0) {
+ return NULL;
+ }
+
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *after_inserted = NULL;
+
+ if (which < 0) {
+ return;
+ }
+
+ after_inserted = get_array_item(array, (size_t)which);
+ if (after_inserted == NULL) {
+ cJSON_AddItemToArray(array, newitem);
+ return;
+ }
+
+ newitem->next = after_inserted;
+ newitem->prev = after_inserted->prev;
+ after_inserted->prev = newitem;
+ if (after_inserted == array->child) {
+ array->child = newitem;
+ } else {
+ newitem->prev->next = newitem;
+ }
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement)
+{
+ if ((parent == NULL) || (replacement == NULL)) {
+ return false;
+ }
+
+ if (replacement == item) {
+ return true;
+ }
+
+ replacement->next = item->next;
+ replacement->prev = item->prev;
+
+ if (replacement->next != NULL) {
+ replacement->next->prev = replacement;
+ }
+ if (replacement->prev != NULL) {
+ replacement->prev->next = replacement;
+ }
+ if (parent->child == item) {
+ parent->child = replacement;
+ }
+
+ item->next = NULL;
+ item->prev = NULL;
+ cJSON_Delete(item);
+
+ return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *obj = NULL;
+
+ if (which < 0) {
+ return;
+ }
+
+ obj = get_array_item(array, (size_t)which);
+ if (obj == NULL) {
+ return;
+ }
+
+ cJSON_ReplaceItemViaPointer(array, obj, newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement,
+ cJSON_bool case_sensitive)
+{
+ cJSON *obj = NULL;
+
+ if (replacement == NULL) {
+ return false;
+ }
+
+ /* replace the name in the replacement */
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) {
+ cJSON_free(replacement->string);
+ }
+ replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
+ replacement->type &= ~cJSON_StringIsConst;
+
+ obj = get_object_item(object, string, case_sensitive);
+ if (obj == NULL) {
+ return false;
+ }
+
+ cJSON_ReplaceItemViaPointer(object, obj, replacement);
+
+ return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+ replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+{
+ replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = b ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+
+ /* use saturation in case of overflow */
+ if (num >= INT_MAX) {
+ item->valueint = INT_MAX;
+ } else if (num <= INT_MIN) {
+ item->valueint = INT_MIN;
+ } else {
+ item->valueint = (int)num;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_String;
+ item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
+ if (!item->valuestring) {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Raw;
+ item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks);
+ if (!item->valuestring) {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Array;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item) {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if (count < 0) {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n) {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if (count < 0) {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = cJSON_CreateNumber((double)numbers[i]);
+ if (!n) {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if (count < 0) {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n) {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if (count < 0) {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++) {
+ n = cJSON_CreateString(strings[i]);
+ if (!n) {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if (!i) {
+ a->child = n;
+ } else {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+/* Duplication */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+ cJSON *newitem = NULL;
+ cJSON *child = NULL;
+ cJSON *next = NULL;
+ cJSON *newchild = NULL;
+
+ /* Bail on bad ptr */
+ if (!item) {
+ goto fail;
+ }
+ /* Create new item */
+ newitem = cJSON_New_Item(&global_hooks);
+ if (!newitem) {
+ goto fail;
+ }
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference);
+ newitem->valueint = item->valueint;
+ newitem->valuedouble = item->valuedouble;
+ if (item->valuestring) {
+ newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks);
+ if (!newitem->valuestring) {
+ goto fail;
+ }
+ }
+ if (item->string) {
+ newitem->string = (item->type & cJSON_StringIsConst) ? item->string : (char *)cJSON_strdup((
+ unsigned char *)item->string, &global_hooks);
+ if (!newitem->string) {
+ goto fail;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse) {
+ return newitem;
+ }
+ /* Walk the ->next chain for the child. */
+ child = item->child;
+ while (child != NULL) {
+ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild) {
+ goto fail;
+ }
+ if (next != NULL) {
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ next->next = newchild;
+ newchild->prev = next;
+ next = newchild;
+ } else {
+ /* Set newitem->child and move to it */
+ newitem->child = newchild;
+ next = newchild;
+ }
+ child = child->next;
+ }
+
+ return newitem;
+
+fail:
+ if (newitem != NULL) {
+ cJSON_Delete(newitem);
+ }
+
+ return NULL;
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+ unsigned char *into = (unsigned char *)json;
+ while (*json) {
+ if (*json == ' ') {
+ json++;
+ } else if (*json == '\t') {
+ /* Whitespace characters. */
+ json++;
+ } else if (*json == '\r') {
+ json++;
+ } else if (*json == '\n') {
+ json++;
+ } else if ((*json == '/') && (json[1] == '/')) {
+ /* double-slash comments, to end of line. */
+ while (*json && (*json != '\n')) {
+ json++;
+ }
+ } else if ((*json == '/') && (json[1] == '*')) {
+ /* multiline comments. */
+ while (*json && !((*json == '*') && (json[1] == '/'))) {
+ json++;
+ }
+ json += 2;
+ } else if (*json == '\"') {
+ /* string literals, which are \" sensitive. */
+ *into++ = (unsigned char) * json++;
+ while (*json && (*json != '\"')) {
+ if (*json == '\\') {
+ *into++ = (unsigned char) * json++;
+ }
+ *into++ = (unsigned char) * json++;
+ }
+ *into++ = (unsigned char) * json++;
+ } else {
+ /* All other characters. */
+ *into++ = (unsigned char) * json++;
+ }
+ }
+
+ /* and null-terminate. */
+ *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xff) == cJSON_True;
+}
+
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive)
+{
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) {
+ return false;
+ }
+
+ /* check if type is valid */
+ switch (a->type & 0xFF) {
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ case cJSON_Number:
+ case cJSON_String:
+ case cJSON_Raw:
+ case cJSON_Array:
+ case cJSON_Object:
+ break;
+
+ default:
+ return false;
+ }
+
+ /* identical objects are equal */
+ if (a == b) {
+ return true;
+ }
+
+ switch (a->type & 0xFF) {
+ /* in these cases and equal type is enough */
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ return true;
+
+ case cJSON_Number:
+ if (a->valuedouble == b->valuedouble) {
+ return true;
+ }
+ return false;
+
+ case cJSON_String:
+ case cJSON_Raw:
+ if ((a->valuestring == NULL) || (b->valuestring == NULL)) {
+ return false;
+ }
+ if (strcmp(a->valuestring, b->valuestring) == 0) {
+ return true;
+ }
+
+ return false;
+
+ case cJSON_Array: {
+ cJSON *a_element = a->child;
+ cJSON *b_element = b->child;
+
+ for (; (a_element != NULL) && (b_element != NULL);) {
+ if (!cJSON_Compare(a_element, b_element, case_sensitive)) {
+ return false;
+ }
+
+ a_element = a_element->next;
+ b_element = b_element->next;
+ }
+
+ return true;
+ }
+
+ case cJSON_Object: {
+ cJSON *a_element = NULL;
+ cJSON_ArrayForEach(a_element, a) {
+ /* TODO This has O(n^2) runtime, which is horrible! */
+ cJSON *b_element = get_object_item(b, a_element->string, case_sensitive);
+ if (b_element == NULL) {
+ return false;
+ }
+
+ if (!cJSON_Compare(a_element, b_element, case_sensitive)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+ return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+ global_hooks.deallocate(object);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/cJSON.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/cJSON.h
new file mode 100644
index 00000000..2e3715a6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/cJSON.h
@@ -0,0 +1,247 @@
+/*
+Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+Permission is hereby granted, 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.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 5
+#define CJSON_VERSION_PATCH 3
+
+#include
+#include
+
+ /* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False (1 << 0)
+#define cJSON_True (1 << 1)
+#define cJSON_NULL (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+ /* The cJSON structure: */
+ typedef struct cJSON
+ {
+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *next;
+ struct cJSON *prev;
+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+ struct cJSON *child;
+
+ /* The type of the item, as above. */
+ int type;
+
+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
+ char *valuestring;
+ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+ int valueint;
+ /* The item's number, if type==cJSON_Number */
+ double valuedouble;
+
+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+ char *string;
+ } cJSON;
+
+ typedef int cJSON_bool;
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+#ifdef __WINDOWS__
+
+ /* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
+ CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+ CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+ CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+ For *nix builds that support visibility attribute, you can define similar behavior by
+ setting default visibility to hidden by adding
+ -fvisibility=hidden (for gcc)
+ or
+ -xldscope=hidden (for sun cc)
+ to CFLAGS
+ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+ */
+
+ /* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type) type __stdcall
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
+#endif
+#else /* !WIN32 */
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+ /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+ /* returns the version of cJSON as a string */
+ CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+ /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+ /* Render a cJSON entity to text for transfer/storage. */
+ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+ /* Render a cJSON entity to text for transfer/storage without any formatting. */
+ CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+ /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+ /* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+ /* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+ /* Delete a cJSON entity and all subentities. */
+ CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
+
+ /* Returns the number of items in an array (or object). */
+ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+ /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+ /* Get item "string" from object. Case insensitive. */
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+ CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+ /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+ /* These functions check the type of an item */
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+ /* These calls create a cJSON item of the appropriate type. */
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+ /* raw json */
+ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+ /* These utilities create an Array of count items. */
+ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
+
+ /* Append item to the specified array/object. */
+ CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+ CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+ /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+ CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+ /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+ CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+ CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+ /* Remove/Detatch items from Arrays/Objects. */
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+ /* Update array items. */
+ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+ CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+ CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
+ CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem);
+
+ /* Duplicate a cJSON item */
+ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+ /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+ need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ The item->next and ->prev pointers are always zero on return from Duplicate. */
+ /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+
+ /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+ /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
+ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+ CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+ /* Macros for creating things quickly. */
+#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s))
+
+ /* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+ /* helper for the cJSON_SetNumberValue macro */
+ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+
+ /* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+ /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+ CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+ CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2.h
new file mode 100644
index 00000000..8b96d25d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2.h
@@ -0,0 +1,5363 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_H
+#define NGHTTP2_H
+
+
+#ifdef IOTX_HTTP2_DEBUG
+#define DEBUGBUILD
+#endif
+/* Define WIN32 when build target is Win32 API (borrowed from
+ libcurl) */
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#define WIN32
+#define ssize_t unsigned int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+/* MSVC < 2013 does not have inttypes.h because it is not C99
+ compliant. See compiler macros and version number in
+ https://sourceforge.net/p/predef/wiki/Compilers/ */
+#include
+#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
+#include
+#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
+#include
+#include
+
+#include
+
+#ifdef NGHTTP2_STATICLIB
+#define NGHTTP2_EXTERN
+#elif defined(WIN32__)
+#ifdef BUILDING_NGHTTP2
+#define NGHTTP2_EXTERN __declspec(dllexport)
+#else /* !BUILDING_NGHTTP2 */
+#define NGHTTP2_EXTERN __declspec(dllimport)
+#endif /* !BUILDING_NGHTTP2 */
+#else /* !defined(WIN32) */
+#ifdef BUILDING_NGHTTP2
+#define NGHTTP2_EXTERN __attribute__((visibility("default")))
+#else /* !BUILDING_NGHTTP2 */
+#define NGHTTP2_EXTERN
+#endif /* !BUILDING_NGHTTP2 */
+#endif /* !defined(WIN32) */
+
+/**
+ * @macro
+ *
+ * The protocol version identification string of this library
+ * supports. This identifier is used if HTTP/2 is used over TLS.
+ */
+#define NGHTTP2_PROTO_VERSION_ID "h2"
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_PROTO_VERSION_ID`.
+ */
+#define NGHTTP2_PROTO_VERSION_ID_LEN 2
+
+/**
+ * @macro
+ *
+ * The serialized form of ALPN protocol identifier this library
+ * supports. Notice that first byte is the length of following
+ * protocol identifier. This is the same wire format of `TLS ALPN
+ * extension `_. This is useful
+ * to process incoming ALPN tokens in wire format.
+ */
+#define NGHTTP2_PROTO_ALPN "\x2h2"
+
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_PROTO_ALPN`.
+ */
+#define NGHTTP2_PROTO_ALPN_LEN (sizeof(NGHTTP2_PROTO_ALPN) - 1)
+
+/**
+ * @macro
+ *
+ * The protocol version identification string of this library
+ * supports. This identifier is used if HTTP/2 is used over cleartext
+ * TCP.
+ */
+#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "h2c"
+
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_CLEARTEXT_PROTO_VERSION_ID`.
+ */
+#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN 3
+
+struct nghttp2_session;
+/**
+ * @struct
+ *
+ * The primary structure to hold the resources needed for a HTTP/2
+ * session. The details of this structure are intentionally hidden
+ * from the public API.
+ */
+typedef struct nghttp2_session nghttp2_session;
+
+/**
+ * @macro
+ *
+ * The age of :type:`nghttp2_info`
+ */
+#define NGHTTP2_VERSION_AGE 1
+
+#ifndef HTTP2_RECV_BUFFER_LENGHT
+#define HTTP2_RECV_BUFFER_LENGHT 16384
+#endif
+/**
+ * @struct
+ *
+ * This struct is what `nghttp2_version()` returns. It holds
+ * information about the particular nghttp2 version.
+ */
+typedef struct {
+ /**
+ * Age of this struct. This instance of nghttp2 sets it to
+ * :macro:`NGHTTP2_VERSION_AGE` but a future version may bump it and
+ * add more struct fields at the bottom
+ */
+ int age;
+ /**
+ * the :macro:`NGHTTP2_VERSION_NUM` number (since age ==1)
+ */
+ int version_num;
+ /**
+ * points to the :macro:`NGHTTP2_VERSION` string (since age ==1)
+ */
+ const char *version_str;
+ /**
+ * points to the :macro:`NGHTTP2_PROTO_VERSION_ID` string this
+ * instance implements (since age ==1)
+ */
+ const char *proto_str;
+ /* -------- the above fields all exist when age == 1 */
+} nghttp2_info;
+
+/**
+ * @macro
+ *
+ * The default weight of stream dependency.
+ */
+#define NGHTTP2_DEFAULT_WEIGHT 16
+
+/**
+ * @macro
+ *
+ * The maximum weight of stream dependency.
+ */
+#define NGHTTP2_MAX_WEIGHT 256
+
+/**
+ * @macro
+ *
+ * The minimum weight of stream dependency.
+ */
+#define NGHTTP2_MIN_WEIGHT 1
+
+/**
+ * @macro
+ *
+ * The maximum window size
+ */
+#define NGHTTP2_MAX_WINDOW_SIZE ((int32_t)((1U << 31) - 1))
+
+/**
+ * @macro
+ *
+ * The initial window size for stream level flow control.
+ */
+#define NGHTTP2_INITIAL_WINDOW_SIZE ((1 << 24) - 1)
+/**
+ * @macro
+ *
+ * The initial window size for connection level flow control.
+ */
+#define NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ((1 << 24) - 1)
+
+/**
+ * @macro
+ *
+ * The default header table size.
+ */
+#define NGHTTP2_DEFAULT_HEADER_TABLE_SIZE (1 << 12)
+
+/**
+ * @macro
+ *
+ * The client magic string, which is the first 24 bytes byte string of
+ * client connection preface.
+ */
+#define NGHTTP2_CLIENT_MAGIC "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_CLIENT_MAGIC`.
+ */
+#define NGHTTP2_CLIENT_MAGIC_LEN 24
+
+/**
+ * @enum
+ *
+ * Error codes used in this library. The code range is [-999, -500],
+ * inclusive. The following values are defined:
+ */
+typedef enum {
+ /**
+ * Invalid argument passed.
+ */
+ NGHTTP2_ERR_INVALID_ARGUMENT = -501,
+ /**
+ * Out of buffer space.
+ */
+ NGHTTP2_ERR_BUFFER_ERROR = -502,
+ /**
+ * The specified protocol version is not supported.
+ */
+ NGHTTP2_ERR_UNSUPPORTED_VERSION = -503,
+ /**
+ * Used as a return value from :type:`nghttp2_send_callback`,
+ * :type:`nghttp2_recv_callback` and
+ * :type:`nghttp2_send_data_callback` to indicate that the operation
+ * would block.
+ */
+ NGHTTP2_ERR_WOULDBLOCK = -504,
+ /**
+ * General protocol error
+ */
+ NGHTTP2_ERR_PROTO = -505,
+ /**
+ * The frame is invalid.
+ */
+ NGHTTP2_ERR_INVALID_FRAME = -506,
+ /**
+ * The peer performed a shutdown on the connection.
+ */
+ NGHTTP2_ERR_EOF = -507,
+ /**
+ * Used as a return value from
+ * :func:`nghttp2_data_source_read_callback` to indicate that data
+ * transfer is postponed. See
+ * :func:`nghttp2_data_source_read_callback` for details.
+ */
+ NGHTTP2_ERR_DEFERRED = -508,
+ /**
+ * Stream ID has reached the maximum value. Therefore no stream ID
+ * is available.
+ */
+ NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE = -509,
+ /**
+ * The stream is already closed; or the stream ID is invalid.
+ */
+ NGHTTP2_ERR_STREAM_CLOSED = -510,
+ /**
+ * RST_STREAM has been added to the outbound queue. The stream is
+ * in closing state.
+ */
+ NGHTTP2_ERR_STREAM_CLOSING = -511,
+ /**
+ * The transmission is not allowed for this stream (e.g., a frame
+ * with END_STREAM flag set has already sent).
+ */
+ NGHTTP2_ERR_STREAM_SHUT_WR = -512,
+ /**
+ * The stream ID is invalid.
+ */
+ NGHTTP2_ERR_INVALID_STREAM_ID = -513,
+ /**
+ * The state of the stream is not valid (e.g., DATA cannot be sent
+ * to the stream if response HEADERS has not been sent).
+ */
+ NGHTTP2_ERR_INVALID_STREAM_STATE = -514,
+ /**
+ * Another DATA frame has already been deferred.
+ */
+ NGHTTP2_ERR_DEFERRED_DATA_EXIST = -515,
+ /**
+ * Starting new stream is not allowed (e.g., GOAWAY has been sent
+ * and/or received).
+ */
+ NGHTTP2_ERR_START_STREAM_NOT_ALLOWED = -516,
+ /**
+ * GOAWAY has already been sent.
+ */
+ NGHTTP2_ERR_GOAWAY_ALREADY_SENT = -517,
+ /**
+ * The received frame contains the invalid header block (e.g., There
+ * are duplicate header names; or the header names are not encoded
+ * in US-ASCII character set and not lower cased; or the header name
+ * is zero-length string; or the header value contains multiple
+ * in-sequence NUL bytes).
+ */
+ NGHTTP2_ERR_INVALID_HEADER_BLOCK = -518,
+ /**
+ * Indicates that the context is not suitable to perform the
+ * requested operation.
+ */
+ NGHTTP2_ERR_INVALID_STATE = -519,
+ /**
+ * The user callback function failed due to the temporal error.
+ */
+ NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE = -521,
+ /**
+ * The length of the frame is invalid, either too large or too small.
+ */
+ NGHTTP2_ERR_FRAME_SIZE_ERROR = -522,
+ /**
+ * Header block inflate/deflate error.
+ */
+ NGHTTP2_ERR_HEADER_COMP = -523,
+ /**
+ * Flow control error
+ */
+ NGHTTP2_ERR_FLOW_CONTROL = -524,
+ /**
+ * Insufficient buffer size given to function.
+ */
+ NGHTTP2_ERR_INSUFF_BUFSIZE = -525,
+ /**
+ * Callback was paused by the application
+ */
+ NGHTTP2_ERR_PAUSE = -526,
+ /**
+ * There are too many in-flight SETTING frame and no more
+ * transmission of SETTINGS is allowed.
+ */
+ NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS = -527,
+ /**
+ * The server push is disabled.
+ */
+ NGHTTP2_ERR_PUSH_DISABLED = -528,
+ /**
+ * DATA or HEADERS frame for a given stream has been already
+ * submitted and has not been fully processed yet. Application
+ * should wait for the transmission of the previously submitted
+ * frame before submitting another.
+ */
+ NGHTTP2_ERR_DATA_EXIST = -529,
+ /**
+ * The current session is closing due to a connection error or
+ * `nghttp2_session_terminate_session()` is called.
+ */
+ NGHTTP2_ERR_SESSION_CLOSING = -530,
+ /**
+ * Invalid HTTP header field was received and stream is going to be
+ * closed.
+ */
+ NGHTTP2_ERR_HTTP_HEADER = -531,
+ /**
+ * Violation in HTTP messaging rule.
+ */
+ NGHTTP2_ERR_HTTP_MESSAGING = -532,
+ /**
+ * Stream was refused.
+ */
+ NGHTTP2_ERR_REFUSED_STREAM = -533,
+ /**
+ * Unexpected internal error, but recovered.
+ */
+ NGHTTP2_ERR_INTERNAL = -534,
+ /**
+ * Indicates that a processing was canceled.
+ */
+ NGHTTP2_ERR_CANCEL = -535,
+ /**
+ * When a local endpoint expects to receive SETTINGS frame, it
+ * receives an other type of frame.
+ */
+ NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
+ /**
+ * The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
+ * under unexpected condition and processing was terminated (e.g.,
+ * out of memory). If application receives this error code, it must
+ * stop using that :type:`nghttp2_session` object and only allowed
+ * operation for that object is deallocate it using
+ * `nghttp2_session_del()`.
+ */
+ NGHTTP2_ERR_FATAL = -900,
+ /**
+ * Out of memory. This is a fatal error.
+ */
+ NGHTTP2_ERR_NOMEM = -901,
+ /**
+ * The user callback function failed. This is a fatal error.
+ */
+ NGHTTP2_ERR_CALLBACK_FAILURE = -902,
+ /**
+ * Invalid client magic (see :macro:`NGHTTP2_CLIENT_MAGIC`) was
+ * received and further processing is not possible.
+ */
+ NGHTTP2_ERR_BAD_CLIENT_MAGIC = -903,
+ /**
+ * Possible flooding by peer was detected in this HTTP/2 session.
+ * Flooding is measured by how many PING and SETTINGS frames with
+ * ACK flag set are queued for transmission. These frames are
+ * response for the peer initiated frames, and peer can cause memory
+ * exhaustion on server side to send these frames forever and does
+ * not read network.
+ */
+ NGHTTP2_ERR_FLOODED = -904
+} nghttp2_error;
+
+/**
+ * @struct
+ *
+ * The object representing single contiguous buffer.
+ */
+typedef struct {
+ /**
+ * The pointer to the buffer.
+ */
+ uint8_t *base;
+ /**
+ * The length of the buffer.
+ */
+ size_t len;
+} nghttp2_vec;
+
+struct nghttp2_rcbuf;
+
+/**
+ * @struct
+ *
+ * The object representing reference counted buffer. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_rcbuf nghttp2_rcbuf;
+
+/**
+ * @function
+ *
+ * Increments the reference count of |rcbuf| by 1.
+ */
+NGHTTP2_EXTERN void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Decrements the reference count of |rcbuf| by 1. If the reference
+ * count becomes zero, the object pointed by |rcbuf| will be freed.
+ * In this case, application must not use |rcbuf| again.
+ */
+NGHTTP2_EXTERN void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Returns the underlying buffer managed by |rcbuf|.
+ */
+NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the underlying buffer is statically allocated,
+ * and 0 otherwise. This can be useful for language bindings that wish
+ * to avoid creating duplicate strings for these buffers.
+ */
+NGHTTP2_EXTERN int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf);
+
+/**
+ * @enum
+ *
+ * The flags for header field name/value pair.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_NV_FLAG_NONE = 0,
+ /**
+ * Indicates that this name/value pair must not be indexed ("Literal
+ * Header Field never Indexed" representation must be used in HPACK
+ * encoding). Other implementation calls this bit as "sensitive".
+ */
+ NGHTTP2_NV_FLAG_NO_INDEX = 0x01,
+ /**
+ * This flag is set solely by application. If this flag is set, the
+ * library does not make a copy of header field name. This could
+ * improve performance.
+ */
+ NGHTTP2_NV_FLAG_NO_COPY_NAME = 0x02,
+ /**
+ * This flag is set solely by application. If this flag is set, the
+ * library does not make a copy of header field value. This could
+ * improve performance.
+ */
+ NGHTTP2_NV_FLAG_NO_COPY_VALUE = 0x04
+} nghttp2_nv_flag;
+
+/**
+ * @struct
+ *
+ * The name/value pair, which mainly used to represent header fields.
+ */
+typedef struct {
+ /**
+ * The |name| byte string. If this struct is presented from library
+ * (e.g., :type:`nghttp2_on_frame_recv_callback`), |name| is
+ * guaranteed to be NULL-terminated. For some callbacks
+ * (:type:`nghttp2_before_frame_send_callback`,
+ * :type:`nghttp2_on_frame_send_callback`, and
+ * :type:`nghttp2_on_frame_not_send_callback`), it may not be
+ * NULL-terminated if header field is passed from application with
+ * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`). When application
+ * is constructing this struct, |name| is not required to be
+ * NULL-terminated.
+ */
+ uint8_t *name;
+ /**
+ * The |value| byte string. If this struct is presented from
+ * library (e.g., :type:`nghttp2_on_frame_recv_callback`), |value|
+ * is guaranteed to be NULL-terminated. For some callbacks
+ * (:type:`nghttp2_before_frame_send_callback`,
+ * :type:`nghttp2_on_frame_send_callback`, and
+ * :type:`nghttp2_on_frame_not_send_callback`), it may not be
+ * NULL-terminated if header field is passed from application with
+ * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE`). When
+ * application is constructing this struct, |value| is not required
+ * to be NULL-terminated.
+ */
+ uint8_t *value;
+ /**
+ * The length of the |name|, excluding terminating NULL.
+ */
+ size_t namelen;
+ /**
+ * The length of the |value|, excluding terminating NULL.
+ */
+ size_t valuelen;
+ /**
+ * Bitwise OR of one or more of :type:`nghttp2_nv_flag`.
+ */
+ uint8_t flags;
+} nghttp2_nv;
+
+/**
+ * @enum
+ *
+ * The frame types in HTTP/2 specification.
+ */
+typedef enum {
+ /**
+ * The DATA frame.
+ */
+ NGHTTP2_DATA = 0,
+ /**
+ * The HEADERS frame.
+ */
+ NGHTTP2_HEADERS = 0x01,
+ /**
+ * The PRIORITY frame.
+ */
+ NGHTTP2_PRIORITY = 0x02,
+ /**
+ * The RST_STREAM frame.
+ */
+ NGHTTP2_RST_STREAM = 0x03,
+ /**
+ * The SETTINGS frame.
+ */
+ NGHTTP2_SETTINGS = 0x04,
+ /**
+ * The PUSH_PROMISE frame.
+ */
+ NGHTTP2_PUSH_PROMISE = 0x05,
+ /**
+ * The PING frame.
+ */
+ NGHTTP2_PING = 0x06,
+ /**
+ * The GOAWAY frame.
+ */
+ NGHTTP2_GOAWAY = 0x07,
+ /**
+ * The WINDOW_UPDATE frame.
+ */
+ NGHTTP2_WINDOW_UPDATE = 0x08,
+ /**
+ * The CONTINUATION frame. This frame type won't be passed to any
+ * callbacks because the library processes this frame type and its
+ * preceding HEADERS/PUSH_PROMISE as a single frame.
+ */
+ NGHTTP2_CONTINUATION = 0x09,
+ /**
+ * The ALTSVC frame, which is defined in `RFC 7383
+ * `_.
+ */
+ NGHTTP2_ALTSVC = 0x0a
+} nghttp2_frame_type;
+
+/**
+ * @enum
+ *
+ * The flags for HTTP/2 frames. This enum defines all flags for all
+ * frames.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_FLAG_NONE = 0,
+ /**
+ * The END_STREAM flag.
+ */
+ NGHTTP2_FLAG_END_STREAM = 0x01,
+ /**
+ * The END_HEADERS flag.
+ */
+ NGHTTP2_FLAG_END_HEADERS = 0x04,
+ /**
+ * The ACK flag.
+ */
+ NGHTTP2_FLAG_ACK = 0x01,
+ /**
+ * The PADDED flag.
+ */
+ NGHTTP2_FLAG_PADDED = 0x08,
+ /**
+ * The PRIORITY flag.
+ */
+ NGHTTP2_FLAG_PRIORITY = 0x20
+} nghttp2_flag;
+
+/**
+ * @enum
+ * The SETTINGS ID.
+ */
+typedef enum {
+ /**
+ * SETTINGS_HEADER_TABLE_SIZE
+ */
+ NGHTTP2_SETTINGS_HEADER_TABLE_SIZE = 0x01,
+ /**
+ * SETTINGS_ENABLE_PUSH
+ */
+ NGHTTP2_SETTINGS_ENABLE_PUSH = 0x02,
+ /**
+ * SETTINGS_MAX_CONCURRENT_STREAMS
+ */
+ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 0x03,
+ /**
+ * SETTINGS_INITIAL_WINDOW_SIZE
+ */
+ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 0x04,
+ /**
+ * SETTINGS_MAX_FRAME_SIZE
+ */
+ NGHTTP2_SETTINGS_MAX_FRAME_SIZE = 0x05,
+ /**
+ * SETTINGS_MAX_HEADER_LIST_SIZE
+ */
+ NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06
+} nghttp2_settings_id;
+/* Note: If we add SETTINGS, update the capacity of
+ NGHTTP2_INBOUND_NUM_IV as well */
+
+/**
+ * @macro
+ *
+ * .. warning::
+ *
+ * Deprecated. The initial max concurrent streams is 0xffffffffu.
+ *
+ * Default maximum number of incoming concurrent streams. Use
+ * `nghttp2_submit_settings()` with
+ * :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the
+ * maximum number of incoming concurrent streams.
+ *
+ * .. note::
+ *
+ * The maximum number of outgoing concurrent streams is 100 by
+ * default.
+ */
+#define NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
+
+/**
+ * @enum
+ * The status codes for the RST_STREAM and GOAWAY frames.
+ */
+typedef enum {
+ /**
+ * No errors.
+ */
+ NGHTTP2_NO_ERROR = 0x00,
+ /**
+ * PROTOCOL_ERROR
+ */
+ NGHTTP2_PROTOCOL_ERROR = 0x01,
+ /**
+ * INTERNAL_ERROR
+ */
+ NGHTTP2_INTERNAL_ERROR = 0x02,
+ /**
+ * FLOW_CONTROL_ERROR
+ */
+ NGHTTP2_FLOW_CONTROL_ERROR = 0x03,
+ /**
+ * SETTINGS_TIMEOUT
+ */
+ NGHTTP2_SETTINGS_TIMEOUT = 0x04,
+ /**
+ * STREAM_CLOSED
+ */
+ NGHTTP2_STREAM_CLOSED = 0x05,
+ /**
+ * FRAME_SIZE_ERROR
+ */
+ NGHTTP2_FRAME_SIZE_ERROR = 0x06,
+ /**
+ * REFUSED_STREAM
+ */
+ NGHTTP2_REFUSED_STREAM = 0x07,
+ /**
+ * CANCEL
+ */
+ NGHTTP2_CANCEL = 0x08,
+ /**
+ * COMPRESSION_ERROR
+ */
+ NGHTTP2_COMPRESSION_ERROR = 0x09,
+ /**
+ * CONNECT_ERROR
+ */
+ NGHTTP2_CONNECT_ERROR = 0x0a,
+ /**
+ * ENHANCE_YOUR_CALM
+ */
+ NGHTTP2_ENHANCE_YOUR_CALM = 0x0b,
+ /**
+ * INADEQUATE_SECURITY
+ */
+ NGHTTP2_INADEQUATE_SECURITY = 0x0c,
+ /**
+ * HTTP_1_1_REQUIRED
+ */
+ NGHTTP2_HTTP_1_1_REQUIRED = 0x0d
+} nghttp2_error_code;
+
+/**
+ * @struct
+ * The frame header.
+ */
+typedef struct {
+ /**
+ * The length field of this frame, excluding frame header.
+ */
+ size_t length;
+ /**
+ * The stream identifier (aka, stream ID)
+ */
+ int32_t stream_id;
+ /**
+ * The type of this frame. See `nghttp2_frame_type`.
+ */
+ uint8_t type;
+ /**
+ * The flags.
+ */
+ uint8_t flags;
+ /**
+ * Reserved bit in frame header. Currently, this is always set to 0
+ * and application should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_frame_hd;
+
+/**
+ * @union
+ *
+ * This union represents the some kind of data source passed to
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+typedef struct {
+ /**
+ * The integer field, suitable for a file descriptor.
+ */
+ int fd;
+ /**
+ * data length.
+ */
+ int len;
+ /**
+ * The pointer to an arbitrary object.
+ */
+ void *ptr;
+} nghttp2_data_source;
+
+/**
+ * @enum
+ *
+ * The flags used to set in |data_flags| output parameter in
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_DATA_FLAG_NONE = 0,
+ /**
+ * Indicates EOF was sensed.
+ */
+ NGHTTP2_DATA_FLAG_EOF = 0x01,
+ /**
+ * Indicates that END_STREAM flag must not be set even if
+ * NGHTTP2_DATA_FLAG_EOF is set. Usually this flag is used to send
+ * trailer fields with `nghttp2_submit_request()` or
+ * `nghttp2_submit_response()`.
+ */
+ NGHTTP2_DATA_FLAG_NO_END_STREAM = 0x02,
+ /**
+ * Indicates that application will send complete DATA frame in
+ * :type:`nghttp2_send_data_callback`.
+ */
+ NGHTTP2_DATA_FLAG_NO_COPY = 0x04
+} nghttp2_data_flag;
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library wants to read data from
+ * the |source|. The read data is sent in the stream |stream_id|.
+ * The implementation of this function must read at most |length|
+ * bytes of data from |source| (or possibly other places) and store
+ * them in |buf| and return number of data stored in |buf|. If EOF is
+ * reached, set :enum:`NGHTTP2_DATA_FLAG_EOF` flag in |*data_flags|.
+ *
+ * Sometime it is desirable to avoid copying data into |buf| and let
+ * application to send data directly. To achieve this, set
+ * :enum:`NGHTTP2_DATA_FLAG_NO_COPY` to |*data_flags| (and possibly
+ * other flags, just like when we do copy), and return the number of
+ * bytes to send without copying data into |buf|. The library, seeing
+ * :enum:`NGHTTP2_DATA_FLAG_NO_COPY`, will invoke
+ * :type:`nghttp2_send_data_callback`. The application must send
+ * complete DATA frame in that callback.
+ *
+ * If this callback is set by `nghttp2_submit_request()`,
+ * `nghttp2_submit_response()` or `nghttp2_submit_headers()` and
+ * `nghttp2_submit_data()` with flag parameter
+ * :enum:`NGHTTP2_FLAG_END_STREAM` set, and
+ * :enum:`NGHTTP2_DATA_FLAG_EOF` flag is set to |*data_flags|, DATA
+ * frame will have END_STREAM flag set. Usually, this is expected
+ * behaviour and all are fine. One exception is send trailer fields.
+ * You cannot send trailer fields after sending frame with END_STREAM
+ * set. To avoid this problem, one can set
+ * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM` along with
+ * :enum:`NGHTTP2_DATA_FLAG_EOF` to signal the library not to set
+ * END_STREAM in DATA frame. Then application can use
+ * `nghttp2_submit_trailer()` to send trailer fields.
+ * `nghttp2_submit_trailer()` can be called inside this callback.
+ *
+ * If the application wants to postpone DATA frames (e.g.,
+ * asynchronous I/O, or reading data blocks for long time), it is
+ * achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading
+ * any data in this invocation. The library removes DATA frame from
+ * the outgoing queue temporarily. To move back deferred DATA frame
+ * to outgoing queue, call `nghttp2_session_resume_data()`.
+ *
+ * By default, |length| is limited to 16KiB at maximum. If peer
+ * allows larger frames, application can enlarge transmission buffer
+ * size. See :type:`nghttp2_data_source_read_length_callback` for
+ * more details.
+ *
+ * If the application just wants to return from
+ * `nghttp2_session_send()` or `nghttp2_session_mem_send()` without
+ * sending anything, return :enum:`NGHTTP2_ERR_PAUSE`.
+ *
+ * In case of error, there are 2 choices. Returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream
+ * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. If a
+ * different error code is desirable, use
+ * `nghttp2_submit_rst_stream()` with a desired error code and then
+ * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Returning
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session
+ * failure.
+ */
+typedef ssize_t (*nghttp2_data_source_read_callback)(
+ nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length,
+ uint32_t *data_flags, nghttp2_data_source *source, void *user_data);
+
+/**
+ * @struct
+ *
+ * This struct represents the data source and the way to read a chunk
+ * of data from it.
+ */
+typedef struct {
+ /**
+ * The data source.
+ */
+ nghttp2_data_source source;
+ /**
+ * The callback function to read a chunk of data from the |source|.
+ */
+ nghttp2_data_source_read_callback read_callback;
+} nghttp2_data_provider;
+
+/**
+ * @struct
+ *
+ * The DATA frame. The received data is delivered via
+ * :type:`nghttp2_on_data_chunk_recv_callback`.
+ */
+typedef struct {
+ nghttp2_frame_hd hd;
+ /**
+ * The length of the padding in this frame. This includes PAD_HIGH
+ * and PAD_LOW.
+ */
+ size_t padlen;
+} nghttp2_data;
+
+/**
+ * @enum
+ *
+ * The category of HEADERS, which indicates the role of the frame. In
+ * HTTP/2 spec, request, response, push response and other arbitrary
+ * headers (e.g., trailer fields) are all called just HEADERS. To
+ * give the application the role of incoming HEADERS frame, we define
+ * several categories.
+ */
+typedef enum {
+ /**
+ * The HEADERS frame is opening new stream, which is analogous to
+ * SYN_STREAM in SPDY.
+ */
+ NGHTTP2_HCAT_REQUEST = 0,
+ /**
+ * The HEADERS frame is the first response headers, which is
+ * analogous to SYN_REPLY in SPDY.
+ */
+ NGHTTP2_HCAT_RESPONSE = 1,
+ /**
+ * The HEADERS frame is the first headers sent against reserved
+ * stream.
+ */
+ NGHTTP2_HCAT_PUSH_RESPONSE = 2,
+ /**
+ * The HEADERS frame which does not apply for the above categories,
+ * which is analogous to HEADERS in SPDY. If non-final response
+ * (e.g., status 1xx) is used, final response HEADERS frame will be
+ * categorized here.
+ */
+ NGHTTP2_HCAT_HEADERS = 3
+} nghttp2_headers_category;
+
+/**
+ * @struct
+ *
+ * The structure to specify stream dependency.
+ */
+typedef struct {
+ /**
+ * The stream ID of the stream to depend on. Specifying 0 makes
+ * stream not depend any other stream.
+ */
+ int32_t stream_id;
+ /**
+ * The weight of this dependency.
+ */
+ int32_t weight;
+ /**
+ * nonzero means exclusive dependency
+ */
+ uint8_t exclusive;
+} nghttp2_priority_spec;
+
+/**
+ * @struct
+ *
+ * The HEADERS frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The length of the padding in this frame. This includes PAD_HIGH
+ * and PAD_LOW.
+ */
+ size_t padlen;
+ /**
+ * The priority specification
+ */
+ nghttp2_priority_spec pri_spec;
+ /**
+ * The name/value pairs.
+ */
+ nghttp2_nv *nva;
+ /**
+ * The number of name/value pairs in |nva|.
+ */
+ size_t nvlen;
+ /**
+ * The category of this HEADERS frame.
+ */
+ nghttp2_headers_category cat;
+} nghttp2_headers;
+
+/**
+ * @struct
+ *
+ * The PRIORITY frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The priority specification.
+ */
+ nghttp2_priority_spec pri_spec;
+} nghttp2_priority;
+
+/**
+ * @struct
+ *
+ * The RST_STREAM frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The error code. See :type:`nghttp2_error_code`.
+ */
+ uint32_t error_code;
+} nghttp2_rst_stream;
+
+/**
+ * @struct
+ *
+ * The SETTINGS ID/Value pair. It has the following members:
+ */
+typedef struct {
+ /**
+ * The SETTINGS ID. See :type:`nghttp2_settings_id`.
+ */
+ int32_t settings_id;
+ /**
+ * The value of this entry.
+ */
+ uint32_t value;
+} nghttp2_settings_entry;
+
+/**
+ * @struct
+ *
+ * The SETTINGS frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The number of SETTINGS ID/Value pairs in |iv|.
+ */
+ size_t niv;
+ /**
+ * The pointer to the array of SETTINGS ID/Value pair.
+ */
+ nghttp2_settings_entry *iv;
+} nghttp2_settings;
+
+/**
+ * @struct
+ *
+ * The PUSH_PROMISE frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The length of the padding in this frame. This includes PAD_HIGH
+ * and PAD_LOW.
+ */
+ size_t padlen;
+ /**
+ * The name/value pairs.
+ */
+ nghttp2_nv *nva;
+ /**
+ * The number of name/value pairs in |nva|.
+ */
+ size_t nvlen;
+ /**
+ * The promised stream ID
+ */
+ int32_t promised_stream_id;
+ /**
+ * Reserved bit. Currently this is always set to 0 and application
+ * should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_push_promise;
+
+/**
+ * @struct
+ *
+ * The PING frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The opaque data
+ */
+ uint8_t opaque_data[8];
+} nghttp2_ping;
+
+/**
+ * @struct
+ *
+ * The GOAWAY frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The last stream stream ID.
+ */
+ int32_t last_stream_id;
+ /**
+ * The error code. See :type:`nghttp2_error_code`.
+ */
+ uint32_t error_code;
+ /**
+ * The additional debug data
+ */
+ uint8_t *opaque_data;
+ /**
+ * The length of |opaque_data| member.
+ */
+ size_t opaque_data_len;
+ /**
+ * Reserved bit. Currently this is always set to 0 and application
+ * should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_goaway;
+
+/**
+ * @struct
+ *
+ * The WINDOW_UPDATE frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The window size increment.
+ */
+ int32_t window_size_increment;
+ /**
+ * Reserved bit. Currently this is always set to 0 and application
+ * should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_window_update;
+
+/**
+ * @struct
+ *
+ * The extension frame. It has following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The pointer to extension payload. The exact pointer type is
+ * determined by hd.type.
+ *
+ * Currently, no extension is supported. This is a place holder for
+ * the future extensions.
+ */
+ void *payload;
+} nghttp2_extension;
+
+/**
+ * @union
+ *
+ * This union includes all frames to pass them to various function
+ * calls as nghttp2_frame type. The CONTINUATION frame is omitted
+ * from here because the library deals with it internally.
+ */
+typedef union {
+ /**
+ * The frame header, which is convenient to inspect frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The DATA frame.
+ */
+ nghttp2_data data;
+ /**
+ * The HEADERS frame.
+ */
+ nghttp2_headers headers;
+ /**
+ * The PRIORITY frame.
+ */
+ nghttp2_priority priority;
+ /**
+ * The RST_STREAM frame.
+ */
+ nghttp2_rst_stream rst_stream;
+ /**
+ * The SETTINGS frame.
+ */
+ nghttp2_settings settings;
+ /**
+ * The PUSH_PROMISE frame.
+ */
+ nghttp2_push_promise push_promise;
+ /**
+ * The PING frame.
+ */
+ nghttp2_ping ping;
+ /**
+ * The GOAWAY frame.
+ */
+ nghttp2_goaway goaway;
+ /**
+ * The WINDOW_UPDATE frame.
+ */
+ nghttp2_window_update window_update;
+ /**
+ * The extension frame.
+ */
+ nghttp2_extension ext;
+} nghttp2_frame;
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when |session| wants to send data to the
+ * remote peer. The implementation of this function must send at most
+ * |length| bytes of data stored in |data|. The |flags| is currently
+ * not used and always 0. It must return the number of bytes sent if
+ * it succeeds. If it cannot send any single byte without blocking,
+ * it must return :enum:`NGHTTP2_ERR_WOULDBLOCK`. For other errors,
+ * it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * This callback is required if the application uses
+ * `nghttp2_session_send()` to send data to the remote endpoint. If
+ * the application uses solely `nghttp2_session_mem_send()` instead,
+ * this callback function is unnecessary.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_send_callback()`.
+ *
+ * .. note::
+ *
+ * The |length| may be very small. If that is the case, and
+ * application disables Nagle algorithm (``TCP_NODELAY``), then just
+ * writing |data| to the network stack leads to very small packet,
+ * and it is very inefficient. An application should be responsible
+ * to buffer up small chunks of data as necessary to avoid this
+ * situation.
+ */
+typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session,
+ const uint8_t *data, size_t length,
+ int flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is
+ * used in :type:`nghttp2_data_source_read_callback` to send complete
+ * DATA frame.
+ *
+ * The |frame| is a DATA frame to send. The |framehd| is the
+ * serialized frame header (9 bytes). The |length| is the length of
+ * application data to send (this does not include padding). The
+ * |source| is the same pointer passed to
+ * :type:`nghttp2_data_source_read_callback`.
+ *
+ * The application first must send frame header |framehd| of length 9
+ * bytes. If ``frame->data.padlen > 0``, send 1 byte of value
+ * ``frame->data.padlen - 1``. Then send exactly |length| bytes of
+ * application data. Finally, if ``frame->data.padlen > 1``, send
+ * ``frame->data.padlen - 1`` bytes of zero as padding.
+ *
+ * The application has to send complete DATA frame in this callback.
+ * If all data were written successfully, return 0.
+ *
+ * If it cannot send any data at all, just return
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`; the library will call this callback
+ * with the same parameters later (It is recommended to send complete
+ * DATA frame at once in this function to deal with error; if partial
+ * frame data has already sent, it is impossible to send another data
+ * in that state, and all we can do is tear down connection). When
+ * data is fully processed, but application wants to make
+ * `nghttp2_session_mem_send()` or `nghttp2_session_send()` return
+ * immediately without processing next frames, return
+ * :enum:`NGHTTP2_ERR_PAUSE`. If application decided to reset this
+ * stream, return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then
+ * the library will send RST_STREAM with INTERNAL_ERROR as error code.
+ * The application can also return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, which will result in
+ * connection closure. Returning any other value is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned.
+ */
+typedef int (*nghttp2_send_data_callback)(nghttp2_session *session,
+ nghttp2_frame *frame,
+ const uint8_t *framehd, size_t length,
+ nghttp2_data_source *source,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when |session| wants to receive data from
+ * the remote peer. The implementation of this function must read at
+ * most |length| bytes of data and store it in |buf|. The |flags| is
+ * currently not used and always 0. It must return the number of
+ * bytes written in |buf| if it succeeds. If it cannot read any
+ * single byte without blocking, it must return
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`. If it gets EOF before it reads any
+ * single byte, it must return :enum:`NGHTTP2_ERR_EOF`. For other
+ * errors, it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ * Returning 0 is treated as :enum:`NGHTTP2_ERR_WOULDBLOCK`. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * This callback is required if the application uses
+ * `nghttp2_session_recv()` to receive data from the remote endpoint.
+ * If the application uses solely `nghttp2_session_mem_recv()`
+ * instead, this callback function is unnecessary.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_recv_callback()`.
+ */
+typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf,
+ size_t length, int flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when a frame is received. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
+ * member of their data structure are always ``NULL`` and 0
+ * respectively. The header name/value pairs are emitted via
+ * :type:`nghttp2_on_header_callback`.
+ *
+ * For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
+ * called after stream is closed (see
+ * :type:`nghttp2_on_stream_close_callback`). The application should
+ * check that stream is still alive using its own stream management or
+ * :func:`nghttp2_session_get_stream_user_data()`.
+ *
+ * Only HEADERS and DATA frame can signal the end of incoming data.
+ * If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the
+ * |frame| is the last frame from the remote peer in this stream.
+ *
+ * This callback won't be called for CONTINUATION frames.
+ * HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero value is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_frame_recv_callback()`.
+ */
+typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is
+ * received. The error is indicated by the |lib_error_code|, which is
+ * one of the values defined in :type:`nghttp2_error`. When this
+ * callback function is invoked, the library automatically submits
+ * either RST_STREAM or GOAWAY frame. The |user_data| pointer is the
+ * third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
+ * member of their data structure are always ``NULL`` and 0
+ * respectively.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_invalid_frame_recv_callback()`.
+ */
+typedef int (*nghttp2_on_invalid_frame_recv_callback)(
+ nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a chunk of data in DATA frame is
+ * received. The |stream_id| is the stream ID this DATA frame belongs
+ * to. The |flags| is the flags of DATA frame which this data chunk
+ * is contained. ``(flags & NGHTTP2_FLAG_END_STREAM) != 0`` does not
+ * necessarily mean this chunk of data is the last one in the stream.
+ * You should use :type:`nghttp2_on_frame_recv_callback` to know all
+ * data frames are received. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * If the application uses `nghttp2_session_mem_recv()`, it can return
+ * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
+ * return without processing further input bytes. The memory by
+ * pointed by the |data| is retained until
+ * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called.
+ * The application must retain the input bytes which was used to
+ * produce the |data| parameter, because it may refer to the memory
+ * region included in the input bytes.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error, and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_data_chunk_recv_callback()`.
+ */
+typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session,
+ uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *data,
+ size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked just before the non-DATA frame |frame| is
+ * sent. The |user_data| pointer is the third argument passed in to
+ * the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * It can also return :enum:`NGHTTP2_ERR_CANCEL` to cancel the
+ * transmission of the given frame.
+ *
+ * If there is a fatal error while executing this callback, the
+ * implementation should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`,
+ * which makes `nghttp2_session_send()` and
+ * `nghttp2_session_mem_send()` functions immediately return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * If the other value is returned, it is treated as if
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. But the
+ * implementation should not rely on this since the library may define
+ * new return value to extend its capability.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_before_frame_send_callback()`.
+ */
+typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked after the frame |frame| is sent. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_frame_send_callback()`.
+ */
+typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked after the non-DATA frame |frame| is not
+ * sent because of the error. The error is indicated by the
+ * |lib_error_code|, which is one of the values defined in
+ * :type:`nghttp2_error`. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * `nghttp2_session_get_stream_user_data()` can be used to get
+ * associated data.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_frame_not_send_callback()`.
+ */
+typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ int lib_error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the stream |stream_id| is closed.
+ * The reason of closure is indicated by the |error_code|. The
+ * |error_code| is usually one of :enum:`nghttp2_error_code`, but that
+ * is not guaranteed. The stream_user_data, which was specified in
+ * `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still
+ * available in this function. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * This function is also called for a stream in reserved state.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()`, `nghttp2_session_mem_recv()`,
+ * `nghttp2_session_send()`, and `nghttp2_session_mem_send()`
+ * functions immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_stream_close_callback()`.
+ */
+typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session,
+ int32_t stream_id,
+ uint32_t error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the reception of header block in
+ * HEADERS or PUSH_PROMISE is started. Each header name/value pair
+ * will be emitted by :type:`nghttp2_on_header_callback`.
+ *
+ * The ``frame->hd.flags`` may not have
+ * :enum:`NGHTTP2_FLAG_END_HEADERS` flag set, which indicates that one
+ * or more CONTINUATION frames are involved. But the application does
+ * not need to care about that because the header name/value pairs are
+ * emitted transparently regardless of CONTINUATION frames.
+ *
+ * The server applications probably create an object to store
+ * information about new stream if ``frame->hd.type ==
+ * NGHTTP2_HEADERS`` and ``frame->headers.cat ==
+ * NGHTTP2_HCAT_REQUEST``. If |session| is configured as server side,
+ * ``frame->headers.cat`` is either ``NGHTTP2_HCAT_REQUEST``
+ * containing request headers or ``NGHTTP2_HCAT_HEADERS`` containing
+ * trailer fields and never get PUSH_PROMISE in this callback.
+ *
+ * For the client applications, ``frame->hd.type`` is either
+ * ``NGHTTP2_HEADERS`` or ``NGHTTP2_PUSH_PROMISE``. In case of
+ * ``NGHTTP2_HEADERS``, ``frame->headers.cat ==
+ * NGHTTP2_HCAT_RESPONSE`` means that it is the first response
+ * headers, but it may be non-final response which is indicated by 1xx
+ * status code. In this case, there may be zero or more HEADERS frame
+ * with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS`` which has
+ * non-final response code and finally client gets exactly one HEADERS
+ * frame with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS``
+ * containing final response headers (non-1xx status code). The
+ * trailer fields also has ``frame->headers.cat ==
+ * NGHTTP2_HCAT_HEADERS`` which does not contain any status code.
+ *
+ * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
+ * the stream (promised stream if frame is PUSH_PROMISE) by issuing
+ * RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,
+ * :type:`nghttp2_on_header_callback` and
+ * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a
+ * different error code is desirable, use
+ * `nghttp2_submit_rst_stream()` with a desired error code and then
+ * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use
+ * ``frame->push_promise.promised_stream_id`` as stream_id parameter
+ * in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * It can return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` to
+ * reset the stream (promised stream if frame is PUSH_PROMISE). For
+ * critical errors, it must return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the other value is
+ * returned, it is treated as if :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * is returned. If :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
+ * `nghttp2_session_mem_recv()` function will immediately return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_begin_headers_callback()`.
+ */
+typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a header name/value pair is received
+ * for the |frame|. The |name| of length |namelen| is header name.
+ * The |value| of length |valuelen| is header value. The |flags| is
+ * bitwise OR of one or more of :type:`nghttp2_nv_flag`.
+ *
+ * If :enum:`NGHTTP2_NV_FLAG_NO_INDEX` is set in |flags|, the receiver
+ * must not index this name/value pair when forwarding it to the next
+ * hop. More specifically, "Literal Header Field never Indexed"
+ * representation must be used in HPACK encoding.
+ *
+ * When this callback is invoked, ``frame->hd.type`` is either
+ * :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`. After all
+ * header name/value pairs are processed with this callback, and no
+ * error has been detected, :type:`nghttp2_on_frame_recv_callback`
+ * will be invoked. If there is an error in decompression,
+ * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be
+ * invoked.
+ *
+ * Both |name| and |value| are guaranteed to be NULL-terminated. The
+ * |namelen| and |valuelen| do not include terminal NULL. If
+ * `nghttp2_option_set_no_http_messaging()` is used with nonzero
+ * value, NULL character may be included in |name| or |value| before
+ * terminating NULL.
+ *
+ * Please note that unless `nghttp2_option_set_no_http_messaging()` is
+ * used, nghttp2 library does perform validation against the |name|
+ * and the |value| using `nghttp2_check_header_name()` and
+ * `nghttp2_check_header_value()`. In addition to this, nghttp2
+ * performs validation based on HTTP Messaging rule, which is briefly
+ * explained in :ref:`http-messaging` section.
+ *
+ * If the application uses `nghttp2_session_mem_recv()`, it can return
+ * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
+ * return without processing further input bytes. The memory pointed
+ * by |frame|, |name| and |value| parameters are retained until
+ * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called.
+ * The application must retain the input bytes which was used to
+ * produce these parameters, because it may refer to the memory region
+ * included in the input bytes.
+ *
+ * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
+ * the stream (promised stream if frame is PUSH_PROMISE) by issuing
+ * RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,
+ * :type:`nghttp2_on_header_callback` and
+ * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a
+ * different error code is desirable, use
+ * `nghttp2_submit_rst_stream()` with a desired error code and then
+ * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use
+ * ``frame->push_promise.promised_stream_id`` as stream_id parameter
+ * in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * It may return :enum:`NGHTTP2_ERR_PAUSE` or
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. For other critical
+ * failures, it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If
+ * the other nonzero value is returned, it is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_header_callback()`.
+ *
+ * .. warning::
+ *
+ * Application should properly limit the total buffer size to store
+ * incoming header fields. Without it, peer may send large number
+ * of header fields or large header fields to cause out of memory in
+ * local endpoint. Due to how HPACK works, peer can do this
+ * effectively without using much memory on their own.
+ */
+typedef int (*nghttp2_on_header_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a header name/value pair is received
+ * for the |frame|. The |name| is header name. The |value| is header
+ * value. The |flags| is bitwise OR of one or more of
+ * :type:`nghttp2_nv_flag`.
+ *
+ * This callback behaves like :type:`nghttp2_on_header_callback`,
+ * except that |name| and |value| are stored in reference counted
+ * buffer. If application wishes to keep these references without
+ * copying them, use `nghttp2_rcbuf_incref()` to increment their
+ * reference count. It is the application's responsibility to call
+ * `nghttp2_rcbuf_decref()` if they called `nghttp2_rcbuf_incref()` so
+ * as not to leak memory. If the |session| is created by
+ * `nghttp2_session_server_new3()` or `nghttp2_session_client_new3()`,
+ * the function to free memory is the one belongs to the mem
+ * parameter. As long as this free function alives, |name| and
+ * |value| can live after |session| was destroyed.
+ */
+typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ nghttp2_rcbuf *name,
+ nghttp2_rcbuf *value, uint8_t flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a invalid header name/value pair is
+ * received for the |frame|.
+ *
+ * The parameter and behaviour are similar to
+ * :type:`nghttp2_on_header_callback`. The difference is that this
+ * callback is only invoked when a invalid header name/value pair is
+ * received which is treated as stream error if this callback is not
+ * set. Only invalid regular header field are passed to this
+ * callback. In other words, invalid pseudo header field is not
+ * passed to this callback. Also header fields which includes upper
+ * cased latter are also treated as error without passing them to this
+ * callback.
+ *
+ * This callback is only considered if HTTP messaging validation is
+ * turned on (which is on by default, see
+ * `nghttp2_option_set_no_http_messaging()`).
+ *
+ * With this callback, application inspects the incoming invalid
+ * field, and it also can reset stream from this callback by returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
+ * error code is :enum:`NGHTTP2_PROTOCOL_ERROR`. To change the error
+ * code, call `nghttp2_submit_rst_stream()` with the error code of
+ * choice in addition to returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
+ *
+ * If 0 is returned, the header field is ignored, and the stream is
+ * not reset.
+ */
+typedef int (*nghttp2_on_invalid_header_callback)(
+ nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
+ size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a invalid header name/value pair is
+ * received for the |frame|.
+ *
+ * The parameter and behaviour are similar to
+ * :type:`nghttp2_on_header_callback2`. The difference is that this
+ * callback is only invoked when a invalid header name/value pair is
+ * received which is silently ignored if this callback is not set.
+ * Only invalid regular header field are passed to this callback. In
+ * other words, invalid pseudo header field is not passed to this
+ * callback. Also header fields which includes upper cased latter are
+ * also treated as error without passing them to this callback.
+ *
+ * This callback is only considered if HTTP messaging validation is
+ * turned on (which is on by default, see
+ * `nghttp2_option_set_no_http_messaging()`).
+ *
+ * With this callback, application inspects the incoming invalid
+ * field, and it also can reset stream from this callback by returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
+ * error code is :enum:`NGHTTP2_INTERNAL_ERROR`. To change the error
+ * code, call `nghttp2_submit_rst_stream()` with the error code of
+ * choice in addition to returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_invalid_header_callback2)(
+ nghttp2_session *session, const nghttp2_frame *frame, nghttp2_rcbuf *name,
+ nghttp2_rcbuf *value, uint8_t flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library asks application how
+ * many padding bytes are required for the transmission of the
+ * |frame|. The application must choose the total length of payload
+ * including padded bytes in range [frame->hd.length, max_payloadlen],
+ * inclusive. Choosing number not in this range will be treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Returning
+ * ``frame->hd.length`` means no padding is added. Returning
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_select_padding_callback()`.
+ */
+typedef ssize_t (*nghttp2_select_padding_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ size_t max_payloadlen,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library wants to get max length of
+ * data to send data to the remote peer. The implementation of this
+ * function should return a value in the following range. [1,
+ * min(|session_remote_window_size|, |stream_remote_window_size|,
+ * |remote_max_frame_size|)]. If a value greater than this range is
+ * returned than the max allow value will be used. Returning a value
+ * smaller than this range is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. The |frame_type| is provided
+ * for future extensibility and identifies the type of frame (see
+ * :type:`nghttp2_frame_type`) for which to get the length for.
+ * Currently supported frame types are: :enum:`NGHTTP2_DATA`.
+ *
+ * This callback can be used to control the length in bytes for which
+ * :type:`nghttp2_data_source_read_callback` is allowed to send to the
+ * remote endpoint. This callback is optional. Returning
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session
+ * failure.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_data_source_read_length_callback()`.
+ */
+typedef ssize_t (*nghttp2_data_source_read_length_callback)(
+ nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
+ int32_t session_remote_window_size, int32_t stream_remote_window_size,
+ uint32_t remote_max_frame_size, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a frame header is received. The
+ * |hd| points to received frame header.
+ *
+ * Unlike :type:`nghttp2_on_frame_recv_callback`, this callback will
+ * also be called when frame header of CONTINUATION frame is received.
+ *
+ * If both :type:`nghttp2_on_begin_frame_callback` and
+ * :type:`nghttp2_on_begin_headers_callback` are set and HEADERS or
+ * PUSH_PROMISE is received, :type:`nghttp2_on_begin_frame_callback`
+ * will be called first.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero value is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_begin_frame_callback()`.
+ */
+typedef int (*nghttp2_on_begin_frame_callback)(nghttp2_session *session,
+ const nghttp2_frame_hd *hd,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when chunk of extension frame payload is
+ * received. The |hd| points to frame header. The received
+ * chunk is |data| of length |len|.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ *
+ * To abort processing this extension frame, return
+ * :enum:`NGHTTP2_ERR_CANCEL`.
+ *
+ * If fatal error occurred, application should return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the
+ * other values are returned, currently they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_extension_chunk_recv_callback)(
+ nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data,
+ size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library asks the application to
+ * unpack extension payload from its wire format. The extension
+ * payload has been passed to the application using
+ * :type:`nghttp2_on_extension_chunk_recv_callback`. The frame header
+ * is already unpacked by the library and provided as |hd|.
+ *
+ * To receive extension frames, the application must tell desired
+ * extension frame type to the library using
+ * `nghttp2_option_set_user_recv_extension_type()`.
+ *
+ * The implementation of this function may store the pointer to the
+ * created object as a result of unpacking in |*payload|, and returns
+ * 0. The pointer stored in |*payload| is opaque to the library, and
+ * the library does not own its pointer. |*payload| is initialized as
+ * ``NULL``. The |*payload| is available as ``frame->ext.payload`` in
+ * :type:`nghttp2_on_frame_recv_callback`. Therefore if application
+ * can free that memory inside :type:`nghttp2_on_frame_recv_callback`
+ * callback. Of course, application has a liberty not ot use
+ * |*payload|, and do its own mechanism to process extension frames.
+ *
+ * To abort processing this extension frame, return
+ * :enum:`NGHTTP2_ERR_CANCEL`.
+ *
+ * If fatal error occurred, application should return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the
+ * other values are returned, currently they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_unpack_extension_callback)(nghttp2_session *session,
+ void **payload,
+ const nghttp2_frame_hd *hd,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library asks the application to pack
+ * extension payload in its wire format. The frame header will be
+ * packed by library. Application must pack payload only.
+ * ``frame->ext.payload`` is the object passed to
+ * `nghttp2_submit_extension()` as payload parameter. Application
+ * must pack extension payload to the |buf| of its capacity |len|
+ * bytes. The |len| is at least 16KiB.
+ *
+ * The implementation of this function should return the number of
+ * bytes written into |buf| when it succeeds.
+ *
+ * To abort processing this extension frame, return
+ * :enum:`NGHTTP2_ERR_CANCEL`, and
+ * :type:`nghttp2_on_frame_not_send_callback` will be invoked.
+ *
+ * If fatal error occurred, application should return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the
+ * other values are returned, currently they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the return value is
+ * strictly larger than |len|, it is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
+ uint8_t *buf, size_t len,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library provides the error message
+ * intended for human consumption. This callback is solely for
+ * debugging purpose. The |msg| is typically NULL-terminated string
+ * of length |len|. |len| does not include the sentinel NULL
+ * character.
+ *
+ * This function is deprecated. The new application should use
+ * :type:`nghttp2_error_callback2`.
+ *
+ * The format of error message may change between nghttp2 library
+ * versions. The application should not depend on the particular
+ * format.
+ *
+ * Normally, application should return 0 from this callback. If fatal
+ * error occurred while doing something in this callback, application
+ * should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * library will return immediately with return value
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
+ * is returned from this callback, they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
+ * rely on this details.
+ */
+typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg,
+ size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library provides the error code, and
+ * message. This callback is solely for debugging purpose.
+ * |lib_error_code| is one of error code defined in
+ * :enum:`nghttp2_error`. The |msg| is typically NULL-terminated
+ * string of length |len|, and intended for human consumption. |len|
+ * does not include the sentinel NULL character.
+ *
+ * The format of error message may change between nghttp2 library
+ * versions. The application should not depend on the particular
+ * format.
+ *
+ * Normally, application should return 0 from this callback. If fatal
+ * error occurred while doing something in this callback, application
+ * should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * library will return immediately with return value
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
+ * is returned from this callback, they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
+ * rely on this details.
+ */
+typedef int (*nghttp2_error_callback2)(nghttp2_session *session,
+ int lib_error_code, const char *msg,
+ size_t len, void *user_data);
+
+struct nghttp2_session_callbacks;
+
+/**
+ * @struct
+ *
+ * Callback functions for :type:`nghttp2_session`. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_session_callbacks nghttp2_session_callbacks;
+
+/**
+ * @function
+ *
+ * Initializes |*callbacks_ptr| with NULL values.
+ *
+ * The initialized object can be used when initializing multiple
+ * :type:`nghttp2_session` objects.
+ *
+ * When the application finished using this object, it can use
+ * `nghttp2_session_callbacks_del()` to free its memory.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |callbacks|. If |callbacks| is
+ * ``NULL``, this function does nothing.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a session wants to send data to
+ * the remote peer. This callback is not necessary if the application
+ * uses solely `nghttp2_session_mem_send()` to serialize data to
+ * transmit.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the a session wants to receive
+ * data from the remote peer. This callback is not necessary if the
+ * application uses solely `nghttp2_session_mem_recv()` to process
+ * received data.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when a frame is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_recv_callback on_frame_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is
+ * received.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a chunk of data in DATA frame
+ * is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked before a non-DATA frame is sent.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_before_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_before_frame_send_callback before_frame_send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked after a frame is sent.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_send_callback on_frame_send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a non-DATA frame is not sent
+ * because of an error.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_not_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the stream is closed.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_stream_close_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_stream_close_callback on_stream_close_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the reception of header block
+ * in HEADERS or PUSH_PROMISE is started.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_headers_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_headers_callback on_begin_headers_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a header name/value pair is
+ * received. If both
+ * `nghttp2_session_callbacks_set_on_header_callback()` and
+ * `nghttp2_session_callbacks_set_on_header_callback2()` are used to
+ * set callbacks, the latter has the precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback on_header_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a header name/value pair is
+ * received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback2 on_header_callback2);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a invalid header name/value
+ * pair is received. If both
+ * `nghttp2_session_callbacks_set_on_invalid_header_callback()` and
+ * `nghttp2_session_callbacks_set_on_invalid_header_callback2()` are
+ * used to set callbacks, the latter takes the precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback on_invalid_header_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a invalid header name/value
+ * pair is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the library asks application
+ * how many padding bytes are required for the transmission of the
+ * given frame.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_select_padding_callback select_padding_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function determine the length allowed in
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_set_data_source_read_length_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_data_source_read_length_callback data_source_read_length_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a frame header is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_frame_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_frame_callback on_begin_frame_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when
+ * :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is used in
+ * :type:`nghttp2_data_source_read_callback` to avoid data copy.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_data_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_send_data_callback send_data_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the library asks the
+ * application to pack extension frame payload in wire format.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_pack_extension_callback pack_extension_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the library asks the
+ * application to unpack extension frame payload from wire format.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_unpack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_unpack_extension_callback unpack_extension_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when chunk of extension frame
+ * payload is received.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when library tells error message to
+ * the application.
+ *
+ * This function is deprecated. The new application should use
+ * `nghttp2_session_callbacks_set_error_callback2()`.
+ *
+ * If both :type:`nghttp2_error_callback` and
+ * :type:`nghttp2_error_callback2` are set, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when library tells error code, and
+ * message to the application.
+ *
+ * If both :type:`nghttp2_error_callback` and
+ * :type:`nghttp2_error_callback2` are set, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback2(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace malloc(). The |mem_user_data|
+ * is the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void *(*nghttp2_malloc)(size_t size, void *mem_user_data);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace free(). The |mem_user_data| is
+ * the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void (*nghttp2_free)(void *ptr, void *mem_user_data);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace calloc(). The |mem_user_data|
+ * is the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void *(*nghttp2_calloc)(size_t nmemb, size_t size, void *mem_user_data);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace realloc(). The |mem_user_data|
+ * is the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void *(*nghttp2_realloc)(void *ptr, size_t size, void *mem_user_data);
+
+/**
+ * @struct
+ *
+ * Custom memory allocator functions and user defined pointer. The
+ * |mem_user_data| member is passed to each allocator function. This
+ * can be used, for example, to achieve per-session memory pool.
+ *
+ * In the following example code, ``my_malloc``, ``my_free``,
+ * ``my_calloc`` and ``my_realloc`` are the replacement of the
+ * standard allocators ``malloc``, ``free``, ``calloc`` and
+ * ``realloc`` respectively::
+ *
+ * void *my_malloc_cb(size_t size, void *mem_user_data) {
+ * return my_malloc(size);
+ * }
+ *
+ * void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); }
+ *
+ * void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) {
+ * return my_calloc(nmemb, size);
+ * }
+ *
+ * void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) {
+ * return my_realloc(ptr, size);
+ * }
+ *
+ * void session_new() {
+ * nghttp2_session *session;
+ * nghttp2_session_callbacks *callbacks;
+ * nghttp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb,
+ * my_realloc_cb};
+ *
+ * ...
+ *
+ * nghttp2_session_client_new3(&session, callbacks, NULL, NULL, &mem);
+ *
+ * ...
+ * }
+ */
+typedef struct {
+ /**
+ * An arbitrary user supplied data. This is passed to each
+ * allocator function.
+ */
+ void *mem_user_data;
+ /**
+ * Custom allocator function to replace malloc().
+ */
+ nghttp2_malloc malloc;
+ /**
+ * Custom allocator function to replace free().
+ */
+ nghttp2_free free;
+ /**
+ * Custom allocator function to replace calloc().
+ */
+ nghttp2_calloc calloc;
+ /**
+ * Custom allocator function to replace realloc().
+ */
+ nghttp2_realloc realloc;
+} nghttp2_mem;
+
+struct nghttp2_option;
+
+/**
+ * @struct
+ *
+ * Configuration options for :type:`nghttp2_session`. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_option nghttp2_option;
+
+/**
+ * @function
+ *
+ * Initializes |*option_ptr| with default values.
+ *
+ * When the application finished using this object, it can use
+ * `nghttp2_option_del()` to free its memory.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_option_new(nghttp2_option **option_ptr);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |option|. If |option| is
+ * ``NULL``, this function does nothing.
+ */
+NGHTTP2_EXTERN void nghttp2_option_del(nghttp2_option *option);
+
+/**
+ * @function
+ *
+ * This option prevents the library from sending WINDOW_UPDATE for a
+ * connection automatically. If this option is set to nonzero, the
+ * library won't send WINDOW_UPDATE for DATA until application calls
+ * `nghttp2_session_consume()` to indicate the consumed amount of
+ * data. Don't use `nghttp2_submit_window_update()` for this purpose.
+ * By default, this option is set to zero.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val);
+
+/**
+ * @function
+ *
+ * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
+ * remote endpoint as if it is received in SETTINGS frame. Without
+ * specifying this option, before the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
+ * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
+ * cause problem if local endpoint submits lots of requests initially
+ * and sending them at once to the remote peer may lead to the
+ * rejection of some requests. Specifying this option to the sensible
+ * value, say 100, may avoid this kind of issue. This value will be
+ * overwritten if the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
+ uint32_t val);
+
+/**
+ * @function
+ *
+ * By default, nghttp2 library, if configured as server, requires
+ * first 24 bytes of client magic byte string (MAGIC). In most cases,
+ * this will simplify the implementation of server. But sometimes
+ * server may want to detect the application protocol based on first
+ * few bytes on clear text communication.
+ *
+ * If this option is used with nonzero |val|, nghttp2 library does not
+ * handle MAGIC. It still checks following SETTINGS frame. This
+ * means that applications should deal with MAGIC by themselves.
+ *
+ * If this option is not used or used with zero value, if MAGIC does
+ * not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()`
+ * and `nghttp2_session_mem_recv()` will return error
+ * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal error.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val);
+
+/**
+ * @function
+ *
+ * By default, nghttp2 library enforces subset of HTTP Messaging rules
+ * described in `HTTP/2 specification, section 8
+ * `_. See
+ * :ref:`http-messaging` section for details. For those applications
+ * who use nghttp2 library as non-HTTP use, give nonzero to |val| to
+ * disable this enforcement. Please note that disabling this feature
+ * does not change the fundamental client and server model of HTTP.
+ * That is, even if the validation is disabled, only client can send
+ * requests.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_http_messaging(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
+ * RFC 7540 does not enforce any limit on the number of incoming
+ * reserved streams (in RFC 7540 terms, streams in reserved (remote)
+ * state). This only affects client side, since only server can push
+ * streams. Malicious server can push arbitrary number of streams,
+ * and make client's memory exhausted. This option can set the
+ * maximum number of such incoming streams to avoid possible memory
+ * exhaustion. If this option is set, and pushed streams are
+ * automatically closed on reception, without calling user provided
+ * callback, if they exceed the given limit. The default value is
+ * 200. If session is configured as server side, this option has no
+ * effect. Server can control the number of streams to push.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
+ uint32_t val);
+
+/**
+ * @function
+ *
+ * Sets extension frame type the application is willing to handle with
+ * user defined callbacks (see
+ * :type:`nghttp2_on_extension_chunk_recv_callback` and
+ * :type:`nghttp2_unpack_extension_callback`). The |type| is
+ * extension frame type, and must be strictly greater than 0x9.
+ * Otherwise, this function does nothing. The application can call
+ * this function multiple times to set more than one frame type to
+ * receive. The application does not have to call this function if it
+ * just sends extension frames.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
+ uint8_t type);
+
+/**
+ * @function
+ *
+ * Sets extension frame type the application is willing to receive
+ * using builtin handler. The |type| is the extension frame type to
+ * receive, and must be strictly greater than 0x9. Otherwise, this
+ * function does nothing. The application can call this function
+ * multiple times to set more than one frame type to receive. The
+ * application does not have to call this function if it just sends
+ * extension frames.
+ *
+ * If same frame type is passed to both
+ * `nghttp2_option_set_builtin_recv_extension_type()` and
+ * `nghttp2_option_set_user_recv_extension_type()`, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
+ uint8_t type);
+
+/**
+ * @function
+ *
+ * This option prevents the library from sending PING frame with ACK
+ * flag set automatically when PING frame without ACK flag set is
+ * received. If this option is set to nonzero, the library won't send
+ * PING frame with ACK flag set in the response for incoming PING
+ * frame. The application can send PING frame with ACK flag set using
+ * `nghttp2_submit_ping()` with :enum:`NGHTTP2_FLAG_ACK` as flags
+ * parameter.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
+ * This option sets the maximum length of header block (a set of
+ * header fields per one HEADERS frame) to send. The length of a
+ * given set of header fields is calculated using
+ * `nghttp2_hd_deflate_bound()`. The default value is 64KiB. If
+ * application attempts to send header fields larger than this limit,
+ * the transmission of the frame fails with error code
+ * :enum:`NGHTTP2_ERR_FRAME_SIZE_ERROR`.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_send_header_block_length(nghttp2_option *option,
+ size_t val);
+
+/**
+ * @function
+ *
+ * This option sets the maximum dynamic table size for deflating
+ * header fields. The default value is 4KiB. In HTTP/2, receiver of
+ * deflated header block can specify maximum dynamic table size. The
+ * actual maximum size is the minimum of the size receiver specified
+ * and this option value.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
+ size_t val);
+
+/**
+ * @function
+ *
+ * This option prevents the library from retaining closed streams to
+ * maintain the priority tree. If this option is set to nonzero,
+ * applications can discard closed stream completely to save memory.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
+ * Initializes |*session_ptr| for client use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+ * does not store |callbacks|. The |user_data| is an arbitrary user
+ * supplied data, which will be passed to the callback functions.
+ *
+ * The :type:`nghttp2_send_callback` must be specified. If the
+ * application code uses `nghttp2_session_recv()`, the
+ * :type:`nghttp2_recv_callback` must be specified. The other members
+ * of |callbacks| can be ``NULL``.
+ *
+ * If this function fails, |*session_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_client_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * Initializes |*session_ptr| for server use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+ * does not store |callbacks|. The |user_data| is an arbitrary user
+ * supplied data, which will be passed to the callback functions.
+ *
+ * The :type:`nghttp2_send_callback` must be specified. If the
+ * application code uses `nghttp2_session_recv()`, the
+ * :type:`nghttp2_recv_callback` must be specified. The other members
+ * of |callbacks| can be ``NULL``.
+ *
+ * If this function fails, |*session_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_server_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_client_new()`, but with additional options
+ * specified in the |option|.
+ *
+ * The |option| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_client_new()`.
+ *
+ * This function does not take ownership |option|. The application is
+ * responsible for freeing |option| if it finishes using the object.
+ *
+ * The library code does not refer to |option| after this function
+ * returns.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_client_new2(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_server_new()`, but with additional options
+ * specified in the |option|.
+ *
+ * The |option| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_server_new()`.
+ *
+ * This function does not take ownership |option|. The application is
+ * responsible for freeing |option| if it finishes using the object.
+ *
+ * The library code does not refer to |option| after this function
+ * returns.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_server_new2(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_client_new2()`, but with additional custom
+ * memory allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_client_new2()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_client_new3(
+ nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option, nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_server_new2()`, but with additional custom
+ * memory allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_server_new2()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_server_new3(
+ nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option, nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |session|. If |session| is
+ * ``NULL``, this function does nothing.
+ */
+NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Sends pending frames to the remote peer.
+ *
+ * This function retrieves the highest prioritized frame from the
+ * outbound queue and sends it to the remote peer. It does this as
+ * many as possible until the user callback
+ * :type:`nghttp2_send_callback` returns
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty.
+ * This function calls several callback functions which are passed
+ * when initializing the |session|. Here is the simple time chart
+ * which tells when each callback is invoked:
+ *
+ * 1. Get the next frame to send from outbound queue.
+ *
+ * 2. Prepare transmission of the frame.
+ *
+ * 3. If the control frame cannot be sent because some preconditions
+ * are not met (e.g., request HEADERS cannot be sent after GOAWAY),
+ * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort
+ * the following steps.
+ *
+ * 4. If the frame is HEADERS, PUSH_PROMISE or DATA,
+ * :type:`nghttp2_select_padding_callback` is invoked.
+ *
+ * 5. If the frame is request HEADERS, the stream is opened here.
+ *
+ * 6. :type:`nghttp2_before_frame_send_callback` is invoked.
+ *
+ * 7. If :enum:`NGHTTP2_ERR_CANCEL` is returned from
+ * :type:`nghttp2_before_frame_send_callback`, the current frame
+ * transmission is canceled, and
+ * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort
+ * the following steps.
+ *
+ * 8. :type:`nghttp2_send_callback` is invoked one or more times to
+ * send the frame.
+ *
+ * 9. :type:`nghttp2_on_frame_send_callback` is invoked.
+ *
+ * 10. If the transmission of the frame triggers closure of the
+ * stream, the stream is closed and
+ * :type:`nghttp2_on_stream_close_callback` is invoked.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * The callback function failed.
+ */
+NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the serialized data to send.
+ *
+ * This function behaves like `nghttp2_session_send()` except that it
+ * does not use :type:`nghttp2_send_callback` to transmit data.
+ * Instead, it assigns the pointer to the serialized data to the
+ * |*data_ptr| and returns its length. The other callbacks are called
+ * in the same way as they are in `nghttp2_session_send()`.
+ *
+ * If no data is available to send, this function returns 0.
+ *
+ * This function may not return all serialized data in one invocation.
+ * To get all data, call this function repeatedly until it returns 0
+ * or one of negative error codes.
+ *
+ * The assigned |*data_ptr| is valid until the next call of
+ * `nghttp2_session_mem_send()` or `nghttp2_session_send()`.
+ *
+ * The caller must send all data before sending the next chunk of
+ * data.
+ *
+ * This function returns the length of the data pointed by the
+ * |*data_ptr| if it succeeds, or one of the following negative error
+ * codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ *
+ * .. note::
+ *
+ * This function may produce very small byte string. If that is the
+ * case, and application disables Nagle algorithm (``TCP_NODELAY``),
+ * then writing this small chunk leads to very small packet, and it
+ * is very inefficient. An application should be responsible to
+ * buffer up small chunks of data as necessary to avoid this
+ * situation.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session,
+ const uint8_t **data_ptr);
+
+/**
+ * @function
+ *
+ * Receives frames from the remote peer.
+ *
+ * This function receives as many frames as possible until the user
+ * callback :type:`nghttp2_recv_callback` returns
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`. This function calls several
+ * callback functions which are passed when initializing the
+ * |session|. Here is the simple time chart which tells when each
+ * callback is invoked:
+ *
+ * 1. :type:`nghttp2_recv_callback` is invoked one or more times to
+ * receive frame header.
+ *
+ * 2. When frame header is received,
+ * :type:`nghttp2_on_begin_frame_callback` is invoked.
+ *
+ * 3. If the frame is DATA frame:
+ *
+ * 1. :type:`nghttp2_recv_callback` is invoked to receive DATA
+ * payload. For each chunk of data,
+ * :type:`nghttp2_on_data_chunk_recv_callback` is invoked.
+ *
+ * 2. If one DATA frame is completely received,
+ * :type:`nghttp2_on_frame_recv_callback` is invoked. If the
+ * reception of the frame triggers the closure of the stream,
+ * :type:`nghttp2_on_stream_close_callback` is invoked.
+ *
+ * 4. If the frame is the control frame:
+ *
+ * 1. :type:`nghttp2_recv_callback` is invoked one or more times to
+ * receive whole frame.
+ *
+ * 2. If the received frame is valid, then following actions are
+ * taken. If the frame is either HEADERS or PUSH_PROMISE,
+ * :type:`nghttp2_on_begin_headers_callback` is invoked. Then
+ * :type:`nghttp2_on_header_callback` is invoked for each header
+ * name/value pair. For invalid header field,
+ * :type:`nghttp2_on_invalid_header_callback` is called. After
+ * all name/value pairs are emitted successfully,
+ * :type:`nghttp2_on_frame_recv_callback` is invoked. For other
+ * frames, :type:`nghttp2_on_frame_recv_callback` is invoked.
+ * If the reception of the frame triggers the closure of the
+ * stream, :type:`nghttp2_on_stream_close_callback` is invoked.
+ *
+ * 3. If the received frame is unpacked but is interpreted as
+ * invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is
+ * invoked.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_EOF`
+ * The remote peer did shutdown on the connection.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * The callback function failed.
+ * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`
+ * Invalid client magic was detected. This error only returns
+ * when |session| was configured as server and
+ * `nghttp2_option_set_no_recv_client_magic()` is not used with
+ * nonzero value.
+ * :enum:`NGHTTP2_ERR_FLOODED`
+ * Flooding was detected in this HTTP/2 session, and it must be
+ * closed. This is most likely caused by misbehaviour of peer.
+ */
+NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Processes data |in| as an input from the remote endpoint. The
+ * |inlen| indicates the number of bytes in the |in|.
+ *
+ * This function behaves like `nghttp2_session_recv()` except that it
+ * does not use :type:`nghttp2_recv_callback` to receive data; the
+ * |in| is the only data for the invocation of this function. If all
+ * bytes are processed, this function returns. The other callbacks
+ * are called in the same way as they are in `nghttp2_session_recv()`.
+ *
+ * In the current implementation, this function always tries to
+ * processes all input data unless either an error occurs or
+ * :enum:`NGHTTP2_ERR_PAUSE` is returned from
+ * :type:`nghttp2_on_header_callback` or
+ * :type:`nghttp2_on_data_chunk_recv_callback`. If
+ * :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the
+ * number of bytes which was used to produce the data or frame for the
+ * callback.
+ *
+ * This function returns the number of processed bytes, or one of the
+ * following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * The callback function failed.
+ * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`
+ * Invalid client magic was detected. This error only returns
+ * when |session| was configured as server and
+ * `nghttp2_option_set_no_recv_client_magic()` is not used with
+ * nonzero value.
+ * :enum:`NGHTTP2_ERR_FLOODED`
+ * Flooding was detected in this HTTP/2 session, and it must be
+ * closed. This is most likely caused by misbehaviour of peer.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
+ const uint8_t *in,
+ size_t inlen);
+
+/**
+ * @function
+ *
+ * Puts back previously deferred DATA frame in the stream |stream_id|
+ * to the outbound queue.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The stream does not exist; or no deferred data exist.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_resume_data(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns nonzero value if |session| wants to receive data from the
+ * remote peer.
+ *
+ * If both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0, the application should
+ * drop the connection.
+ */
+NGHTTP2_EXTERN int nghttp2_session_want_read(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero value if |session| wants to send data to the remote
+ * peer.
+ *
+ * If both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0, the application should
+ * drop the connection.
+ */
+NGHTTP2_EXTERN int nghttp2_session_want_write(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns stream_user_data for the stream |stream_id|. The
+ * stream_user_data is provided by `nghttp2_submit_request()`,
+ * `nghttp2_submit_headers()` or
+ * `nghttp2_session_set_stream_user_data()`. Unless it is set using
+ * `nghttp2_session_set_stream_user_data()`, if the stream is
+ * initiated by the remote endpoint, stream_user_data is always
+ * ``NULL``. If the stream does not exist, this function returns
+ * ``NULL``.
+ */
+NGHTTP2_EXTERN void *
+nghttp2_session_get_stream_user_data(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Sets the |stream_user_data| to the stream denoted by the
+ * |stream_id|. If a stream user data is already set to the stream,
+ * it is replaced with the |stream_user_data|. It is valid to specify
+ * ``NULL`` in the |stream_user_data|, which nullifies the associated
+ * data pointer.
+ *
+ * It is valid to set the |stream_user_data| to the stream reserved by
+ * PUSH_PROMISE frame.
+ *
+ * This function returns 0 if it succeeds, or one of following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The stream does not exist
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_set_stream_user_data(nghttp2_session *session,
+ int32_t stream_id, void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Sets |user_data| to |session|, overwriting the existing user data
+ * specified in `nghttp2_session_client_new()`, or
+ * `nghttp2_session_server_new()`.
+ */
+NGHTTP2_EXTERN void nghttp2_session_set_user_data(nghttp2_session *session,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * Returns the number of frames in the outbound queue. This does not
+ * include the deferred DATA frames.
+ */
+NGHTTP2_EXTERN size_t
+nghttp2_session_get_outbound_queue_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the number of DATA payload in bytes received without
+ * WINDOW_UPDATE transmission for the stream |stream_id|. The local
+ * (receive) window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective data length. In particular, if the
+ * local window size is reduced by submitting negative
+ * window_size_increment with `nghttp2_submit_window_update()`, this
+ * function returns the number of bytes less than actually received.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_recv_data_length(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the local (receive) window size for the stream |stream_id|.
+ * The local window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective window size.
+ *
+ * This function does not take into account the amount of received
+ * data from the remote endpoint. Use
+ * `nghttp2_session_get_stream_local_window_size()` to know the amount
+ * of data the remote endpoint can send without receiving stream level
+ * WINDOW_UPDATE frame. Note that each stream is still subject to the
+ * connection level flow control.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_local_window_size(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the amount of flow-controlled payload (e.g., DATA) that the
+ * remote endpoint can send without receiving stream level
+ * WINDOW_UPDATE frame. It is also subject to the connection level
+ * flow control. So the actual amount of data to send is
+ * min(`nghttp2_session_get_stream_local_window_size()`,
+ * `nghttp2_session_get_local_window_size()`).
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_local_window_size(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the number of DATA payload in bytes received without
+ * WINDOW_UPDATE transmission for a connection. The local (receive)
+ * window size can be adjusted by `nghttp2_submit_window_update()`.
+ * This function takes into account that and returns effective data
+ * length. In particular, if the local window size is reduced by
+ * submitting negative window_size_increment with
+ * `nghttp2_submit_window_update()`, this function returns the number
+ * of bytes less than actually received.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_effective_recv_data_length(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the local (receive) window size for a connection. The
+ * local window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective window size.
+ *
+ * This function does not take into account the amount of received
+ * data from the remote endpoint. Use
+ * `nghttp2_session_get_local_window_size()` to know the amount of
+ * data the remote endpoint can send without receiving
+ * connection-level WINDOW_UPDATE frame. Note that each stream is
+ * still subject to the stream level flow control.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_effective_local_window_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the amount of flow-controlled payload (e.g., DATA) that the
+ * remote endpoint can send without receiving connection level
+ * WINDOW_UPDATE frame. Note that each stream is still subject to the
+ * stream level flow control (see
+ * `nghttp2_session_get_stream_local_window_size()`).
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_local_window_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the remote window size for a given stream |stream_id|.
+ *
+ * This is the amount of flow-controlled payload (e.g., DATA) that the
+ * local endpoint can send without stream level WINDOW_UPDATE. There
+ * is also connection level flow control, so the effective size of
+ * payload that the local endpoint can actually send is
+ * min(`nghttp2_session_get_stream_remote_window_size()`,
+ * `nghttp2_session_get_remote_window_size()`).
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_remote_window_size(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the remote window size for a connection.
+ *
+ * This function always succeeds.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_remote_window_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns 1 if local peer half closed the given stream |stream_id|.
+ * Returns 0 if it did not. Returns -1 if no such stream exists.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_get_stream_local_close(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns 1 if remote peer half closed the given stream |stream_id|.
+ * Returns 0 if it did not. Returns -1 if no such stream exists.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_get_stream_remote_close(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the current dynamic table size of HPACK inflater, including
+ * the overhead 32 bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN size_t
+nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the current dynamic table size of HPACK deflater including
+ * the overhead 32 bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN size_t
+nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Signals the session so that the connection should be terminated.
+ *
+ * The last stream ID is the minimum value between the stream ID of a
+ * stream for which :type:`nghttp2_on_frame_recv_callback` was called
+ * most recently and the last stream ID we have sent to the peer
+ * previously.
+ *
+ * The |error_code| is the error code of this GOAWAY frame. The
+ * pre-defined error code is one of :enum:`nghttp2_error_code`.
+ *
+ * After the transmission, both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0.
+ *
+ * This function should be called when the connection should be
+ * terminated after sending GOAWAY. If the remaining streams should
+ * be processed after GOAWAY, use `nghttp2_submit_goaway()` instead.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_terminate_session(nghttp2_session *session,
+ uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Signals the session so that the connection should be terminated.
+ *
+ * This function behaves like `nghttp2_session_terminate_session()`,
+ * but the last stream ID can be specified by the application for fine
+ * grained control of stream. The HTTP/2 specification does not allow
+ * last_stream_id to be increased. So the actual value sent as
+ * last_stream_id is the minimum value between the given
+ * |last_stream_id| and the last_stream_id we have previously sent to
+ * the peer.
+ *
+ * The |last_stream_id| is peer's stream ID or 0. So if |session| is
+ * initialized as client, |last_stream_id| must be even or 0. If
+ * |session| is initialized as server, |last_stream_id| must be odd or
+ * 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |last_stream_id| is invalid.
+ */
+NGHTTP2_EXTERN int nghttp2_session_terminate_session2(nghttp2_session *session,
+ int32_t last_stream_id,
+ uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Signals to the client that the server started graceful shutdown
+ * procedure.
+ *
+ * This function is only usable for server. If this function is
+ * called with client side session, this function returns
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`.
+ *
+ * To gracefully shutdown HTTP/2 session, server should call this
+ * function to send GOAWAY with last_stream_id (1u << 31) - 1. And
+ * after some delay (e.g., 1 RTT), send another GOAWAY with the stream
+ * ID that the server has some processing using
+ * `nghttp2_submit_goaway()`. See also
+ * `nghttp2_session_get_last_proc_stream_id()`.
+ *
+ * Unlike `nghttp2_submit_goaway()`, this function just sends GOAWAY
+ * and does nothing more. This is a mere indication to the client
+ * that session shutdown is imminent. The application should call
+ * `nghttp2_submit_goaway()` with appropriate last_stream_id after
+ * this call.
+ *
+ * If one or more GOAWAY frame have been already sent by either
+ * `nghttp2_submit_goaway()` or `nghttp2_session_terminate_session()`,
+ * this function has no effect.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * The |session| is initialized as client.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_shutdown_notice(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the value of SETTINGS |id| notified by a remote endpoint.
+ * The |id| must be one of values defined in
+ * :enum:`nghttp2_settings_id`.
+ */
+NGHTTP2_EXTERN uint32_t nghttp2_session_get_remote_settings(
+ nghttp2_session *session, nghttp2_settings_id id);
+
+/**
+ * @function
+ *
+ * Returns the value of SETTINGS |id| of local endpoint acknowledged
+ * by the remote endpoint. The |id| must be one of the values defined
+ * in :enum:`nghttp2_settings_id`.
+ */
+NGHTTP2_EXTERN uint32_t nghttp2_session_get_local_settings(
+ nghttp2_session *session, nghttp2_settings_id id);
+
+/**
+ * @function
+ *
+ * Tells the |session| that next stream ID is |next_stream_id|. The
+ * |next_stream_id| must be equal or greater than the value returned
+ * by `nghttp2_session_get_next_stream_id()`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |next_stream_id| is strictly less than the value
+ * `nghttp2_session_get_next_stream_id()` returns; or
+ * |next_stream_id| is invalid (e.g., even integer for client, or
+ * odd integer for server).
+ */
+NGHTTP2_EXTERN int nghttp2_session_set_next_stream_id(nghttp2_session *session,
+ int32_t next_stream_id);
+
+/**
+ * @function
+ *
+ * Returns the next outgoing stream ID. Notice that return type is
+ * uint32_t. If we run out of stream ID for this session, this
+ * function returns 1 << 31.
+ */
+NGHTTP2_EXTERN uint32_t
+nghttp2_session_get_next_stream_id(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Tells the |session| that |size| bytes for a stream denoted by
+ * |stream_id| were consumed by application and are ready to
+ * WINDOW_UPDATE. The consumed bytes are counted towards both
+ * connection and stream level WINDOW_UPDATE (see
+ * `nghttp2_session_consume_connection()` and
+ * `nghttp2_session_consume_stream()` to update consumption
+ * independently). This function is intended to be used without
+ * automatic window update (see
+ * `nghttp2_option_set_no_auto_window_update()`).
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * Automatic WINDOW_UPDATE is not disabled.
+ */
+NGHTTP2_EXTERN int nghttp2_session_consume(nghttp2_session *session,
+ int32_t stream_id, size_t size);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_consume()`, but this only tells library that
+ * |size| bytes were consumed only for connection level. Note that
+ * HTTP/2 maintains connection and stream level flow control windows
+ * independently.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * Automatic WINDOW_UPDATE is not disabled.
+ */
+NGHTTP2_EXTERN int nghttp2_session_consume_connection(nghttp2_session *session,
+ size_t size);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_consume()`, but this only tells library that
+ * |size| bytes were consumed only for stream denoted by |stream_id|.
+ * Note that HTTP/2 maintains connection and stream level flow control
+ * windows independently.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * Automatic WINDOW_UPDATE is not disabled.
+ */
+NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session,
+ int32_t stream_id,
+ size_t size);
+
+/**
+ * @function
+ *
+ * Changes priority of existing stream denoted by |stream_id|. The
+ * new priority specification is |pri_spec|.
+ *
+ * The priority is changed silently and instantly, and no PRIORITY
+ * frame will be sent to notify the peer of this change. This
+ * function may be useful for server to change the priority of pushed
+ * stream.
+ *
+ * If |session| is initialized as server, and ``pri_spec->stream_id``
+ * points to the idle stream, the idle stream is created if it does
+ * not exist. The created idle stream will depend on root stream
+ * (stream 0) with weight 16.
+ *
+ * Otherwise, if stream denoted by ``pri_spec->stream_id`` is not
+ * found, we use default priority instead of given |pri_spec|. That
+ * is make stream depend on root stream with weight 16.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * Attempted to depend on itself; or no stream exist for the given
+ * |stream_id|; or |stream_id| is 0
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_change_stream_priority(nghttp2_session *session,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Creates idle stream with the given |stream_id|, and priority
+ * |pri_spec|.
+ *
+ * The stream creation is done without sending PRIORITY frame, which
+ * means that peer does not know about the existence of this idle
+ * stream in the local endpoint.
+ *
+ * RFC 7540 does not disallow the use of creation of idle stream with
+ * odd or even stream ID regardless of client or server. So this
+ * function can create odd or even stream ID regardless of client or
+ * server. But probably it is a bit safer to use the stream ID the
+ * local endpoint can initiate (in other words, use odd stream ID for
+ * client, and even stream ID for server), to avoid potential
+ * collision from peer's instruction. Also we can use
+ * `nghttp2_session_set_next_stream_id()` to avoid to open created
+ * idle streams accidentally if we follow this recommendation.
+ *
+ * If |session| is initialized as server, and ``pri_spec->stream_id``
+ * points to the idle stream, the idle stream is created if it does
+ * not exist. The created idle stream will depend on root stream
+ * (stream 0) with weight 16.
+ *
+ * Otherwise, if stream denoted by ``pri_spec->stream_id`` is not
+ * found, we use default priority instead of given |pri_spec|. That
+ * is make stream depend on root stream with weight 16.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * Attempted to depend on itself; or stream denoted by |stream_id|
+ * already exists; or |stream_id| cannot be used to create idle
+ * stream (in other words, local endpoint has already opened
+ * stream ID greater than or equal to the given stream ID; or
+ * |stream_id| is 0
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Performs post-process of HTTP Upgrade request. This function can
+ * be called from both client and server, but the behavior is very
+ * different in each other.
+ *
+ * .. warning::
+ *
+ * This function is deprecated in favor of
+ * `nghttp2_session_upgrade2()`, because this function lacks the
+ * parameter to tell the library the request method used in the
+ * original HTTP request. This information is required for client
+ * to validate actual response body length against content-length
+ * header field (see `nghttp2_option_set_no_http_messaging()`). If
+ * HEAD is used in request, the length of response body must be 0
+ * regardless of value included in content-length header field.
+ *
+ * If called from client side, the |settings_payload| must be the
+ * value sent in ``HTTP2-Settings`` header field and must be decoded
+ * by base64url decoder. The |settings_payloadlen| is the length of
+ * |settings_payload|. The |settings_payload| is unpacked and its
+ * setting values will be submitted using `nghttp2_submit_settings()`.
+ * This means that the client application code does not need to submit
+ * SETTINGS by itself. The stream with stream ID=1 is opened and the
+ * |stream_user_data| is used for its stream_user_data. The opened
+ * stream becomes half-closed (local) state.
+ *
+ * If called from server side, the |settings_payload| must be the
+ * value received in ``HTTP2-Settings`` header field and must be
+ * decoded by base64url decoder. The |settings_payloadlen| is the
+ * length of |settings_payload|. It is treated as if the SETTINGS
+ * frame with that payload is received. Thus, callback functions for
+ * the reception of SETTINGS frame will be invoked. The stream with
+ * stream ID=1 is opened. The |stream_user_data| is ignored. The
+ * opened stream becomes half-closed (remote).
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |settings_payload| is badly formed.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The stream ID 1 is already used or closed; or is not available.
+ */
+NGHTTP2_EXTERN int nghttp2_session_upgrade(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Performs post-process of HTTP Upgrade request. This function can
+ * be called from both client and server, but the behavior is very
+ * different in each other.
+ *
+ * If called from client side, the |settings_payload| must be the
+ * value sent in ``HTTP2-Settings`` header field and must be decoded
+ * by base64url decoder. The |settings_payloadlen| is the length of
+ * |settings_payload|. The |settings_payload| is unpacked and its
+ * setting values will be submitted using `nghttp2_submit_settings()`.
+ * This means that the client application code does not need to submit
+ * SETTINGS by itself. The stream with stream ID=1 is opened and the
+ * |stream_user_data| is used for its stream_user_data. The opened
+ * stream becomes half-closed (local) state.
+ *
+ * If called from server side, the |settings_payload| must be the
+ * value received in ``HTTP2-Settings`` header field and must be
+ * decoded by base64url decoder. The |settings_payloadlen| is the
+ * length of |settings_payload|. It is treated as if the SETTINGS
+ * frame with that payload is received. Thus, callback functions for
+ * the reception of SETTINGS frame will be invoked. The stream with
+ * stream ID=1 is opened. The |stream_user_data| is ignored. The
+ * opened stream becomes half-closed (remote).
+ *
+ * If the request method is HEAD, pass nonzero value to
+ * |head_request|. Otherwise, pass 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |settings_payload| is badly formed.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The stream ID 1 is already used or closed; or is not available.
+ */
+NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen,
+ int head_request,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Serializes the SETTINGS values |iv| in the |buf|. The size of the
+ * |buf| is specified by |buflen|. The number of entries in the |iv|
+ * array is given by |niv|. The required space in |buf| for the |niv|
+ * entries is ``6*niv`` bytes and if the given buffer is too small, an
+ * error is returned. This function is used mainly for creating a
+ * SETTINGS payload to be sent with the ``HTTP2-Settings`` header
+ * field in an HTTP Upgrade request. The data written in |buf| is NOT
+ * base64url encoded and the application is responsible for encoding.
+ *
+ * This function returns the number of bytes written in |buf|, or one
+ * of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |iv| contains duplicate settings ID or invalid value.
+ *
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ * The provided |buflen| size is too small to hold the output.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_pack_settings_payload(
+ uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv);
+
+/**
+ * @function
+ *
+ * Returns string describing the |lib_error_code|. The
+ * |lib_error_code| must be one of the :enum:`nghttp2_error`.
+ */
+NGHTTP2_EXTERN const char *nghttp2_strerror(int lib_error_code);
+
+/**
+ * @function
+ *
+ * Returns string representation of HTTP/2 error code |error_code|
+ * (e.g., ``PROTOCOL_ERROR`` is returned if ``error_code ==
+ * NGHTTP2_PROTOCOL_ERROR``). If string representation is unknown for
+ * given |error_code|, this function returns string ``unknown``.
+ */
+NGHTTP2_EXTERN const char *nghttp2_http2_strerror(uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Initializes |pri_spec| with the |stream_id| of the stream to depend
+ * on with |weight| and its exclusive flag. If |exclusive| is
+ * nonzero, exclusive flag is set.
+ *
+ * The |weight| must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive.
+ */
+NGHTTP2_EXTERN void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec,
+ int32_t stream_id,
+ int32_t weight, int exclusive);
+
+/**
+ * @function
+ *
+ * Initializes |pri_spec| with the default values. The default values
+ * are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and
+ * exclusive = 0.
+ */
+NGHTTP2_EXTERN void
+nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the |pri_spec| is filled with default values.
+ */
+NGHTTP2_EXTERN int
+nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Submits HEADERS frame and optionally one or more DATA frames.
+ *
+ * The |pri_spec| is priority specification of this request. ``NULL``
+ * means the default priority (see
+ * `nghttp2_priority_spec_default_init()`). To specify the priority,
+ * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
+ * this function will copy its data members.
+ *
+ * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is
+ * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
+ * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
+ * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * HTTP/2 specification has requirement about header fields in the
+ * request HEADERS. See the specification for more details.
+ *
+ * If |data_prd| is not ``NULL``, it provides data which will be sent
+ * in subsequent DATA frames. In this case, a method that allows
+ * request message bodies
+ * (https://tools.ietf.org/html/rfc7231#section-4) must be specified
+ * with ``:method`` key in |nva| (e.g. ``POST``). This function does
+ * not take ownership of the |data_prd|. The function copies the
+ * members of the |data_prd|. If |data_prd| is ``NULL``, HEADERS have
+ * END_STREAM set. The |stream_user_data| is data associated to the
+ * stream opened by this request and can be an arbitrary pointer,
+ * which can be retrieved later by
+ * `nghttp2_session_get_stream_user_data()`.
+ *
+ * This function returns assigned stream ID if it succeeds, or one of
+ * the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
+ * No stream ID is available because maximum stream ID was
+ * reached.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * Trying to depend on itself (new stream ID equals
+ * ``pri_spec->stream_id``).
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The |session| is server session.
+ *
+ * .. warning::
+ *
+ * This function returns assigned stream ID if it succeeds. But
+ * that stream is not opened yet. The application must not submit
+ * frame to that stream ID before
+ * :type:`nghttp2_before_frame_send_callback` is called for this
+ * frame.
+ *
+ */
+NGHTTP2_EXTERN int32_t nghttp2_submit_request(
+ nghttp2_session *session, const nghttp2_priority_spec *pri_spec,
+ const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits response HEADERS frame and optionally one or more DATA
+ * frames against the stream |stream_id|.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * HTTP/2 specification has requirement about header fields in the
+ * response HEADERS. See the specification for more details.
+ *
+ * If |data_prd| is not ``NULL``, it provides data which will be sent
+ * in subsequent DATA frames. This function does not take ownership
+ * of the |data_prd|. The function copies the members of the
+ * |data_prd|. If |data_prd| is ``NULL``, HEADERS will have
+ * END_STREAM flag set.
+ *
+ * This method can be used as normal HTTP response and push response.
+ * When pushing a resource using this function, the |session| must be
+ * configured using `nghttp2_session_server_new()` or its variants and
+ * the target stream denoted by the |stream_id| must be reserved using
+ * `nghttp2_submit_push_promise()`.
+ *
+ * To send non-final response headers (e.g., HTTP status 101), don't
+ * use this function because this function half-closes the outbound
+ * stream. Instead, use `nghttp2_submit_headers()` for this purpose.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * DATA or HEADERS has been already submitted and not fully
+ * processed yet. Normally, this does not happen, but when
+ * application wrongly calls `nghttp2_submit_response()` twice,
+ * this may happen.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The |session| is client session.
+ *
+ * .. warning::
+ *
+ * Calling this function twice for the same stream ID may lead to
+ * program crash. It is generally considered to a programming error
+ * to commit response twice.
+ */
+NGHTTP2_EXTERN int
+nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen,
+ const nghttp2_data_provider *data_prd);
+
+/**
+ * @function
+ *
+ * Submits trailer fields HEADERS against the stream |stream_id|.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application must not include pseudo-header
+ * fields (headers whose names starts with ":") in |nva|.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * For server, trailer fields must follow response HEADERS or response
+ * DATA without END_STREAM flat set. The library does not enforce
+ * this requirement, and applications should do this for themselves.
+ * If `nghttp2_submit_trailer()` is called before any response HEADERS
+ * submission (usually by `nghttp2_submit_response()`), the content of
+ * |nva| will be sent as response headers, which will result in error.
+ *
+ * This function has the same effect with `nghttp2_submit_headers()`,
+ * with flags = :enum:`NGHTTP2_FLAG_END_STREAM` and both pri_spec and
+ * stream_user_data to NULL.
+ *
+ * To submit trailer fields after `nghttp2_submit_response()` is
+ * called, the application has to specify
+ * :type:`nghttp2_data_provider` to `nghttp2_submit_response()`.
+ * Inside of :type:`nghttp2_data_source_read_callback`, when setting
+ * :enum:`NGHTTP2_DATA_FLAG_EOF`, also set
+ * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM`. After that, the
+ * application can send trailer fields using
+ * `nghttp2_submit_trailer()`. `nghttp2_submit_trailer()` can be used
+ * inside :type:`nghttp2_data_source_read_callback`.
+ *
+ * This function returns 0 if it succeeds and |stream_id| is -1.
+ * Otherwise, this function returns 0 if it succeeds, or one of the
+ * following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
+ int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen);
+
+/**
+ * @function
+ *
+ * Submits HEADERS frame. The |flags| is bitwise OR of the
+ * following values:
+ *
+ * * :enum:`NGHTTP2_FLAG_END_STREAM`
+ *
+ * If |flags| includes :enum:`NGHTTP2_FLAG_END_STREAM`, this frame has
+ * END_STREAM flag set.
+ *
+ * The library handles the CONTINUATION frame internally and it
+ * correctly sets END_HEADERS to the last sequence of the PUSH_PROMISE
+ * or CONTINUATION frame.
+ *
+ * If the |stream_id| is -1, this frame is assumed as request (i.e.,
+ * request HEADERS frame which opens new stream). In this case, the
+ * assigned stream ID will be returned. Otherwise, specify stream ID
+ * in |stream_id|.
+ *
+ * The |pri_spec| is priority specification of this request. ``NULL``
+ * means the default priority (see
+ * `nghttp2_priority_spec_default_init()`). To specify the priority,
+ * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
+ * this function will copy its data members.
+ *
+ * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is
+ * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
+ * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
+ * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * The |stream_user_data| is a pointer to an arbitrary data which is
+ * associated to the stream this frame will open. Therefore it is
+ * only used if this frame opens streams, in other words, it changes
+ * stream state from idle or reserved to open.
+ *
+ * This function is low-level in a sense that the application code can
+ * specify flags directly. For usual HTTP request,
+ * `nghttp2_submit_request()` is useful. Likewise, for HTTP response,
+ * prefer `nghttp2_submit_response()`.
+ *
+ * This function returns newly assigned stream ID if it succeeds and
+ * |stream_id| is -1. Otherwise, this function returns 0 if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
+ * No stream ID is available because maximum stream ID was
+ * reached.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0; or trying to depend on itself (stream ID
+ * equals ``pri_spec->stream_id``).
+ * :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * DATA or HEADERS has been already submitted and not fully
+ * processed yet. This happens if stream denoted by |stream_id|
+ * is in reserved state.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The |stream_id| is -1, and |session| is server session.
+ *
+ * .. warning::
+ *
+ * This function returns assigned stream ID if it succeeds and
+ * |stream_id| is -1. But that stream is not opened yet. The
+ * application must not submit frame to that stream ID before
+ * :type:`nghttp2_before_frame_send_callback` is called for this
+ * frame.
+ *
+ */
+NGHTTP2_EXTERN int32_t nghttp2_submit_headers(
+ nghttp2_session *session, uint8_t flags, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits one or more DATA frames to the stream |stream_id|. The
+ * data to be sent are provided by |data_prd|. If |flags| contains
+ * :enum:`NGHTTP2_FLAG_END_STREAM`, the last DATA frame has END_STREAM
+ * flag set.
+ *
+ * This function does not take ownership of the |data_prd|. The
+ * function copies the members of the |data_prd|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * DATA or HEADERS has been already submitted and not fully
+ * processed yet.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_STREAM_CLOSED`
+ * The stream was already closed; or the |stream_id| is invalid.
+ *
+ * .. note::
+ *
+ * Currently, only one DATA or HEADERS is allowed for a stream at a
+ * time. Submitting these frames more than once before first DATA
+ * or HEADERS is finished results in :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * error code. The earliest callback which tells that previous
+ * frame is done is :type:`nghttp2_on_frame_send_callback`. In side
+ * that callback, new data can be submitted using
+ * `nghttp2_submit_data()`. Of course, all data except for last one
+ * must not have :enum:`NGHTTP2_FLAG_END_STREAM` flag set in
+ * |flags|. This sounds a bit complicated, and we recommend to use
+ * `nghttp2_submit_request()` and `nghttp2_submit_response()` to
+ * avoid this cascading issue. The experience shows that for HTTP
+ * use, these two functions are enough to implement both client and
+ * server.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_data_provider *data_prd);
+
+/**
+ * @function
+ *
+ * Submits PRIORITY frame to change the priority of stream |stream_id|
+ * to the priority specification |pri_spec|.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |pri_spec| is priority specification of this request. ``NULL``
+ * is not allowed for this function. To specify the priority, use
+ * `nghttp2_priority_spec_init()`. This function will copy its data
+ * members.
+ *
+ * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is
+ * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
+ * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
+ * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0; or the |pri_spec| is NULL; or trying to
+ * depend on itself.
+ */
+NGHTTP2_EXTERN int
+nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Submits RST_STREAM frame to cancel/reject the stream |stream_id|
+ * with the error code |error_code|.
+ *
+ * The pre-defined error code is one of :enum:`nghttp2_error_code`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_rst_stream(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Stores local settings and submits SETTINGS frame. The |iv| is the
+ * pointer to the array of :type:`nghttp2_settings_entry`. The |niv|
+ * indicates the number of :type:`nghttp2_settings_entry`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function does not take ownership of the |iv|. This function
+ * copies all the elements in the |iv|.
+ *
+ * While updating individual stream's local window size, if the window
+ * size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
+ * RST_STREAM is issued against such a stream.
+ *
+ * SETTINGS with :enum:`NGHTTP2_FLAG_ACK` is automatically submitted
+ * by the library and application could not send it at its will.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |iv| contains invalid value (e.g., initial window size
+ * strictly greater than (1 << 31) - 1.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session,
+ uint8_t flags,
+ const nghttp2_settings_entry *iv,
+ size_t niv);
+
+/**
+ * @function
+ *
+ * Submits PUSH_PROMISE frame.
+ *
+ * The |flags| is currently ignored. The library handles the
+ * CONTINUATION frame internally and it correctly sets END_HEADERS to
+ * the last sequence of the PUSH_PROMISE or CONTINUATION frame.
+ *
+ * The |stream_id| must be client initiated stream ID.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * The |promised_stream_user_data| is a pointer to an arbitrary data
+ * which is associated to the promised stream this frame will open and
+ * make it in reserved state. It is available using
+ * `nghttp2_session_get_stream_user_data()`. The application can
+ * access it in :type:`nghttp2_before_frame_send_callback` and
+ * :type:`nghttp2_on_frame_send_callback` of this frame.
+ *
+ * The client side is not allowed to use this function.
+ *
+ * To submit response headers and data, use
+ * `nghttp2_submit_response()`.
+ *
+ * This function returns assigned promised stream ID if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * This function was invoked when |session| is initialized as
+ * client.
+ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
+ * No stream ID is available because maximum stream ID was
+ * reached.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0; The |stream_id| does not designate stream
+ * that peer initiated.
+ * :enum:`NGHTTP2_ERR_STREAM_CLOSED`
+ * The stream was already closed; or the |stream_id| is invalid.
+ *
+ * .. warning::
+ *
+ * This function returns assigned promised stream ID if it succeeds.
+ * As of 1.16.0, stream object for pushed resource is created when
+ * this function succeeds. In that case, the application can submit
+ * push response for the promised frame.
+ *
+ * In 1.15.0 or prior versions, pushed stream is not opened yet when
+ * this function succeeds. The application must not submit frame to
+ * that stream ID before :type:`nghttp2_before_frame_send_callback`
+ * is called for this frame.
+ *
+ */
+NGHTTP2_EXTERN int32_t nghttp2_submit_push_promise(
+ nghttp2_session *session, uint8_t flags, int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen, void *promised_stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits PING frame. You don't have to send PING back when you
+ * received PING frame. The library automatically submits PING frame
+ * in this case.
+ *
+ * The |flags| is bitwise OR of 0 or more of the following value.
+ *
+ * * :enum:`NGHTTP2_FLAG_ACK`
+ *
+ * Unless `nghttp2_option_set_no_auto_ping_ack()` is used, the |flags|
+ * should be :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * If the |opaque_data| is non ``NULL``, then it should point to the 8
+ * bytes array of memory to specify opaque data to send with PING
+ * frame. If the |opaque_data| is ``NULL``, zero-cleared 8 bytes will
+ * be sent as opaque data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
+ const uint8_t *opaque_data);
+
+/**
+ * @function
+ *
+ * Submits GOAWAY frame with the last stream ID |last_stream_id| and
+ * the error code |error_code|.
+ *
+ * The pre-defined error code is one of :enum:`nghttp2_error_code`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |last_stream_id| is peer's stream ID or 0. So if |session| is
+ * initialized as client, |last_stream_id| must be even or 0. If
+ * |session| is initialized as server, |last_stream_id| must be odd or
+ * 0.
+ *
+ * The HTTP/2 specification says last_stream_id must not be increased
+ * from the value previously sent. So the actual value sent as
+ * last_stream_id is the minimum value between the given
+ * |last_stream_id| and the last_stream_id previously sent to the
+ * peer.
+ *
+ * If the |opaque_data| is not ``NULL`` and |opaque_data_len| is not
+ * zero, those data will be sent as additional debug data. The
+ * library makes a copy of the memory region pointed by |opaque_data|
+ * with the length |opaque_data_len|, so the caller does not need to
+ * keep this memory after the return of this function. If the
+ * |opaque_data_len| is 0, the |opaque_data| could be ``NULL``.
+ *
+ * After successful transmission of GOAWAY, following things happen.
+ * All incoming streams having strictly more than |last_stream_id| are
+ * closed. All incoming HEADERS which starts new stream are simply
+ * ignored. After all active streams are handled, both
+ * `nghttp2_session_want_read()` and `nghttp2_session_want_write()`
+ * return 0 and the application can close session.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |opaque_data_len| is too large; the |last_stream_id| is
+ * invalid.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_goaway(nghttp2_session *session,
+ uint8_t flags, int32_t last_stream_id,
+ uint32_t error_code,
+ const uint8_t *opaque_data,
+ size_t opaque_data_len);
+
+/**
+ * @function
+ *
+ * Returns the last stream ID of a stream for which
+ * :type:`nghttp2_on_frame_recv_callback` was invoked most recently.
+ * The returned value can be used as last_stream_id parameter for
+ * `nghttp2_submit_goaway()` and
+ * `nghttp2_session_terminate_session2()`.
+ *
+ * This function always succeeds.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_last_proc_stream_id(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero if new request can be sent from local endpoint.
+ *
+ * This function return 0 if request is not allowed for this session.
+ * There are several reasons why request is not allowed. Some of the
+ * reasons are: session is server; stream ID has been spent; GOAWAY
+ * has been sent or received.
+ *
+ * The application can call `nghttp2_submit_request()` without
+ * consulting this function. In that case, `nghttp2_submit_request()`
+ * may return error. Or, request is failed to sent, and
+ * :type:`nghttp2_on_stream_close_callback` is called.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_check_request_allowed(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero if |session| is initialized as server side session.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_check_server_session(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Submits WINDOW_UPDATE frame.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |stream_id| is the stream ID to send this WINDOW_UPDATE. To
+ * send connection level WINDOW_UPDATE, specify 0 to |stream_id|.
+ *
+ * If the |window_size_increment| is positive, the WINDOW_UPDATE with
+ * that value as window_size_increment is queued. If the
+ * |window_size_increment| is larger than the received bytes from the
+ * remote endpoint, the local window size is increased by that
+ * difference. If the sole purpose is to increase the local window
+ * size, consider to use `nghttp2_session_set_local_window_size()`.
+ *
+ * If the |window_size_increment| is negative, the local window size
+ * is decreased by -|window_size_increment|. If automatic
+ * WINDOW_UPDATE is enabled
+ * (`nghttp2_option_set_no_auto_window_update()`), and the library
+ * decided that the WINDOW_UPDATE should be submitted, then
+ * WINDOW_UPDATE is queued with the current received bytes count. If
+ * the sole purpose is to decrease the local window size, consider to
+ * use `nghttp2_session_set_local_window_size()`.
+ *
+ * If the |window_size_increment| is 0, the function does nothing and
+ * returns 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_FLOW_CONTROL`
+ * The local window size overflow or gets negative.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_window_update(nghttp2_session *session,
+ uint8_t flags,
+ int32_t stream_id,
+ int32_t window_size_increment);
+
+/**
+ * @function
+ *
+ * Set local window size (local endpoints's window size) to the given
+ * |window_size| for the given stream denoted by |stream_id|. To
+ * change connection level window size, specify 0 to |stream_id|. To
+ * increase window size, this function may submit WINDOW_UPDATE frame
+ * to transmission queue.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This sounds similar to `nghttp2_submit_window_update()`, but there
+ * are 2 differences. The first difference is that this function
+ * takes the absolute value of window size to set, rather than the
+ * delta. To change the window size, this may be easier to use since
+ * the application just declares the intended window size, rather than
+ * calculating delta. The second difference is that
+ * `nghttp2_submit_window_update()` affects the received bytes count
+ * which has not acked yet. By the specification of
+ * `nghttp2_submit_window_update()`, to strictly increase the local
+ * window size, we have to submit delta including all received bytes
+ * count, which might not be desirable in some cases. On the other
+ * hand, this function does not affect the received bytes count. It
+ * just sets the local window size to the given value.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is negative.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id, int32_t window_size);
+
+/**
+ * @function
+ *
+ * Submits extension frame.
+ *
+ * Application can pass arbitrary frame flags and stream ID in |flags|
+ * and |stream_id| respectively. The |payload| is opaque pointer, and
+ * it can be accessible though ``frame->ext.payload`` in
+ * :type:`nghttp2_pack_extension_callback`. The library will not own
+ * passed |payload| pointer.
+ *
+ * The application must set :type:`nghttp2_pack_extension_callback`
+ * using `nghttp2_session_callbacks_set_pack_extension_callback()`.
+ *
+ * The application should retain the memory pointed by |payload| until
+ * the transmission of extension frame is done (which is indicated by
+ * :type:`nghttp2_on_frame_send_callback`), or transmission fails
+ * (which is indicated by :type:`nghttp2_on_frame_not_send_callback`).
+ * If application does not touch this memory region after packing it
+ * into a wire format, application can free it inside
+ * :type:`nghttp2_pack_extension_callback`.
+ *
+ * The standard HTTP/2 frame cannot be sent with this function, so
+ * |type| must be strictly grater than 0x9. Otherwise, this function
+ * will fail with error code :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * If :type:`nghttp2_pack_extension_callback` is not set.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * If |type| specifies standard HTTP/2 frame type. The frame
+ * types in the rage [0x0, 0x9], both inclusive, are standard
+ * HTTP/2 frame type, and cannot be sent using this function.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory
+ */
+NGHTTP2_EXTERN int nghttp2_submit_extension(nghttp2_session *session,
+ uint8_t type, uint8_t flags,
+ int32_t stream_id, void *payload);
+
+/**
+ * @struct
+ *
+ * The payload of ALTSVC frame. ALTSVC frame is a non-critical
+ * extension to HTTP/2. If this frame is received, and
+ * `nghttp2_option_set_user_recv_extension_type()` is not set, and
+ * `nghttp2_option_set_builtin_recv_extension_type()` is set for
+ * :enum:`NGHTTP2_ALTSVC`, ``nghttp2_extension.payload`` will point to
+ * this struct.
+ *
+ * It has the following members:
+ */
+typedef struct {
+ /**
+ * The pointer to origin which this alternative service is
+ * associated with. This is not necessarily NULL-terminated.
+ */
+ uint8_t *origin;
+ /**
+ * The length of the |origin|.
+ */
+ size_t origin_len;
+ /**
+ * The pointer to Alt-Svc field value contained in ALTSVC frame.
+ * This is not necessarily NULL-terminated.
+ */
+ uint8_t *field_value;
+ /**
+ * The length of the |field_value|.
+ */
+ size_t field_value_len;
+} nghttp2_ext_altsvc;
+
+/**
+ * @function
+ *
+ * Submits ALTSVC frame.
+ *
+ * ALTSVC frame is a non-critical extension to HTTP/2, and defined in
+ * is defined in `RFC 7383
+ * `_.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |origin| points to the origin this alternative service is
+ * associated with. The |origin_len| is the length of the origin. If
+ * |stream_id| is 0, the origin must be specified. If |stream_id| is
+ * not zero, the origin must be empty (in other words, |origin_len|
+ * must be 0).
+ *
+ * The ALTSVC frame is only usable from server side. If this function
+ * is invoked with client side session, this function returns
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * The function is called from client side session
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The sum of |origin_len| and |field_value_len| is larger than
+ * 16382; or |origin_len| is 0 while |stream_id| is 0; or
+ * |origin_len| is not 0 while |stream_id| is not 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ const uint8_t *origin,
+ size_t origin_len,
+ const uint8_t *field_value,
+ size_t field_value_len);
+
+/**
+ * @function
+ *
+ * Compares ``lhs->name`` of length ``lhs->namelen`` bytes and
+ * ``rhs->name`` of length ``rhs->namelen`` bytes. Returns negative
+ * integer if ``lhs->name`` is found to be less than ``rhs->name``; or
+ * returns positive integer if ``lhs->name`` is found to be greater
+ * than ``rhs->name``; or returns 0 otherwise.
+ */
+NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs,
+ const nghttp2_nv *rhs);
+
+/**
+ * @function
+ *
+ * A helper function for dealing with NPN in client side or ALPN in
+ * server side. The |in| contains peer's protocol list in preferable
+ * order. The format of |in| is length-prefixed and not
+ * null-terminated. For example, ``h2`` and
+ * ``http/1.1`` stored in |in| like this::
+ *
+ * in[0] = 2
+ * in[1..2] = "h2"
+ * in[3] = 8
+ * in[4..11] = "http/1.1"
+ * inlen = 12
+ *
+ * The selection algorithm is as follows:
+ *
+ * 1. If peer's list contains HTTP/2 protocol the library supports,
+ * it is selected and returns 1. The following step is not taken.
+ *
+ * 2. If peer's list contains ``http/1.1``, this function selects
+ * ``http/1.1`` and returns 0. The following step is not taken.
+ *
+ * 3. This function selects nothing and returns -1 (So called
+ * non-overlap case). In this case, |out| and |outlen| are left
+ * untouched.
+ *
+ * Selecting ``h2`` means that ``h2`` is written into |*out| and its
+ * length (which is 2) is assigned to |*outlen|.
+ *
+ * For ALPN, refer to https://tools.ietf.org/html/rfc7301
+ *
+ * See http://technotes.googlecode.com/git/nextprotoneg.html for more
+ * details about NPN.
+ *
+ * For NPN, to use this method you should do something like::
+ *
+ * static int select_next_proto_cb(SSL* ssl,
+ * unsigned char **out,
+ * unsigned char *outlen,
+ * const unsigned char *in,
+ * unsigned int inlen,
+ * void *arg)
+ * {
+ * int rv;
+ * rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
+ * if (rv == -1) {
+ * return SSL_TLSEXT_ERR_NOACK;
+ * }
+ * if (rv == 1) {
+ * ((MyType*)arg)->http2_selected = 1;
+ * }
+ * return SSL_TLSEXT_ERR_OK;
+ * }
+ * ...
+ * SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
+ *
+ */
+NGHTTP2_EXTERN int nghttp2_select_next_protocol(unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen);
+
+/**
+ * @function
+ *
+ * Returns a pointer to a nghttp2_info struct with version information
+ * about the run-time library in use. The |least_version| argument
+ * can be set to a 24 bit numerical value for the least accepted
+ * version number and if the condition is not met, this function will
+ * return a ``NULL``. Pass in 0 to skip the version checking.
+ */
+NGHTTP2_EXTERN nghttp2_info *nghttp2_version(int least_version);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the :type:`nghttp2_error` library error code
+ * |lib_error| is fatal.
+ */
+NGHTTP2_EXTERN int nghttp2_is_fatal(int lib_error_code);
+
+/**
+ * @function
+ *
+ * Returns nonzero if HTTP header field name |name| of length |len| is
+ * valid according to http://tools.ietf.org/html/rfc7230#section-3.2
+ *
+ * Because this is a header field name in HTTP2, the upper cased alphabet
+ * is treated as error.
+ */
+NGHTTP2_EXTERN int nghttp2_check_header_name(const uint8_t *name, size_t len);
+
+/**
+ * @function
+ *
+ * Returns nonzero if HTTP header field value |value| of length |len|
+ * is valid according to
+ * http://tools.ietf.org/html/rfc7230#section-3.2
+ */
+NGHTTP2_EXTERN int nghttp2_check_header_value(const uint8_t *value, size_t len);
+
+/* HPACK API */
+
+struct nghttp2_hd_deflater;
+
+/**
+ * @struct
+ *
+ * HPACK deflater object.
+ */
+typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;
+
+/**
+ * @function
+ *
+ * Initializes |*deflater_ptr| for deflating name/values pairs.
+ *
+ * The |max_deflate_dynamic_table_size| is the upper bound of header
+ * table size the deflater will use.
+ *
+ * If this function fails, |*deflater_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
+ size_t max_deflate_dynamic_table_size);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_hd_deflate_new()`, but with additional custom memory
+ * allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_hd_deflate_new()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
+ size_t max_deflate_dynamic_table_size,
+ nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Deallocates any resources allocated for |deflater|.
+ */
+NGHTTP2_EXTERN void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater);
+
+/**
+ * @function
+ *
+ * Changes header table size of the |deflater| to
+ * |settings_max_dynamic_table_size| bytes. This may trigger eviction
+ * in the dynamic table.
+ *
+ * The |settings_max_dynamic_table_size| should be the value received
+ * in SETTINGS_HEADER_TABLE_SIZE.
+ *
+ * The deflater never uses more memory than
+ * ``max_deflate_dynamic_table_size`` bytes specified in
+ * `nghttp2_hd_deflate_new()`. Therefore, if
+ * |settings_max_dynamic_table_size| >
+ * ``max_deflate_dynamic_table_size``, resulting maximum table size
+ * becomes ``max_deflate_dynamic_table_size``.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
+ size_t settings_max_dynamic_table_size);
+
+/**
+ * @function
+ *
+ * Deflates the |nva|, which has the |nvlen| name/value pairs, into
+ * the |buf| of length |buflen|.
+ *
+ * If |buf| is not large enough to store the deflated header block,
+ * this function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The
+ * caller should use `nghttp2_hd_deflate_bound()` to know the upper
+ * bound of buffer size required to deflate given header name/value
+ * pairs.
+ *
+ * Once this function fails, subsequent call of this function always
+ * returns :enum:`NGHTTP2_ERR_HEADER_COMP`.
+ *
+ * After this function returns, it is safe to delete the |nva|.
+ *
+ * This function returns the number of bytes written to |buf| if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Deflation process has failed.
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ * The provided |buflen| size is too small to hold the output.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
+ uint8_t *buf, size_t buflen,
+ const nghttp2_nv *nva,
+ size_t nvlen);
+
+/**
+ * @function
+ *
+ * Deflates the |nva|, which has the |nvlen| name/value pairs, into
+ * the |veclen| size of buf vector |vec|. The each size of buffer
+ * must be set in len field of :type:`nghttp2_vec`. If and only if
+ * one chunk is filled up completely, next chunk will be used. If
+ * |vec| is not large enough to store the deflated header block, this
+ * function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller
+ * should use `nghttp2_hd_deflate_bound()` to know the upper bound of
+ * buffer size required to deflate given header name/value pairs.
+ *
+ * Once this function fails, subsequent call of this function always
+ * returns :enum:`NGHTTP2_ERR_HEADER_COMP`.
+ *
+ * After this function returns, it is safe to delete the |nva|.
+ *
+ * This function returns the number of bytes written to |vec| if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Deflation process has failed.
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ * The provided |buflen| size is too small to hold the output.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
+ const nghttp2_vec *vec,
+ size_t veclen,
+ const nghttp2_nv *nva,
+ size_t nvlen);
+
+/**
+ * @function
+ *
+ * Returns an upper bound on the compressed size after deflation of
+ * |nva| of length |nvlen|.
+ */
+NGHTTP2_EXTERN size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
+ const nghttp2_nv *nva,
+ size_t nvlen);
+
+/**
+ * @function
+ *
+ * Returns the number of entries that header table of |deflater|
+ * contains. This is the sum of the number of static table and
+ * dynamic table, so the return value is at least 61.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater);
+
+/**
+ * @function
+ *
+ * Returns the table entry denoted by |idx| from header table of
+ * |deflater|. The |idx| is 1-based, and idx=1 returns first entry of
+ * static table. idx=62 returns first entry of dynamic table if it
+ * exists. Specifying idx=0 is error, and this function returns NULL.
+ * If |idx| is strictly greater than the number of entries the tables
+ * contain, this function returns NULL.
+ */
+NGHTTP2_EXTERN
+const nghttp2_nv *
+nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx);
+
+/**
+ * @function
+ *
+ * Returns the used dynamic table size, including the overhead 32
+ * bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater);
+
+/**
+ * @function
+ *
+ * Returns the maximum dynamic table size.
+ */
+NGHTTP2_EXTERN
+size_t
+nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater);
+
+struct nghttp2_hd_inflater;
+
+/**
+ * @struct
+ *
+ * HPACK inflater object.
+ */
+typedef struct nghttp2_hd_inflater nghttp2_hd_inflater;
+
+/**
+ * @function
+ *
+ * Initializes |*inflater_ptr| for inflating name/values pairs.
+ *
+ * If this function fails, |*inflater_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_hd_inflate_new()`, but with additional custom memory
+ * allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_hd_inflate_new()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ */
+NGHTTP2_EXTERN int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
+ nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Deallocates any resources allocated for |inflater|.
+ */
+NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Changes header table size in the |inflater|. This may trigger
+ * eviction in the dynamic table.
+ *
+ * The |settings_max_dynamic_table_size| should be the value
+ * transmitted in SETTINGS_HEADER_TABLE_SIZE.
+ *
+ * This function must not be called while header block is being
+ * inflated. In other words, this function must be called after
+ * initialization of |inflater|, but before calling
+ * `nghttp2_hd_inflate_hd2()`, or after
+ * `nghttp2_hd_inflate_end_headers()`. Otherwise,
+ * `NGHTTP2_ERR_INVALID_STATE` was returned.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * The function is called while header block is being inflated.
+ * Probably, application missed to call
+ * `nghttp2_hd_inflate_end_headers()`.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
+ size_t settings_max_dynamic_table_size);
+
+/**
+ * @enum
+ *
+ * The flags for header inflation.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_HD_INFLATE_NONE = 0,
+ /**
+ * Indicates all headers were inflated.
+ */
+ NGHTTP2_HD_INFLATE_FINAL = 0x01,
+ /**
+ * Indicates a header was emitted.
+ */
+ NGHTTP2_HD_INFLATE_EMIT = 0x02
+} nghttp2_hd_inflate_flag;
+
+/**
+ * @function
+ *
+ * .. warning::
+ *
+ * Deprecated. Use `nghttp2_hd_inflate_hd2()` instead.
+ *
+ * Inflates name/value block stored in |in| with length |inlen|. This
+ * function performs decompression. For each successful emission of
+ * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
+ * |*inflate_flags| and name/value pair is assigned to the |nv_out|
+ * and the function returns. The caller must not free the members of
+ * |nv_out|.
+ *
+ * The |nv_out| may include pointers to the memory region in the |in|.
+ * The caller must retain the |in| while the |nv_out| is used.
+ *
+ * The application should call this function repeatedly until the
+ * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
+ * return value is non-negative. This means the all input values are
+ * processed successfully. Then the application must call
+ * `nghttp2_hd_inflate_end_headers()` to prepare for the next header
+ * block input.
+ *
+ * The caller can feed complete compressed header block. It also can
+ * feed it in several chunks. The caller must set |in_final| to
+ * nonzero if the given input is the last block of the compressed
+ * header.
+ *
+ * This function returns the number of bytes processed if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Inflation process has failed.
+ * :enum:`NGHTTP2_ERR_BUFFER_ERROR`
+ * The header field name or value is too large.
+ *
+ * Example follows::
+ *
+ * int inflate_header_block(nghttp2_hd_inflater *hd_inflater,
+ * uint8_t *in, size_t inlen, int final)
+ * {
+ * ssize_t rv;
+ *
+ * for(;;) {
+ * nghttp2_nv nv;
+ * int inflate_flags = 0;
+ *
+ * rv = nghttp2_hd_inflate_hd(hd_inflater, &nv, &inflate_flags,
+ * in, inlen, final);
+ *
+ * if(rv < 0) {
+ * fprintf(stderr, "inflate failed with error code %zd", rv);
+ * return -1;
+ * }
+ *
+ * in += rv;
+ * inlen -= rv;
+ *
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ * fwrite(nv.name, nv.namelen, 1, stderr);
+ * fprintf(stderr, ": ");
+ * fwrite(nv.value, nv.valuelen, 1, stderr);
+ * fprintf(stderr, "\n");
+ * }
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
+ * nghttp2_hd_inflate_end_headers(hd_inflater);
+ * break;
+ * }
+ * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
+ * inlen == 0) {
+ * break;
+ * }
+ * }
+ *
+ * return 0;
+ * }
+ *
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out,
+ int *inflate_flags, uint8_t *in,
+ size_t inlen, int in_final);
+
+/**
+ * @function
+ *
+ * Inflates name/value block stored in |in| with length |inlen|. This
+ * function performs decompression. For each successful emission of
+ * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
+ * |*inflate_flags| and name/value pair is assigned to the |nv_out|
+ * and the function returns. The caller must not free the members of
+ * |nv_out|.
+ *
+ * The |nv_out| may include pointers to the memory region in the |in|.
+ * The caller must retain the |in| while the |nv_out| is used.
+ *
+ * The application should call this function repeatedly until the
+ * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
+ * return value is non-negative. If that happens, all given input
+ * data (|inlen| bytes) are processed successfully. Then the
+ * application must call `nghttp2_hd_inflate_end_headers()` to prepare
+ * for the next header block input.
+ *
+ * In other words, if |in_final| is nonzero, and this function returns
+ * |inlen|, you can assert that :enum:`NGHTTP2_HD_INFLATE_FINAL` is
+ * set in |*inflate_flags|.
+ *
+ * The caller can feed complete compressed header block. It also can
+ * feed it in several chunks. The caller must set |in_final| to
+ * nonzero if the given input is the last block of the compressed
+ * header.
+ *
+ * This function returns the number of bytes processed if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Inflation process has failed.
+ * :enum:`NGHTTP2_ERR_BUFFER_ERROR`
+ * The header field name or value is too large.
+ *
+ * Example follows::
+ *
+ * int inflate_header_block(nghttp2_hd_inflater *hd_inflater,
+ * uint8_t *in, size_t inlen, int final)
+ * {
+ * ssize_t rv;
+ *
+ * for(;;) {
+ * nghttp2_nv nv;
+ * int inflate_flags = 0;
+ *
+ * rv = nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags,
+ * in, inlen, final);
+ *
+ * if(rv < 0) {
+ * fprintf(stderr, "inflate failed with error code %zd", rv);
+ * return -1;
+ * }
+ *
+ * in += rv;
+ * inlen -= rv;
+ *
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ * fwrite(nv.name, nv.namelen, 1, stderr);
+ * fprintf(stderr, ": ");
+ * fwrite(nv.value, nv.valuelen, 1, stderr);
+ * fprintf(stderr, "\n");
+ * }
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
+ * nghttp2_hd_inflate_end_headers(hd_inflater);
+ * break;
+ * }
+ * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
+ * inlen == 0) {
+ * break;
+ * }
+ * }
+ *
+ * return 0;
+ * }
+ *
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out,
+ int *inflate_flags,
+ const uint8_t *in, size_t inlen,
+ int in_final);
+
+/**
+ * @function
+ *
+ * Signals the end of decompression for one header block.
+ *
+ * This function returns 0 if it succeeds. Currently this function
+ * always succeeds.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Returns the number of entries that header table of |inflater|
+ * contains. This is the sum of the number of static table and
+ * dynamic table, so the return value is at least 61.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Returns the table entry denoted by |idx| from header table of
+ * |inflater|. The |idx| is 1-based, and idx=1 returns first entry of
+ * static table. idx=62 returns first entry of dynamic table if it
+ * exists. Specifying idx=0 is error, and this function returns NULL.
+ * If |idx| is strictly greater than the number of entries the tables
+ * contain, this function returns NULL.
+ */
+NGHTTP2_EXTERN
+const nghttp2_nv *
+nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx);
+
+/**
+ * @function
+ *
+ * Returns the used dynamic table size, including the overhead 32
+ * bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Returns the maximum dynamic table size.
+ */
+NGHTTP2_EXTERN
+size_t
+nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater);
+
+struct nghttp2_stream;
+
+/**
+ * @struct
+ *
+ * The structure to represent HTTP/2 stream. The details of this
+ * structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_stream nghttp2_stream;
+
+/**
+ * @function
+ *
+ * Returns pointer to :type:`nghttp2_stream` object denoted by
+ * |stream_id|. If stream was not found, returns NULL.
+ *
+ * Returns imaginary root stream (see
+ * `nghttp2_session_get_root_stream()`) if 0 is given in |stream_id|.
+ *
+ * Unless |stream_id| == 0, the returned pointer is valid until next
+ * call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
+ * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @enum
+ *
+ * State of stream as described in RFC 7540.
+ */
+typedef enum {
+ /**
+ * idle state.
+ */
+ NGHTTP2_STREAM_STATE_IDLE = 1,
+ /**
+ * open state.
+ */
+ NGHTTP2_STREAM_STATE_OPEN,
+ /**
+ * reserved (local) state.
+ */
+ NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
+ /**
+ * reserved (remote) state.
+ */
+ NGHTTP2_STREAM_STATE_RESERVED_REMOTE,
+ /**
+ * half closed (local) state.
+ */
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL,
+ /**
+ * half closed (remote) state.
+ */
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE,
+ /**
+ * closed state.
+ */
+ NGHTTP2_STREAM_STATE_CLOSED
+} nghttp2_stream_proto_state;
+
+/**
+ * @function
+ *
+ * Returns state of |stream|. The root stream retrieved by
+ * `nghttp2_session_get_root_stream()` will have stream state
+ * :enum:`NGHTTP2_STREAM_STATE_IDLE`.
+ */
+NGHTTP2_EXTERN nghttp2_stream_proto_state
+nghttp2_stream_get_state(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns root of dependency tree, which is imaginary stream with
+ * stream ID 0. The returned pointer is valid until |session| is
+ * freed by `nghttp2_session_del()`.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_session_get_root_stream(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the parent stream of |stream| in dependency tree. Returns
+ * NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_parent(nghttp2_stream *stream);
+
+NGHTTP2_EXTERN int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the next sibling stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_next_sibling(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the previous sibling stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_previous_sibling(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the first child stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_first_child(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns dependency weight to the parent stream of |stream|.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the sum of the weight for |stream|'s children.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library outputs debug logging.
+ * The function is called with arguments suitable for ``vfprintf(3)``
+ *
+ * The debug output is only enabled if the library is built with
+ * ``DEBUGBUILD`` macro defined.
+ */
+typedef void (*nghttp2_debug_vprintf_callback)(const char *format,
+ va_list args);
+
+/**
+ * @function
+ *
+ * Sets a debug output callback called by the library when built with
+ * ``DEBUGBUILD`` macro defined. If this option is not used, debug
+ * log is written into standard error output.
+ *
+ * For builds without ``DEBUGBUILD`` macro defined, this function is
+ * noop.
+ *
+ * Note that building with ``DEBUGBUILD`` may cause significant
+ * performance penalty to libnghttp2 because of extra processing. It
+ * should be used for debugging purpose only.
+ *
+ * .. Warning::
+ *
+ * Building with ``DEBUGBUILD`` may cause significant performance
+ * penalty to libnghttp2 because of extra processing. It should be
+ * used for debugging purpose only. We write this two times because
+ * this is important.
+ */
+NGHTTP2_EXTERN void nghttp2_set_debug_vprintf_callback(
+ nghttp2_debug_vprintf_callback debug_vprintf_callback);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NGHTTP2_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_buf.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_buf.c
new file mode 100644
index 00000000..b40d5672
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_buf.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_buf.h"
+
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_debug.h"
+
+void nghttp2_buf_init(nghttp2_buf *buf) {
+ buf->begin = NULL;
+ buf->end = NULL;
+ buf->pos = NULL;
+ buf->last = NULL;
+ buf->mark = NULL;
+}
+
+int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) {
+ nghttp2_buf_init(buf);
+ return nghttp2_buf_reserve(buf, initial, mem);
+}
+
+void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) {
+ if (buf == NULL) {
+ return;
+ }
+
+ nghttp2_mem_free(mem, buf->begin);
+ buf->begin = NULL;
+}
+
+int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
+ uint8_t *ptr;
+ size_t cap;
+
+ cap = nghttp2_buf_cap(buf);
+
+ if (cap >= new_cap) {
+ return 0;
+ }
+
+ new_cap = nghttp2_max(new_cap, cap * 2);
+
+ ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
+ if (ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ buf->pos = ptr + (buf->pos - buf->begin);
+ buf->last = ptr + (buf->last - buf->begin);
+ buf->mark = ptr + (buf->mark - buf->begin);
+ buf->begin = ptr;
+ buf->end = ptr + new_cap;
+
+ return 0;
+}
+
+void nghttp2_buf_reset(nghttp2_buf *buf) {
+ buf->pos = buf->last = buf->mark = buf->begin;
+}
+
+void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
+ buf->begin = buf->pos = buf->last = buf->mark = begin;
+ buf->end = begin + len;
+}
+
+static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length,
+ nghttp2_mem *mem) {
+ int rv;
+
+ *chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
+ if (*chain == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ (*chain)->next = NULL;
+
+ rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem);
+ if (rv != 0) {
+ nghttp2_mem_free(mem, *chain);
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ return 0;
+}
+
+static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) {
+ nghttp2_buf_free(&chain->buf, mem);
+ nghttp2_mem_free(mem, chain);
+}
+
+int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
+ nghttp2_mem *mem) {
+ return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem);
+}
+
+int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t offset, nghttp2_mem *mem) {
+ return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset,
+ mem);
+}
+
+int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t chunk_keep, size_t offset,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_buf_chain *chain;
+
+ if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ rv = buf_chain_new(&chain, chunk_length, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ bufs->mem = mem;
+ bufs->offset = offset;
+
+ bufs->head = chain;
+ bufs->cur = bufs->head;
+
+ nghttp2_buf_shift_right(&bufs->cur->buf, offset);
+
+ bufs->chunk_length = chunk_length;
+ bufs->chunk_used = 1;
+ bufs->max_chunk = max_chunk;
+ bufs->chunk_keep = chunk_keep;
+
+ return 0;
+}
+
+int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
+ int rv;
+ nghttp2_buf_chain *chain;
+
+ if (chunk_length < bufs->offset) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ rv = buf_chain_new(&chain, chunk_length, bufs->mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ nghttp2_bufs_free(bufs);
+
+ bufs->head = chain;
+ bufs->cur = bufs->head;
+
+ nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
+
+ bufs->chunk_length = chunk_length;
+ bufs->chunk_used = 1;
+
+ return 0;
+}
+
+void nghttp2_bufs_free(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *chain, *next_chain;
+
+ if (bufs == NULL) {
+ return;
+ }
+
+ for (chain = bufs->head; chain;) {
+ next_chain = chain->next;
+
+ buf_chain_del(chain, bufs->mem);
+
+ chain = next_chain;
+ }
+
+ bufs->head = NULL;
+}
+
+int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
+ nghttp2_mem *mem) {
+ nghttp2_buf_chain *chain;
+
+ chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
+ if (chain == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ chain->next = NULL;
+
+ nghttp2_buf_wrap_init(&chain->buf, begin, len);
+
+ bufs->mem = mem;
+ bufs->offset = 0;
+
+ bufs->head = chain;
+ bufs->cur = bufs->head;
+
+ bufs->chunk_length = len;
+ bufs->chunk_used = 1;
+ bufs->max_chunk = 1;
+ bufs->chunk_keep = 1;
+
+ return 0;
+}
+
+int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
+ size_t veclen, nghttp2_mem *mem) {
+ size_t i = 0;
+ nghttp2_buf_chain *cur_chain;
+ nghttp2_buf_chain *head_chain;
+ nghttp2_buf_chain **dst_chain = &head_chain;
+
+ if (veclen == 0) {
+ return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem);
+ }
+
+ head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
+ if (head_chain == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ for (i = 0; i < veclen; ++i) {
+ cur_chain = &head_chain[i];
+ cur_chain->next = NULL;
+ nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
+
+ *dst_chain = cur_chain;
+ dst_chain = &cur_chain->next;
+ }
+
+ bufs->mem = mem;
+ bufs->offset = 0;
+
+ bufs->head = head_chain;
+ bufs->cur = bufs->head;
+
+ /* We don't use chunk_length since no allocation is expected. */
+ bufs->chunk_length = 0;
+ bufs->chunk_used = veclen;
+ bufs->max_chunk = veclen;
+ bufs->chunk_keep = veclen;
+
+ return 0;
+}
+
+void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
+ if (bufs == NULL) {
+ return;
+ }
+
+ if (bufs->head) {
+ nghttp2_mem_free(bufs->mem, bufs->head);
+ }
+}
+
+void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *ci;
+
+ for (ci = bufs->cur; ci; ci = ci->next) {
+ if (nghttp2_buf_len(&ci->buf) == 0) {
+ return;
+ } else {
+ bufs->cur = ci;
+ }
+ }
+}
+
+size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *ci;
+ size_t len;
+
+ len = 0;
+ for (ci = bufs->head; ci; ci = ci->next) {
+ len += nghttp2_buf_len(&ci->buf);
+ }
+
+ return len;
+}
+
+static int bufs_alloc_chain(nghttp2_bufs *bufs) {
+ int rv;
+ nghttp2_buf_chain *chain;
+
+ if (bufs->cur->next) {
+ bufs->cur = bufs->cur->next;
+
+ return 0;
+ }
+
+ if (bufs->max_chunk == bufs->chunk_used) {
+ return NGHTTP2_ERR_BUFFER_ERROR;
+ }
+
+ rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",
+ bufs->chunk_length, bufs, bufs->chunk_used);
+
+ ++bufs->chunk_used;
+
+ bufs->cur->next = chain;
+ bufs->cur = chain;
+
+ nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
+
+ return 0;
+}
+
+int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
+ int rv;
+ size_t nwrite;
+ nghttp2_buf *buf;
+ const uint8_t *p;
+
+ p = data;
+
+ while (len) {
+ buf = &bufs->cur->buf;
+
+ nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
+ if (nwrite == 0) {
+ rv = bufs_alloc_chain(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ buf->last = nghttp2_cpymem(buf->last, p, nwrite);
+ p += nwrite;
+ len -= nwrite;
+ }
+
+ return 0;
+}
+
+static int bufs_ensure_addb(nghttp2_bufs *bufs) {
+ int rv;
+ nghttp2_buf *buf;
+
+ buf = &bufs->cur->buf;
+
+ if (nghttp2_buf_avail(buf) > 0) {
+ return 0;
+ }
+
+ rv = bufs_alloc_chain(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last++ = b;
+
+ return 0;
+}
+
+int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last = b;
+
+ return 0;
+}
+
+int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last++ |= b;
+
+ return 0;
+}
+
+int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last |= b;
+
+ return 0;
+}
+
+ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
+ size_t len;
+ nghttp2_buf_chain *chain;
+ nghttp2_buf *buf;
+ uint8_t *res;
+ nghttp2_buf resbuf;
+
+ len = 0;
+
+ for (chain = bufs->head; chain; chain = chain->next) {
+ len += nghttp2_buf_len(&chain->buf);
+ }
+
+ if (len == 0) {
+ res = NULL;
+ return 0;
+ }
+
+ res = nghttp2_mem_malloc(bufs->mem, len);
+ if (res == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_buf_wrap_init(&resbuf, res, len);
+
+ for (chain = bufs->head; chain; chain = chain->next) {
+ buf = &chain->buf;
+ resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
+ }
+
+ *out = res;
+
+ return (ssize_t)len;
+}
+
+size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
+ size_t len;
+ nghttp2_buf_chain *chain;
+ nghttp2_buf *buf;
+ nghttp2_buf resbuf;
+
+ len = nghttp2_bufs_len(bufs);
+
+ nghttp2_buf_wrap_init(&resbuf, out, len);
+
+ for (chain = bufs->head; chain; chain = chain->next) {
+ buf = &chain->buf;
+ resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
+ }
+
+ return len;
+}
+
+void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *chain, *ci;
+ size_t k;
+
+ k = bufs->chunk_keep;
+
+ for (ci = bufs->head; ci; ci = ci->next) {
+ nghttp2_buf_reset(&ci->buf);
+ nghttp2_buf_shift_right(&ci->buf, bufs->offset);
+
+ if (--k == 0) {
+ break;
+ }
+ }
+
+ if (ci) {
+ chain = ci->next;
+ ci->next = NULL;
+
+ for (ci = chain; ci;) {
+ chain = ci->next;
+
+ buf_chain_del(ci, bufs->mem);
+
+ ci = chain;
+ }
+
+ bufs->chunk_used = bufs->chunk_keep;
+ }
+
+ bufs->cur = bufs->head;
+}
+
+int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
+
+int nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *chain;
+
+ chain = bufs->cur->next;
+
+ return chain && nghttp2_buf_len(&chain->buf);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_buf.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_buf.h
new file mode 100644
index 00000000..7e33a528
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_buf.h
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_BUF_H
+#define NGHTTP2_BUF_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#include "nghttp2_int.h"
+#include "nghttp2_mem.h"
+
+typedef struct {
+ /* This points to the beginning of the buffer. The effective range
+ of buffer is [begin, end). */
+ uint8_t *begin;
+ /* This points to the memory one byte beyond the end of the
+ buffer. */
+ uint8_t *end;
+ /* The position indicator for effective start of the buffer. pos <=
+ last must be hold. */
+ uint8_t *pos;
+ /* The position indicator for effective one beyond of the end of the
+ buffer. last <= end must be hold. */
+ uint8_t *last;
+ /* Mark arbitrary position in buffer [begin, end) */
+ uint8_t *mark;
+} nghttp2_buf;
+
+#define nghttp2_buf_len(BUF) ((size_t)((BUF)->last - (BUF)->pos))
+#define nghttp2_buf_avail(BUF) ((size_t)((BUF)->end - (BUF)->last))
+#define nghttp2_buf_mark_avail(BUF) ((size_t)((BUF)->mark - (BUF)->last))
+#define nghttp2_buf_cap(BUF) ((size_t)((BUF)->end - (BUF)->begin))
+
+#define nghttp2_buf_pos_offset(BUF) ((size_t)((BUF)->pos - (BUF)->begin))
+#define nghttp2_buf_last_offset(BUF) ((size_t)((BUF)->last - (BUF)->begin))
+
+#define nghttp2_buf_shift_right(BUF, AMT) \
+ do { \
+ (BUF)->pos += AMT; \
+ (BUF)->last += AMT; \
+ } while (0)
+
+#define nghttp2_buf_shift_left(BUF, AMT) \
+ do { \
+ (BUF)->pos -= AMT; \
+ (BUF)->last -= AMT; \
+ } while (0)
+
+/*
+ * Initializes the |buf|. No memory is allocated in this function. Use
+ * nghttp2_buf_reserve() to allocate memory.
+ */
+void nghttp2_buf_init(nghttp2_buf *buf);
+
+/*
+ * Initializes the |buf| and allocates at least |initial| bytes of
+ * memory.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem);
+
+/*
+ * Frees buffer in |buf|.
+ */
+void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem);
+
+/*
+ * Extends buffer so that nghttp2_buf_cap() returns at least
+ * |new_cap|. If extensions took place, buffer pointers in |buf| will
+ * change.
+ *
+ * This function returns 0 if it succeeds, or one of the followings
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem);
+
+/*
+ * Resets pos, last, mark member of |buf| to buf->begin.
+ */
+void nghttp2_buf_reset(nghttp2_buf *buf);
+
+/*
+ * Initializes |buf| using supplied buffer |begin| of length
+ * |len|. Semantically, the application should not call *_reserve() or
+ * nghttp2_free() functions for |buf|.
+ */
+void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
+
+struct nghttp2_buf_chain;
+
+typedef struct nghttp2_buf_chain nghttp2_buf_chain;
+
+/* Chains 2 buffers */
+struct nghttp2_buf_chain {
+ /* Points to the subsequent buffer. NULL if there is no such
+ buffer. */
+ nghttp2_buf_chain *next;
+ nghttp2_buf buf;
+};
+
+typedef struct {
+ /* Points to the first buffer */
+ nghttp2_buf_chain *head;
+ /* Buffer pointer where write occurs. */
+ nghttp2_buf_chain *cur;
+ /* Memory allocator */
+ nghttp2_mem *mem;
+ /* The buffer capacity of each buf. This field may be 0 if
+ nghttp2_bufs is initialized by nghttp2_bufs_wrap_init* family
+ functions. */
+ size_t chunk_length;
+ /* The maximum number of nghttp2_buf_chain */
+ size_t max_chunk;
+ /* The number of nghttp2_buf_chain allocated */
+ size_t chunk_used;
+ /* The number of nghttp2_buf_chain to keep on reset */
+ size_t chunk_keep;
+ /* pos offset from begin in each buffers. On initialization and
+ reset, buf->pos and buf->last are positioned at buf->begin +
+ offset. */
+ size_t offset;
+} nghttp2_bufs;
+
+/*
+ * This is the same as calling nghttp2_bufs_init2 with the given
+ * arguments and offset = 0.
+ */
+int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
+ nghttp2_mem *mem);
+
+/*
+ * This is the same as calling nghttp2_bufs_init3 with the given
+ * arguments and chunk_keep = max_chunk.
+ */
+int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t offset, nghttp2_mem *mem);
+
+/*
+ * Initializes |bufs|. Each buffer size is given in the
+ * |chunk_length|. The maximum number of buffers is given in the
+ * |max_chunk|. On reset, first |chunk_keep| buffers are kept and
+ * remaining buffers are deleted. Each buffer will have bufs->pos and
+ * bufs->last shifted to left by |offset| bytes on creation and reset.
+ *
+ * This function allocates first buffer. bufs->head and bufs->cur
+ * will point to the first buffer after this call.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * chunk_keep is 0; or max_chunk < chunk_keep; or offset is too
+ * long.
+ */
+int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t chunk_keep, size_t offset,
+ nghttp2_mem *mem);
+
+/*
+ * Frees any related resources to the |bufs|.
+ */
+void nghttp2_bufs_free(nghttp2_bufs *bufs);
+
+/*
+ * Initializes |bufs| using supplied buffer |begin| of length |len|.
+ * The first buffer bufs->head uses buffer |begin|. The buffer size
+ * is fixed and no extra chunk buffer is allocated. In other
+ * words, max_chunk = chunk_keep = 1. To free the resource allocated
+ * for |bufs|, use nghttp2_bufs_wrap_free().
+ *
+ * Don't use the function which performs allocation, such as
+ * nghttp2_bufs_realloc().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
+ nghttp2_mem *mem);
+
+/*
+ * Initializes |bufs| using supplied |veclen| size of buf vector
+ * |vec|. The number of buffers is fixed and no extra chunk buffer is
+ * allocated. In other words, max_chunk = chunk_keep = |in_len|. To
+ * free the resource allocated for |bufs|, use
+ * nghttp2_bufs_wrap_free().
+ *
+ * Don't use the function which performs allocation, such as
+ * nghttp2_bufs_realloc().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
+ size_t veclen, nghttp2_mem *mem);
+
+/*
+ * Frees any related resource to the |bufs|. This function does not
+ * free supplied buffer provided in nghttp2_bufs_wrap_init().
+ */
+void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
+
+/*
+ * Reallocates internal buffer using |chunk_length|. The max_chunk,
+ * chunk_keep and offset do not change. After successful allocation
+ * of new buffer, previous buffers are deallocated without copying
+ * anything into new buffers. chunk_used is reset to 1.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * chunk_length < offset
+ */
+int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length);
+
+/*
+ * Appends the |data| of length |len| to the |bufs|. The write starts
+ * at bufs->cur->buf.last. A new buffers will be allocated to store
+ * all data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
+
+/*
+ * Appends a single byte |b| to the |bufs|. The write starts at
+ * bufs->cur->buf.last. A new buffers will be allocated to store all
+ * data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
+
+/*
+ * Behaves like nghttp2_bufs_addb(), but this does not update
+ * buf->last pointer.
+ */
+int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
+
+#define nghttp2_bufs_fast_addb(BUFS, B) \
+ do { \
+ *(BUFS)->cur->buf.last++ = B; \
+ } while (0)
+
+#define nghttp2_bufs_fast_addb_hold(BUFS, B) \
+ do { \
+ *(BUFS)->cur->buf.last = B; \
+ } while (0)
+
+/*
+ * Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
+ * will be allocated if necessary.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
+
+/*
+ * Behaves like nghttp2_bufs_orb(), but does not update buf->last
+ * pointer.
+ */
+int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
+
+#define nghttp2_bufs_fast_orb(BUFS, B) \
+ do { \
+ uint8_t **p = &(BUFS)->cur->buf.last; \
+ **p = (uint8_t)(**p | (B)); \
+ ++(*p); \
+ } while (0)
+
+#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
+ do { \
+ uint8_t *p = (BUFS)->cur->buf.last; \
+ *p = (uint8_t)(*p | (B)); \
+ } while (0)
+
+/*
+ * Copies all data stored in |bufs| to the contiguous buffer. This
+ * function allocates the contiguous memory to store all data in
+ * |bufs| and assigns it to |*out|.
+ *
+ * The contents of |bufs| is left unchanged.
+ *
+ * This function returns the length of copied data and assigns the
+ * pointer to copied data to |*out| if it succeeds, or one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
+
+/*
+ * Copies all data stored in |bufs| to |out|. This function assumes
+ * that the buffer space pointed by |out| has at least
+ * nghttp2_bufs(bufs) bytes.
+ *
+ * The contents of |bufs| is left unchanged.
+ *
+ * This function returns the length of copied data.
+ */
+size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
+
+/*
+ * Resets |bufs| and makes the buffers empty.
+ */
+void nghttp2_bufs_reset(nghttp2_bufs *bufs);
+
+/*
+ * Moves bufs->cur to bufs->cur->next. If resulting bufs->cur is
+ * NULL, this function allocates new buffers and bufs->cur points to
+ * it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_advance(nghttp2_bufs *bufs);
+
+/* Sets bufs->cur to bufs->head */
+#define nghttp2_bufs_rewind(BUFS) \
+ do { \
+ (BUFS)->cur = (BUFS)->head; \
+ } while (0)
+
+/*
+ * Move bufs->cur, from the current position, using next member, to
+ * the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
+ * which satisfies nghttp2_buf_len(buf) == 0. If
+ * nghttp2_buf_len(&bufs->cur->buf) == 0 or bufs->cur->next is NULL,
+ * bufs->cur is unchanged.
+ */
+void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
+
+/*
+ * Returns nonzero if bufs->cur->next is not empty.
+ */
+int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
+
+#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
+
+/*
+ * Returns the total buffer length of |bufs|.
+ */
+size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
+
+#endif /* NGHTTP2_BUF_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_callbacks.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_callbacks.c
new file mode 100644
index 00000000..a2f7e3fb
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_callbacks.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_callbacks.h"
+#include
+#include
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+#if INFRA_MEM_STATS
+#define NGHTTP2_CB_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "nghttp2.cb")
+#define NGHTTP2_CB_FREE(ptr) LITE_free(ptr)
+#else
+#define NGHTTP2_CB_MALLOC(size) HAL_Malloc(size)
+#define NGHTTP2_CB_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr) {
+ *callbacks_ptr = NGHTTP2_CB_MALLOC(sizeof(nghttp2_session_callbacks));
+
+ if (*callbacks_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ memset(*callbacks_ptr, 0, sizeof(nghttp2_session_callbacks));
+ return 0;
+}
+
+void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks) {
+ NGHTTP2_CB_FREE(callbacks);
+}
+
+void nghttp2_session_callbacks_set_send_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) {
+ cbs->send_callback = send_callback;
+}
+
+void nghttp2_session_callbacks_set_recv_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
+ cbs->recv_callback = recv_callback;
+}
+
+void nghttp2_session_callbacks_set_on_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_recv_callback on_frame_recv_callback) {
+ cbs->on_frame_recv_callback = on_frame_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
+ cbs->on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
+ cbs->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_before_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_before_frame_send_callback before_frame_send_callback) {
+ cbs->before_frame_send_callback = before_frame_send_callback;
+}
+
+void nghttp2_session_callbacks_set_on_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_send_callback on_frame_send_callback) {
+ cbs->on_frame_send_callback = on_frame_send_callback;
+}
+
+void nghttp2_session_callbacks_set_on_frame_not_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
+ cbs->on_frame_not_send_callback = on_frame_not_send_callback;
+}
+
+void nghttp2_session_callbacks_set_on_stream_close_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_stream_close_callback on_stream_close_callback) {
+ cbs->on_stream_close_callback = on_stream_close_callback;
+}
+
+void nghttp2_session_callbacks_set_on_begin_headers_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_headers_callback on_begin_headers_callback) {
+ cbs->on_begin_headers_callback = on_begin_headers_callback;
+}
+
+void nghttp2_session_callbacks_set_on_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback on_header_callback) {
+ cbs->on_header_callback = on_header_callback;
+}
+
+void nghttp2_session_callbacks_set_on_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback2 on_header_callback2) {
+ cbs->on_header_callback2 = on_header_callback2;
+}
+
+void nghttp2_session_callbacks_set_on_invalid_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback on_invalid_header_callback) {
+ cbs->on_invalid_header_callback = on_invalid_header_callback;
+}
+
+void nghttp2_session_callbacks_set_on_invalid_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
+ cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
+}
+
+void nghttp2_session_callbacks_set_select_padding_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_select_padding_callback select_padding_callback) {
+ cbs->select_padding_callback = select_padding_callback;
+}
+
+void nghttp2_session_callbacks_set_data_source_read_length_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_data_source_read_length_callback data_source_read_length_callback) {
+ cbs->read_length_callback = data_source_read_length_callback;
+}
+
+void nghttp2_session_callbacks_set_on_begin_frame_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_frame_callback on_begin_frame_callback) {
+ cbs->on_begin_frame_callback = on_begin_frame_callback;
+}
+
+void nghttp2_session_callbacks_set_send_data_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_send_data_callback send_data_callback) {
+ cbs->send_data_callback = send_data_callback;
+}
+
+void nghttp2_session_callbacks_set_pack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_pack_extension_callback pack_extension_callback) {
+ cbs->pack_extension_callback = pack_extension_callback;
+}
+
+void nghttp2_session_callbacks_set_unpack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_unpack_extension_callback unpack_extension_callback) {
+ cbs->unpack_extension_callback = unpack_extension_callback;
+}
+
+void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
+ cbs->on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_error_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) {
+ cbs->error_callback = error_callback;
+}
+
+void nghttp2_session_callbacks_set_error_callback2(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
+ cbs->error_callback2 = error_callback2;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_callbacks.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_callbacks.h
new file mode 100644
index 00000000..542df190
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_callbacks.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_CALLBACKS_H
+#define NGHTTP2_CALLBACKS_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/*
+ * Callback functions.
+ */
+struct nghttp2_session_callbacks {
+ /**
+ * Callback function invoked when the session wants to send data to
+ * the remote peer. This callback is not necessary if the
+ * application uses solely `nghttp2_session_mem_send()` to serialize
+ * data to transmit.
+ */
+ nghttp2_send_callback send_callback;
+ /**
+ * Callback function invoked when the session wants to receive data
+ * from the remote peer. This callback is not necessary if the
+ * application uses solely `nghttp2_session_mem_recv()` to process
+ * received data.
+ */
+ nghttp2_recv_callback recv_callback;
+ /**
+ * Callback function invoked by `nghttp2_session_recv()` when a
+ * frame is received.
+ */
+ nghttp2_on_frame_recv_callback on_frame_recv_callback;
+ /**
+ * Callback function invoked by `nghttp2_session_recv()` when an
+ * invalid non-DATA frame is received.
+ */
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback;
+ /**
+ * Callback function invoked when a chunk of data in DATA frame is
+ * received.
+ */
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
+ /**
+ * Callback function invoked before a non-DATA frame is sent.
+ */
+ nghttp2_before_frame_send_callback before_frame_send_callback;
+ /**
+ * Callback function invoked after a frame is sent.
+ */
+ nghttp2_on_frame_send_callback on_frame_send_callback;
+ /**
+ * The callback function invoked when a non-DATA frame is not sent
+ * because of an error.
+ */
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback;
+ /**
+ * Callback function invoked when the stream is closed.
+ */
+ nghttp2_on_stream_close_callback on_stream_close_callback;
+ /**
+ * Callback function invoked when the reception of header block in
+ * HEADERS or PUSH_PROMISE is started.
+ */
+ nghttp2_on_begin_headers_callback on_begin_headers_callback;
+ /**
+ * Callback function invoked when a header name/value pair is
+ * received.
+ */
+ nghttp2_on_header_callback on_header_callback;
+ nghttp2_on_header_callback2 on_header_callback2;
+ /**
+ * Callback function invoked when a invalid header name/value pair
+ * is received which is silently ignored if these callbacks are not
+ * set.
+ */
+ nghttp2_on_invalid_header_callback on_invalid_header_callback;
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
+ /**
+ * Callback function invoked when the library asks application how
+ * many padding bytes are required for the transmission of the given
+ * frame.
+ */
+ nghttp2_select_padding_callback select_padding_callback;
+ /**
+ * The callback function used to determine the length allowed in
+ * `nghttp2_data_source_read_callback()`
+ */
+ nghttp2_data_source_read_length_callback read_length_callback;
+ /**
+ * Sets callback function invoked when a frame header is received.
+ */
+ nghttp2_on_begin_frame_callback on_begin_frame_callback;
+ nghttp2_send_data_callback send_data_callback;
+ nghttp2_pack_extension_callback pack_extension_callback;
+ nghttp2_unpack_extension_callback unpack_extension_callback;
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
+ nghttp2_error_callback error_callback;
+ nghttp2_error_callback2 error_callback2;
+};
+
+#endif /* NGHTTP2_CALLBACKS_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_debug.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_debug.c
new file mode 100644
index 00000000..6533f989
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_debug.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_debug.h"
+
+#include
+
+#ifdef DEBUGBUILD
+
+static void nghttp2_default_debug_vfprintf_callback(const char *fmt,
+ va_list args) {
+ vfprintf(stderr, fmt, args);
+}
+
+static nghttp2_debug_vprintf_callback static_debug_vprintf_callback =
+ nghttp2_default_debug_vfprintf_callback;
+
+void nghttp2_debug_vprintf(const char *format, ...) {
+ if (static_debug_vprintf_callback) {
+ va_list args;
+ va_start(args, format);
+ static_debug_vprintf_callback(format, args);
+ va_end(args);
+ }
+}
+
+void nghttp2_set_debug_vprintf_callback(
+ nghttp2_debug_vprintf_callback debug_vprintf_callback) {
+ static_debug_vprintf_callback = debug_vprintf_callback;
+}
+
+#else /* !DEBUGBUILD */
+
+void nghttp2_set_debug_vprintf_callback(
+ nghttp2_debug_vprintf_callback debug_vprintf_callback) {
+ (void)debug_vprintf_callback;
+}
+
+#endif /* !DEBUGBUILD */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_debug.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_debug.h
new file mode 100644
index 00000000..6fed6ea0
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_debug.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_DEBUG_H
+#define NGHTTP2_DEBUG_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#ifdef DEBUGBUILD
+#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
+void nghttp2_debug_vprintf(const char *format, ...);
+#else
+#define DEBUGF(...) \
+ do { \
+ } while (0)
+#endif
+
+#endif /* NGHTTP2_DEBUG_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_frame.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_frame.c
new file mode 100644
index 00000000..76c919ec
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_frame.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_frame.h"
+
+#include
+#include
+#include
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_net.h"
+#include "nghttp2_priority_spec.h"
+#include "nghttp2_debug.h"
+
+void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) {
+ nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
+ buf[3] = hd->type;
+ buf[4] = hd->flags;
+ nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id);
+ /* ignore hd->reserved for now */
+}
+
+void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf) {
+ hd->length = nghttp2_get_uint32(&buf[0]) >> 8;
+ hd->type = buf[3];
+ hd->flags = buf[4];
+ hd->stream_id = nghttp2_get_uint32(&buf[5]) & NGHTTP2_STREAM_ID_MASK;
+ hd->reserved = 0;
+}
+
+void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
+ uint8_t flags, int32_t stream_id) {
+ hd->length = length;
+ hd->type = type;
+ hd->flags = flags;
+ hd->stream_id = stream_id;
+ hd->reserved = 0;
+}
+
+void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
+ int32_t stream_id, nghttp2_headers_category cat,
+ const nghttp2_priority_spec *pri_spec,
+ nghttp2_nv *nva, size_t nvlen) {
+ nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_HEADERS, flags, stream_id);
+ frame->padlen = 0;
+ frame->nva = nva;
+ frame->nvlen = nvlen;
+ frame->cat = cat;
+
+ if (pri_spec) {
+ frame->pri_spec = *pri_spec;
+ } else {
+ nghttp2_priority_spec_default_init(&frame->pri_spec);
+ }
+}
+
+void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem) {
+ nghttp2_nv_array_del(frame->nva, mem);
+}
+
+void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec) {
+ nghttp2_frame_hd_init(&frame->hd, NGHTTP2_PRIORITY_SPECLEN, NGHTTP2_PRIORITY,
+ NGHTTP2_FLAG_NONE, stream_id);
+ frame->pri_spec = *pri_spec;
+}
+
+void nghttp2_frame_priority_free(nghttp2_priority *frame) { (void)frame; }
+
+void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
+ uint32_t error_code) {
+ nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE,
+ stream_id);
+ frame->error_code = error_code;
+}
+
+void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame) { (void)frame; }
+
+void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
+ nghttp2_settings_entry *iv, size_t niv) {
+ nghttp2_frame_hd_init(&frame->hd, niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH,
+ NGHTTP2_SETTINGS, flags, 0);
+ frame->niv = niv;
+ frame->iv = iv;
+}
+
+void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem) {
+ nghttp2_mem_free(mem, frame->iv);
+}
+
+void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
+ int32_t stream_id,
+ int32_t promised_stream_id,
+ nghttp2_nv *nva, size_t nvlen) {
+ nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_PUSH_PROMISE, flags, stream_id);
+ frame->padlen = 0;
+ frame->nva = nva;
+ frame->nvlen = nvlen;
+ frame->promised_stream_id = promised_stream_id;
+ frame->reserved = 0;
+}
+
+void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame,
+ nghttp2_mem *mem) {
+ nghttp2_nv_array_del(frame->nva, mem);
+}
+
+void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
+ const uint8_t *opaque_data) {
+ nghttp2_frame_hd_init(&frame->hd, 8, NGHTTP2_PING, flags, 0);
+ if (opaque_data) {
+ memcpy(frame->opaque_data, opaque_data, sizeof(frame->opaque_data));
+ } else {
+ memset(frame->opaque_data, 0, sizeof(frame->opaque_data));
+ }
+}
+
+void nghttp2_frame_ping_free(nghttp2_ping *frame) { (void)frame; }
+
+void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
+ uint32_t error_code, uint8_t *opaque_data,
+ size_t opaque_data_len) {
+ nghttp2_frame_hd_init(&frame->hd, 8 + opaque_data_len, NGHTTP2_GOAWAY,
+ NGHTTP2_FLAG_NONE, 0);
+ frame->last_stream_id = last_stream_id;
+ frame->error_code = error_code;
+ frame->opaque_data = opaque_data;
+ frame->opaque_data_len = opaque_data_len;
+ frame->reserved = 0;
+}
+
+void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem) {
+ nghttp2_mem_free(mem, frame->opaque_data);
+}
+
+void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
+ uint8_t flags, int32_t stream_id,
+ int32_t window_size_increment) {
+ nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags, stream_id);
+ frame->window_size_increment = window_size_increment;
+ frame->reserved = 0;
+}
+
+void nghttp2_frame_window_update_free(nghttp2_window_update *frame) {
+ (void)frame;
+}
+
+size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) {
+ /* We have iframe->padlen == 0, but iframe->frame.hd.flags may have
+ NGHTTP2_FLAG_PADDED set. This happens when receiving
+ CONTINUATION frame, since we don't reset flags after HEADERS was
+ received. */
+ if (padlen == 0) {
+ return 0;
+ }
+ return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0);
+}
+
+void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
+ int32_t stream_id) {
+ /* At this moment, the length of DATA frame is unknown */
+ nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id);
+ frame->padlen = 0;
+}
+
+void nghttp2_frame_data_free(nghttp2_data *frame) { (void)frame; }
+
+void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
+ uint8_t flags, int32_t stream_id,
+ void *payload) {
+ nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id);
+ frame->payload = payload;
+}
+
+void nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; }
+
+void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
+ uint8_t *origin, size_t origin_len,
+ uint8_t *field_value, size_t field_value_len) {
+ nghttp2_ext_altsvc *altsvc;
+
+ nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len,
+ NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id);
+
+ altsvc = frame->payload;
+ altsvc->origin = origin;
+ altsvc->origin_len = origin_len;
+ altsvc->field_value = field_value;
+ altsvc->field_value_len = field_value_len;
+}
+
+void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
+ nghttp2_ext_altsvc *altsvc;
+
+ altsvc = frame->payload;
+ /* We use the same buffer for altsvc->origin and
+ altsvc->field_value. */
+ nghttp2_mem_free(mem, altsvc->origin);
+}
+
+size_t nghttp2_frame_priority_len(uint8_t flags) {
+ if (flags & NGHTTP2_FLAG_PRIORITY) {
+ return NGHTTP2_PRIORITY_SPECLEN;
+ }
+
+ return 0;
+}
+
+size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) {
+ return nghttp2_frame_priority_len(frame->hd.flags);
+}
+
+/*
+ * Call this function after payload was serialized, but not before
+ * changing buf->pos and serializing frame header.
+ *
+ * This function assumes bufs->cur points to the last buf chain of the
+ * frame(s).
+ *
+ * This function serializes frame header for HEADERS/PUSH_PROMISE and
+ * handles their successive CONTINUATION frames.
+ *
+ * We don't process any padding here.
+ */
+static int frame_pack_headers_shared(nghttp2_bufs *bufs,
+ nghttp2_frame_hd *frame_hd) {
+ nghttp2_buf *buf;
+ nghttp2_buf_chain *ci, *ce;
+ nghttp2_frame_hd hd;
+
+ buf = &bufs->head->buf;
+
+ hd = *frame_hd;
+ hd.length = nghttp2_buf_len(buf);
+
+ DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length);
+
+ /* We have multiple frame buffers, which means one or more
+ CONTINUATION frame is involved. Remove END_HEADERS flag from the
+ first frame. */
+ if (bufs->head != bufs->cur) {
+ hd.flags = (uint8_t)(hd.flags & ~NGHTTP2_FLAG_END_HEADERS);
+ }
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+ nghttp2_frame_pack_frame_hd(buf->pos, &hd);
+
+ if (bufs->head != bufs->cur) {
+ /* 2nd and later frames are CONTINUATION frames. */
+ hd.type = NGHTTP2_CONTINUATION;
+ /* We don't have no flags except for last CONTINUATION */
+ hd.flags = NGHTTP2_FLAG_NONE;
+
+ ce = bufs->cur;
+
+ for (ci = bufs->head->next; ci != ce; ci = ci->next) {
+ buf = &ci->buf;
+
+ hd.length = nghttp2_buf_len(buf);
+
+ DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+ nghttp2_frame_pack_frame_hd(buf->pos, &hd);
+ }
+
+ buf = &ci->buf;
+ hd.length = nghttp2_buf_len(buf);
+ /* Set END_HEADERS flag for last CONTINUATION */
+ hd.flags = NGHTTP2_FLAG_END_HEADERS;
+
+ DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+ nghttp2_frame_pack_frame_hd(buf->pos, &hd);
+ }
+
+ return 0;
+}
+
+int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
+ nghttp2_hd_deflater *deflater) {
+ size_t nv_offset;
+ int rv;
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ nv_offset = nghttp2_frame_headers_payload_nv_offset(frame);
+
+ buf = &bufs->cur->buf;
+
+ buf->pos += nv_offset;
+ buf->last = buf->pos;
+
+ /* This call will adjust buf->last to the correct position */
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ buf->pos -= nv_offset;
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
+ nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec);
+ }
+
+ frame->padlen = 0;
+ frame->hd.length = nghttp2_bufs_len(bufs);
+
+ return frame_pack_headers_shared(bufs, &frame->hd);
+}
+
+void nghttp2_frame_pack_priority_spec(uint8_t *buf,
+ const nghttp2_priority_spec *pri_spec) {
+ nghttp2_put_uint32be(buf, (uint32_t)pri_spec->stream_id);
+ if (pri_spec->exclusive) {
+ buf[0] |= 0x80;
+ }
+ buf[4] = (uint8_t)(pri_spec->weight - 1);
+}
+
+void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
+ const uint8_t *payload) {
+ int32_t dep_stream_id;
+ uint8_t exclusive;
+ int32_t weight;
+
+ dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+ exclusive = (payload[0] & 0x80) > 0;
+ weight = payload[4] + 1;
+
+ nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive);
+}
+
+int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
+ const uint8_t *payload) {
+ if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
+ nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
+ } else {
+ nghttp2_priority_spec_default_init(&frame->pri_spec);
+ }
+
+ frame->nva = NULL;
+ frame->nvlen = 0;
+
+ return 0;
+}
+
+int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= NGHTTP2_PRIORITY_SPECLEN);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec);
+
+ buf->last += NGHTTP2_PRIORITY_SPECLEN;
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
+ const uint8_t *payload) {
+ nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
+}
+
+int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
+ nghttp2_rst_stream *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= 4);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint32be(buf->last, frame->error_code);
+ buf->last += 4;
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
+ const uint8_t *payload) {
+ frame->error_code = nghttp2_get_uint32(payload);
+}
+
+int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ if (nghttp2_buf_avail(buf) < frame->hd.length) {
+ return NGHTTP2_ERR_FRAME_SIZE_ERROR;
+ }
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ buf->last +=
+ nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv);
+
+ return 0;
+}
+
+size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
+ const nghttp2_settings_entry *iv,
+ size_t niv) {
+ size_t i;
+ for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
+ nghttp2_put_uint16be(buf, (uint16_t)iv[i].settings_id);
+ nghttp2_put_uint32be(buf + 2, iv[i].value);
+ }
+ return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv;
+}
+
+void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
+ nghttp2_settings_entry *iv,
+ size_t niv) {
+ frame->iv = iv;
+ frame->niv = niv;
+}
+
+void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
+ const uint8_t *payload) {
+ iv->settings_id = nghttp2_get_uint16(&payload[0]);
+ iv->value = nghttp2_get_uint32(&payload[2]);
+}
+
+int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
+ size_t *niv_ptr,
+ const uint8_t *payload,
+ size_t payloadlen,
+ nghttp2_mem *mem) {
+ size_t i;
+
+ *niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
+
+ if (*niv_ptr == 0) {
+ *iv_ptr = NULL;
+
+ return 0;
+ }
+
+ *iv_ptr =
+ nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry));
+
+ if (*iv_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ for (i = 0; i < *niv_ptr; ++i) {
+ size_t off = i * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
+ nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]);
+ }
+
+ return 0;
+}
+
+int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
+ nghttp2_push_promise *frame,
+ nghttp2_hd_deflater *deflater) {
+ size_t nv_offset = 4;
+ int rv;
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->cur->buf;
+
+ buf->pos += nv_offset;
+ buf->last = buf->pos;
+
+ /* This call will adjust buf->last to the correct position */
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ buf->pos -= nv_offset;
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ nghttp2_put_uint32be(buf->pos, (uint32_t)frame->promised_stream_id);
+
+ frame->padlen = 0;
+ frame->hd.length = nghttp2_bufs_len(bufs);
+
+ return frame_pack_headers_shared(bufs, &frame->hd);
+}
+
+int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
+ const uint8_t *payload) {
+ frame->promised_stream_id =
+ nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+ frame->nva = NULL;
+ frame->nvlen = 0;
+ return 0;
+}
+
+int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= 8);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ buf->last =
+ nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
+ const uint8_t *payload) {
+ memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
+}
+
+int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) {
+ int rv;
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint32be(buf->last, (uint32_t)frame->last_stream_id);
+ buf->last += 4;
+
+ nghttp2_put_uint32be(buf->last, frame->error_code);
+ buf->last += 4;
+
+ rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ return NGHTTP2_ERR_FRAME_SIZE_ERROR;
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ uint8_t *var_gift_payload,
+ size_t var_gift_payloadlen) {
+ frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+ frame->error_code = nghttp2_get_uint32(payload + 4);
+
+ frame->opaque_data = var_gift_payload;
+ frame->opaque_data_len = var_gift_payloadlen;
+}
+
+int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem) {
+ uint8_t *var_gift_payload;
+ size_t var_gift_payloadlen;
+
+ if (payloadlen > 8) {
+ var_gift_payloadlen = payloadlen - 8;
+ } else {
+ var_gift_payloadlen = 0;
+ }
+
+ payloadlen -= var_gift_payloadlen;
+
+ if (!var_gift_payloadlen) {
+ var_gift_payload = NULL;
+ } else {
+ var_gift_payload = nghttp2_mem_malloc(mem, var_gift_payloadlen);
+
+ if (var_gift_payload == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ memcpy(var_gift_payload, payload + 8, var_gift_payloadlen);
+ }
+
+ nghttp2_frame_unpack_goaway_payload(frame, payload, var_gift_payload,
+ var_gift_payloadlen);
+
+ return 0;
+}
+
+int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
+ nghttp2_window_update *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= 4);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment);
+ buf->last += 4;
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
+ const uint8_t *payload) {
+ frame->window_size_increment =
+ nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
+}
+
+int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
+ int rv;
+ nghttp2_buf *buf;
+ nghttp2_ext_altsvc *altsvc;
+
+ /* This is required with --disable-assert. */
+ (void)rv;
+
+ altsvc = frame->payload;
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >=
+ 2 + altsvc->origin_len + altsvc->field_value_len);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len);
+ buf->last += 2;
+
+ rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len);
+
+ assert(rv == 0);
+
+ rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len);
+
+ assert(rv == 0);
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
+ size_t origin_len, uint8_t *payload,
+ size_t payloadlen) {
+ nghttp2_ext_altsvc *altsvc;
+ uint8_t *p;
+
+ altsvc = frame->payload;
+ p = payload;
+
+ altsvc->origin = p;
+
+ p += origin_len;
+
+ altsvc->origin_len = origin_len;
+
+ altsvc->field_value = p;
+ altsvc->field_value_len = (size_t)(payload + payloadlen - p);
+}
+
+int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem) {
+ uint8_t *buf;
+ size_t origin_len;
+
+ if (payloadlen < 2) {
+ return NGHTTP2_FRAME_SIZE_ERROR;
+ }
+
+ origin_len = nghttp2_get_uint16(payload);
+
+ buf = nghttp2_mem_malloc(mem, payloadlen - 2);
+ if (!buf) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_cpymem(buf, payload + 2, payloadlen - 2);
+
+ nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2);
+
+ return 0;
+}
+
+nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
+ size_t niv, nghttp2_mem *mem) {
+ nghttp2_settings_entry *iv_copy;
+ size_t len = niv * sizeof(nghttp2_settings_entry);
+
+ if (len == 0) {
+ return NULL;
+ }
+
+ iv_copy = nghttp2_mem_malloc(mem, len);
+
+ if (iv_copy == NULL) {
+ return NULL;
+ }
+
+ memcpy(iv_copy, iv, len);
+
+ return iv_copy;
+}
+
+int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b) {
+ return a->namelen == b->namelen && a->valuelen == b->valuelen &&
+ memcmp(a->name, b->name, a->namelen) == 0 &&
+ memcmp(a->value, b->value, a->valuelen) == 0;
+}
+
+void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem) {
+ nghttp2_mem_free(mem, nva);
+}
+
+static int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b,
+ size_t blen) {
+ int rv;
+
+ if (alen == blen) {
+ return memcmp(a, b, alen);
+ }
+
+ if (alen < blen) {
+ rv = memcmp(a, b, alen);
+
+ if (rv == 0) {
+ return -1;
+ }
+
+ return rv;
+ }
+
+ rv = memcmp(a, b, blen);
+
+ if (rv == 0) {
+ return 1;
+ }
+
+ return rv;
+}
+
+int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) {
+ return bytes_compar(lhs->name, lhs->namelen, rhs->name, rhs->namelen);
+}
+
+static int nv_compar(const void *lhs, const void *rhs) {
+ const nghttp2_nv *a = (const nghttp2_nv *)lhs;
+ const nghttp2_nv *b = (const nghttp2_nv *)rhs;
+ int rv;
+
+ rv = bytes_compar(a->name, a->namelen, b->name, b->namelen);
+
+ if (rv == 0) {
+ return bytes_compar(a->value, a->valuelen, b->value, b->valuelen);
+ }
+
+ return rv;
+}
+
+void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) {
+ qsort(nva, nvlen, sizeof(nghttp2_nv), nv_compar);
+}
+
+int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
+ size_t nvlen, nghttp2_mem *mem) {
+ size_t i;
+ uint8_t *data = NULL;
+ size_t buflen = 0;
+ nghttp2_nv *p;
+
+ if (nvlen == 0) {
+ *nva_ptr = NULL;
+
+ return 0;
+ }
+
+ for (i = 0; i < nvlen; ++i) {
+ /* + 1 for null-termination */
+ if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) {
+ buflen += nva[i].namelen + 1;
+ }
+ if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) {
+ buflen += nva[i].valuelen + 1;
+ }
+ }
+
+ buflen += sizeof(nghttp2_nv) * nvlen;
+
+ *nva_ptr = nghttp2_mem_malloc(mem, buflen);
+
+ if (*nva_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ p = *nva_ptr;
+ data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
+
+ for (i = 0; i < nvlen; ++i) {
+ p->flags = nva[i].flags;
+
+ if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) {
+ p->name = nva[i].name;
+ p->namelen = nva[i].namelen;
+ } else {
+ if (nva[i].namelen) {
+ memcpy(data, nva[i].name, nva[i].namelen);
+ }
+ p->name = data;
+ p->namelen = nva[i].namelen;
+ data[p->namelen] = '\0';
+ nghttp2_downcase(p->name, p->namelen);
+ data += nva[i].namelen + 1;
+ }
+
+ if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) {
+ p->value = nva[i].value;
+ p->valuelen = nva[i].valuelen;
+ } else {
+ if (nva[i].valuelen) {
+ memcpy(data, nva[i].value, nva[i].valuelen);
+ }
+ p->value = data;
+ p->valuelen = nva[i].valuelen;
+ data[p->valuelen] = '\0';
+ data += nva[i].valuelen + 1;
+ }
+
+ ++p;
+ }
+ return 0;
+}
+
+int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
+ size_t i;
+ for (i = 0; i < niv; ++i) {
+ switch (iv[i].settings_id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ break;
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+ break;
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+ if (iv[i].value != 0 && iv[i].value != 1) {
+ return 0;
+ }
+ break;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ if (iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) {
+ return 0;
+ }
+ break;
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+ if (iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
+ iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
+ return 0;
+ }
+ break;
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+ break;
+ }
+ }
+ return 1;
+}
+
+static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
+ size_t trail_padlen;
+ size_t newlen;
+
+ DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen);
+
+ memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN);
+
+ --buf->pos;
+
+ buf->pos[4] |= NGHTTP2_FLAG_PADDED;
+
+ newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen;
+ nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3]));
+
+ if (framehd_only) {
+ return;
+ }
+
+ trail_padlen = padlen - 1;
+ buf->pos[NGHTTP2_FRAME_HDLEN] = (uint8_t)trail_padlen;
+
+ /* zero out padding */
+ memset(buf->last, 0, trail_padlen);
+ /* extend buffers trail_padlen bytes, since we ate previous padlen -
+ trail_padlen byte(s) */
+ buf->last += trail_padlen;
+}
+
+int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
+ size_t padlen, int framehd_only) {
+ nghttp2_buf *buf;
+
+ if (padlen == 0) {
+ DEBUGF("send: padlen = 0, nothing to do\n");
+
+ return 0;
+ }
+
+ /*
+ * We have arranged bufs like this:
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |Frame header | Frame payload... :
+ * +-+-----------------+-------------------------------------------+
+ * | |Frame header | Frame payload... :
+ * +-+-----------------+-------------------------------------------+
+ * | |Frame header | Frame payload... :
+ * +-+-----------------+-------------------------------------------+
+ *
+ * We arranged padding so that it is included in the first frame
+ * completely. For padded frame, we are going to adjust buf->pos of
+ * frame which includes padding and serialize (memmove) frame header
+ * in the correct position. Also extends buf->last to include
+ * padding.
+ */
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= padlen - 1);
+
+ frame_set_pad(buf, padlen, framehd_only);
+
+ hd->length += padlen;
+ hd->flags |= NGHTTP2_FLAG_PADDED;
+
+ DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen);
+
+ return 0;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_frame.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_frame.h
new file mode 100644
index 00000000..07aeb8b7
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_frame.h
@@ -0,0 +1,556 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_FRAME_H
+#define NGHTTP2_FRAME_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_hd.h"
+#include "nghttp2_buf.h"
+
+#define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1)
+#define NGHTTP2_PRI_GROUP_ID_MASK ((1u << 31) - 1)
+#define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1)
+#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1)
+#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1)
+
+/* The number of bytes of frame header. */
+#define NGHTTP2_FRAME_HDLEN 9
+
+#define NGHTTP2_MAX_FRAME_SIZE_MAX ((1 << 24) - 1)
+#define NGHTTP2_MAX_FRAME_SIZE_MIN (1 << 14)
+
+#define NGHTTP2_MAX_PAYLOADLEN 16384
+/* The one frame buffer length for tranmission. We may use several of
+ them to support CONTINUATION. To account for Pad Length field, we
+ allocate extra 1 byte, which saves extra large memcopying. */
+#define NGHTTP2_FRAMEBUF_CHUNKLEN \
+ (NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN)
+
+/* The default length of DATA frame payload. */
+#define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN
+
+/* Maximum headers block size to send, calculated using
+ nghttp2_hd_deflate_bound(). This is the default value, and can be
+ overridden by nghttp2_option_set_max_send_header_block_size(). */
+#define NGHTTP2_MAX_HEADERSLEN 65536
+
+/* The number of bytes for each SETTINGS entry */
+#define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6
+
+/* Length of priority related fields in HEADERS/PRIORITY frames */
+#define NGHTTP2_PRIORITY_SPECLEN 5
+
+/* Maximum length of padding in bytes. */
+#define NGHTTP2_MAX_PADLEN 256
+
+/* Union of extension frame payload */
+typedef union {
+ nghttp2_ext_altsvc altsvc;
+} nghttp2_ext_frame_payload;
+
+void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
+
+void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf);
+
+/**
+ * Initializes frame header |hd| with given parameters. Reserved bit
+ * is set to 0.
+ */
+void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
+ uint8_t flags, int32_t stream_id);
+
+/**
+ * Returns the number of priority field depending on the |flags|. If
+ * |flags| has neither NGHTTP2_FLAG_PRIORITY_GROUP nor
+ * NGHTTP2_FLAG_PRIORITY_DEPENDENCY set, return 0.
+ */
+size_t nghttp2_frame_priority_len(uint8_t flags);
+
+/**
+ * Packs the |pri_spec| in |buf|. This function assumes |buf| has
+ * enough space for serialization.
+ */
+void nghttp2_frame_pack_priority_spec(uint8_t *buf,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * Unpacks the priority specification from payload |payload| of length
+ * |payloadlen| to |pri_spec|. The |flags| is used to determine what
+ * kind of priority specification is in |payload|. This function
+ * assumes the |payload| contains whole priority specification.
+ */
+void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
+ const uint8_t *payload);
+
+/*
+ * Returns the offset from the HEADERS frame payload where the
+ * compressed header block starts. The frame payload does not include
+ * frame header.
+ */
+size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
+
+/*
+ * Packs HEADERS frame |frame| in wire format and store it in |bufs|.
+ * This function expands |bufs| as necessary to store frame.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * frame->hd.length is assigned after length is determined during
+ * packing process. CONTINUATION frames are also serialized in this
+ * function. This function does not handle padding.
+ *
+ * This function returns 0 if it succeeds, or returns one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * The deflate operation failed.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
+ nghttp2_hd_deflater *deflater);
+
+/*
+ * Unpacks HEADERS frame byte sequence into |frame|. This function
+ * only unapcks bytes that come before name/value header block and
+ * after possible Pad Length field.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs PRIORITY frame |frame| in wire format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
+
+/*
+ * Unpacks PRIORITY wire format into |frame|.
+ */
+void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs RST_STREAM frame |frame| in wire frame format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
+ nghttp2_rst_stream *frame);
+
+/*
+ * Unpacks RST_STREAM frame byte sequence into |frame|.
+ */
+void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs SETTINGS frame |frame| in wire format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function returns 0 if it succeeds, or returns one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The length of the frame is too large.
+ */
+int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame);
+
+/*
+ * Packs the |iv|, which includes |niv| entries, in the |buf|,
+ * assuming the |buf| has at least 8 * |niv| bytes.
+ *
+ * Returns the number of bytes written into the |buf|.
+ */
+size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
+ const nghttp2_settings_entry *iv,
+ size_t niv);
+
+void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
+ const uint8_t *payload);
+
+/*
+ * Initializes payload of frame->settings. The |frame| takes
+ * ownership of |iv|.
+ */
+void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
+ nghttp2_settings_entry *iv,
+ size_t niv);
+
+/*
+ * Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
+ * assigned to the |*niv_ptr|. This function allocates enough memory
+ * to store the result in |*iv_ptr|. The caller is responsible to free
+ * |*iv_ptr| after its use.
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
+ size_t *niv_ptr,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Packs PUSH_PROMISE frame |frame| in wire format and store it in
+ * |bufs|. This function expands |bufs| as necessary to store
+ * frame.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * frame->hd.length is assigned after length is determined during
+ * packing process. CONTINUATION frames are also serialized in this
+ * function. This function does not handle padding.
+ *
+ * This function returns 0 if it succeeds, or returns one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * The deflate operation failed.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
+ nghttp2_push_promise *frame,
+ nghttp2_hd_deflater *deflater);
+
+/*
+ * Unpacks PUSH_PROMISE frame byte sequence into |frame|. This
+ * function only unapcks bytes that come before name/value header
+ * block and after possible Pad Length field.
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_PROTO
+ * TODO END_HEADERS flag is not set
+ */
+int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs PING frame |frame| in wire format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
+
+/*
+ * Unpacks PING wire format into |frame|.
+ */
+void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs GOAWAY frame |frame| in wire format and store it in |bufs|.
+ * This function expands |bufs| as necessary to store frame.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The length of the frame is too large.
+ */
+int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame);
+
+/*
+ * Unpacks GOAWAY wire format into |frame|. The |payload| of length
+ * |payloadlen| contains first 8 bytes of payload. The
+ * |var_gift_payload| of length |var_gift_payloadlen| contains
+ * remaining payload and its buffer is gifted to the function and then
+ * |frame|. The |var_gift_payloadlen| must be freed by
+ * nghttp2_frame_goaway_free().
+ */
+void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ uint8_t *var_gift_payload,
+ size_t var_gift_payloadlen);
+
+/*
+ * Unpacks GOAWAY wire format into |frame|. This function only exists
+ * for unit test. After allocating buffer for debug data, this
+ * function internally calls nghttp2_frame_unpack_goaway_payload().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
+ * in |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
+ nghttp2_window_update *frame);
+
+/*
+ * Unpacks WINDOW_UPDATE frame byte sequence into |frame|.
+ */
+void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs ALTSVC frame |frame| in wire frame format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext);
+
+/*
+ * Unpacks ALTSVC wire format into |frame|. The |payload| of
+ * |payloadlen| bytes contains frame payload. This function assumes
+ * that frame->payload points to the nghttp2_ext_altsvc object.
+ *
+ * This function always succeeds and returns 0.
+ */
+void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
+ size_t origin_len, uint8_t *payload,
+ size_t payloadlen);
+
+/*
+ * Unpacks ALTSVC wire format into |frame|. This function only exists
+ * for unit test. After allocating buffer for fields, this function
+ * internally calls nghttp2_frame_unpack_altsvc_payload().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The payload is too small.
+ */
+int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Initializes HEADERS frame |frame| with given values. |frame| takes
+ * ownership of |nva|, so caller must not free it. If |stream_id| is
+ * not assigned yet, it must be -1.
+ */
+void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
+ int32_t stream_id, nghttp2_headers_category cat,
+ const nghttp2_priority_spec *pri_spec,
+ nghttp2_nv *nva, size_t nvlen);
+
+void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem);
+
+void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+void nghttp2_frame_priority_free(nghttp2_priority *frame);
+
+void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
+ uint32_t error_code);
+
+void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame);
+
+/*
+ * Initializes PUSH_PROMISE frame |frame| with given values. |frame|
+ * takes ownership of |nva|, so caller must not free it.
+ */
+void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
+ int32_t stream_id,
+ int32_t promised_stream_id,
+ nghttp2_nv *nva, size_t nvlen);
+
+void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame,
+ nghttp2_mem *mem);
+
+/*
+ * Initializes SETTINGS frame |frame| with given values. |frame| takes
+ * ownership of |iv|, so caller must not free it. The |flags| are
+ * bitwise-OR of one or more of nghttp2_settings_flag.
+ */
+void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
+ nghttp2_settings_entry *iv, size_t niv);
+
+void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem);
+
+/*
+ * Initializes PING frame |frame| with given values. If the
+ * |opqeue_data| is not NULL, it must point to 8 bytes memory region
+ * of data. The data pointed by |opaque_data| is copied. It can be
+ * NULL. In this case, 8 bytes NULL is used.
+ */
+void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
+ const uint8_t *opque_data);
+
+void nghttp2_frame_ping_free(nghttp2_ping *frame);
+
+/*
+ * Initializes GOAWAY frame |frame| with given values. On success,
+ * this function takes ownership of |opaque_data|, so caller must not
+ * free it. If the |opaque_data_len| is 0, opaque_data could be NULL.
+ */
+void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
+ uint32_t error_code, uint8_t *opaque_data,
+ size_t opaque_data_len);
+
+void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem);
+
+void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
+ uint8_t flags, int32_t stream_id,
+ int32_t window_size_increment);
+
+void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
+
+void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
+ uint8_t flags, int32_t stream_id,
+ void *payload);
+
+void nghttp2_frame_extension_free(nghttp2_extension *frame);
+
+/*
+ * Initializes ALTSVC frame |frame| with given values. This function
+ * assumes that frame->payload points to nghttp2_ext_altsvc object.
+ * Also |origin| and |field_value| are allocated in single buffer,
+ * starting |origin|. On success, this function takes ownership of
+ * |origin|, so caller must not free it.
+ */
+void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
+ uint8_t *origin, size_t origin_len,
+ uint8_t *field_value, size_t field_value_len);
+
+/*
+ * Frees up resources under |frame|. This function does not free
+ * nghttp2_ext_altsvc object pointed by frame->payload. This function
+ * only frees origin pointed by nghttp2_ext_altsvc.origin. Therefore,
+ * other fields must be allocated in the same buffer with origin.
+ */
+void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem);
+
+/*
+ * Returns the number of padding bytes after payload. The total
+ * padding length is given in the |padlen|. The returned value does
+ * not include the Pad Length field. If |padlen| is 0, this function
+ * returns 0, regardless of frame->hd.flags.
+ */
+size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen);
+
+void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
+ int32_t stream_id);
+
+void nghttp2_frame_data_free(nghttp2_data *frame);
+
+/*
+ * Makes copy of |iv| and return the copy. The |niv| is the number of
+ * entries in |iv|. This function returns the pointer to the copy if
+ * it succeeds, or NULL.
+ */
+nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
+ size_t niv, nghttp2_mem *mem);
+
+/*
+ * Sorts the |nva| in ascending order of name and value. If names are
+ * equivalent, sort them by value.
+ */
+void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen);
+
+/*
+ * Copies name/value pairs from |nva|, which contains |nvlen| pairs,
+ * to |*nva_ptr|, which is dynamically allocated so that all items can
+ * be stored. The resultant name and value in nghttp2_nv are
+ * guaranteed to be NULL-terminated even if the input is not
+ * null-terminated.
+ *
+ * The |*nva_ptr| must be freed using nghttp2_nv_array_del().
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
+ size_t nvlen, nghttp2_mem *mem);
+
+/*
+ * Returns nonzero if the name/value pair |a| equals to |b|. The name
+ * is compared in case-sensitive, because we ensure that this function
+ * is called after the name is lower-cased.
+ */
+int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b);
+
+/*
+ * Frees |nva|.
+ */
+void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem);
+
+/*
+ * Checks that the |iv|, which includes |niv| entries, does not have
+ * invalid values.
+ *
+ * This function returns nonzero if it succeeds, or 0.
+ */
+int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
+
+/*
+ * Sets Pad Length field and flags and adjusts frame header position
+ * of each buffers in |bufs|. The number of padding is given in the
+ * |padlen| including Pad Length field. The |hd| is the frame header
+ * for the serialized data. This function fills zeros padding region
+ * unless framehd_only is nonzero.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The length of the resulting frame is too large.
+ */
+int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
+ size_t padlen, int framehd_only);
+
+#endif /* NGHTTP2_FRAME_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd.c
new file mode 100644
index 00000000..d7e80a23
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd.c
@@ -0,0 +1,2317 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_hd.h"
+
+#include
+#include
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_int.h"
+#include "nghttp2_debug.h"
+
+/* Make scalar initialization form of nghttp2_hd_entry */
+#define MAKE_STATIC_ENT(N, V, T, H) \
+ { \
+ {NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
+ {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
+ {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
+ T, H \
+ }
+
+/* Generated by mkstatictbl.py */
+/* 3rd parameter is nghttp2_token value for header field name. We use
+ first enum value if same header names are repeated (e.g.,
+ :status). */
+static nghttp2_hd_static_entry static_table[] = {
+ MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
+ MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
+ MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
+ MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
+ MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
+ MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
+ MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
+ MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
+ MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
+ MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
+ MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
+ MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
+ MAKE_STATIC_ENT("accept", "", 18, 136609321u),
+ MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
+ MAKE_STATIC_ENT("age", "", 20, 742476188u),
+ MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
+ MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
+ MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
+ MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
+ MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
+ MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
+ MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
+ MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
+ MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
+ MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
+ MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
+ MAKE_STATIC_ENT("date", "", 32, 3564297305u),
+ MAKE_STATIC_ENT("etag", "", 33, 113792960u),
+ MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
+ MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
+ MAKE_STATIC_ENT("from", "", 36, 2513272949u),
+ MAKE_STATIC_ENT("host", "", 37, 2952701295u),
+ MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
+ MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
+ MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
+ MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
+ MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
+ MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
+ MAKE_STATIC_ENT("link", "", 44, 232457833u),
+ MAKE_STATIC_ENT("location", "", 45, 200649126u),
+ MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
+ MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
+ MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
+ MAKE_STATIC_ENT("range", "", 49, 4208725202u),
+ MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
+ MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
+ MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
+ MAKE_STATIC_ENT("server", "", 53, 1085029842u),
+ MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
+ MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
+ MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
+ MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
+ MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
+ MAKE_STATIC_ENT("via", "", 59, 1762798611u),
+ MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
+};
+
+static int memeq(const void *s1, const void *s2, size_t n) {
+ return memcmp(s1, s2, n) == 0;
+}
+
+/*
+ * This function was generated by genlibtokenlookup.py. Inspired by
+ * h2o header lookup. https://github.com/h2o/h2o
+ */
+static int32_t lookup_token(const uint8_t *name, size_t namelen) {
+ switch (namelen) {
+ case 2:
+ switch (name[1]) {
+ case 'e':
+ if (memeq("t", name, 1)) {
+ return NGHTTP2_TOKEN_TE;
+ }
+ break;
+ }
+ break;
+ case 3:
+ switch (name[2]) {
+ case 'a':
+ if (memeq("vi", name, 2)) {
+ return NGHTTP2_TOKEN_VIA;
+ }
+ break;
+ case 'e':
+ if (memeq("ag", name, 2)) {
+ return NGHTTP2_TOKEN_AGE;
+ }
+ break;
+ }
+ break;
+ case 4:
+ switch (name[3]) {
+ case 'e':
+ if (memeq("dat", name, 3)) {
+ return NGHTTP2_TOKEN_DATE;
+ }
+ break;
+ case 'g':
+ if (memeq("eta", name, 3)) {
+ return NGHTTP2_TOKEN_ETAG;
+ }
+ break;
+ case 'k':
+ if (memeq("lin", name, 3)) {
+ return NGHTTP2_TOKEN_LINK;
+ }
+ break;
+ case 'm':
+ if (memeq("fro", name, 3)) {
+ return NGHTTP2_TOKEN_FROM;
+ }
+ break;
+ case 't':
+ if (memeq("hos", name, 3)) {
+ return NGHTTP2_TOKEN_HOST;
+ }
+ break;
+ case 'y':
+ if (memeq("var", name, 3)) {
+ return NGHTTP2_TOKEN_VARY;
+ }
+ break;
+ }
+ break;
+ case 5:
+ switch (name[4]) {
+ case 'e':
+ if (memeq("rang", name, 4)) {
+ return NGHTTP2_TOKEN_RANGE;
+ }
+ break;
+ case 'h':
+ if (memeq(":pat", name, 4)) {
+ return NGHTTP2_TOKEN__PATH;
+ }
+ break;
+ case 'w':
+ if (memeq("allo", name, 4)) {
+ return NGHTTP2_TOKEN_ALLOW;
+ }
+ break;
+ }
+ break;
+ case 6:
+ switch (name[5]) {
+ case 'e':
+ if (memeq("cooki", name, 5)) {
+ return NGHTTP2_TOKEN_COOKIE;
+ }
+ break;
+ case 'r':
+ if (memeq("serve", name, 5)) {
+ return NGHTTP2_TOKEN_SERVER;
+ }
+ break;
+ case 't':
+ if (memeq("accep", name, 5)) {
+ return NGHTTP2_TOKEN_ACCEPT;
+ }
+ if (memeq("expec", name, 5)) {
+ return NGHTTP2_TOKEN_EXPECT;
+ }
+ break;
+ }
+ break;
+ case 7:
+ switch (name[6]) {
+ case 'd':
+ if (memeq(":metho", name, 6)) {
+ return NGHTTP2_TOKEN__METHOD;
+ }
+ break;
+ case 'e':
+ if (memeq(":schem", name, 6)) {
+ return NGHTTP2_TOKEN__SCHEME;
+ }
+ if (memeq("upgrad", name, 6)) {
+ return NGHTTP2_TOKEN_UPGRADE;
+ }
+ break;
+ case 'h':
+ if (memeq("refres", name, 6)) {
+ return NGHTTP2_TOKEN_REFRESH;
+ }
+ break;
+ case 'r':
+ if (memeq("refere", name, 6)) {
+ return NGHTTP2_TOKEN_REFERER;
+ }
+ break;
+ case 's':
+ if (memeq(":statu", name, 6)) {
+ return NGHTTP2_TOKEN__STATUS;
+ }
+ if (memeq("expire", name, 6)) {
+ return NGHTTP2_TOKEN_EXPIRES;
+ }
+ break;
+ }
+ break;
+ case 8:
+ switch (name[7]) {
+ case 'e':
+ if (memeq("if-rang", name, 7)) {
+ return NGHTTP2_TOKEN_IF_RANGE;
+ }
+ break;
+ case 'h':
+ if (memeq("if-matc", name, 7)) {
+ return NGHTTP2_TOKEN_IF_MATCH;
+ }
+ break;
+ case 'n':
+ if (memeq("locatio", name, 7)) {
+ return NGHTTP2_TOKEN_LOCATION;
+ }
+ break;
+ }
+ break;
+ case 10:
+ switch (name[9]) {
+ case 'e':
+ if (memeq("keep-aliv", name, 9)) {
+ return NGHTTP2_TOKEN_KEEP_ALIVE;
+ }
+ if (memeq("set-cooki", name, 9)) {
+ return NGHTTP2_TOKEN_SET_COOKIE;
+ }
+ break;
+ case 'n':
+ if (memeq("connectio", name, 9)) {
+ return NGHTTP2_TOKEN_CONNECTION;
+ }
+ break;
+ case 't':
+ if (memeq("user-agen", name, 9)) {
+ return NGHTTP2_TOKEN_USER_AGENT;
+ }
+ break;
+ case 'y':
+ if (memeq(":authorit", name, 9)) {
+ return NGHTTP2_TOKEN__AUTHORITY;
+ }
+ break;
+ }
+ break;
+ case 11:
+ switch (name[10]) {
+ case 'r':
+ if (memeq("retry-afte", name, 10)) {
+ return NGHTTP2_TOKEN_RETRY_AFTER;
+ }
+ break;
+ }
+ break;
+ case 12:
+ switch (name[11]) {
+ case 'e':
+ if (memeq("content-typ", name, 11)) {
+ return NGHTTP2_TOKEN_CONTENT_TYPE;
+ }
+ break;
+ case 's':
+ if (memeq("max-forward", name, 11)) {
+ return NGHTTP2_TOKEN_MAX_FORWARDS;
+ }
+ break;
+ }
+ break;
+ case 13:
+ switch (name[12]) {
+ case 'd':
+ if (memeq("last-modifie", name, 12)) {
+ return NGHTTP2_TOKEN_LAST_MODIFIED;
+ }
+ break;
+ case 'e':
+ if (memeq("content-rang", name, 12)) {
+ return NGHTTP2_TOKEN_CONTENT_RANGE;
+ }
+ break;
+ case 'h':
+ if (memeq("if-none-matc", name, 12)) {
+ return NGHTTP2_TOKEN_IF_NONE_MATCH;
+ }
+ break;
+ case 'l':
+ if (memeq("cache-contro", name, 12)) {
+ return NGHTTP2_TOKEN_CACHE_CONTROL;
+ }
+ break;
+ case 'n':
+ if (memeq("authorizatio", name, 12)) {
+ return NGHTTP2_TOKEN_AUTHORIZATION;
+ }
+ break;
+ case 's':
+ if (memeq("accept-range", name, 12)) {
+ return NGHTTP2_TOKEN_ACCEPT_RANGES;
+ }
+ break;
+ }
+ break;
+ case 14:
+ switch (name[13]) {
+ case 'h':
+ if (memeq("content-lengt", name, 13)) {
+ return NGHTTP2_TOKEN_CONTENT_LENGTH;
+ }
+ break;
+ case 't':
+ if (memeq("accept-charse", name, 13)) {
+ return NGHTTP2_TOKEN_ACCEPT_CHARSET;
+ }
+ break;
+ }
+ break;
+ case 15:
+ switch (name[14]) {
+ case 'e':
+ if (memeq("accept-languag", name, 14)) {
+ return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
+ }
+ break;
+ case 'g':
+ if (memeq("accept-encodin", name, 14)) {
+ return NGHTTP2_TOKEN_ACCEPT_ENCODING;
+ }
+ break;
+ }
+ break;
+ case 16:
+ switch (name[15]) {
+ case 'e':
+ if (memeq("content-languag", name, 15)) {
+ return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
+ }
+ if (memeq("www-authenticat", name, 15)) {
+ return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
+ }
+ break;
+ case 'g':
+ if (memeq("content-encodin", name, 15)) {
+ return NGHTTP2_TOKEN_CONTENT_ENCODING;
+ }
+ break;
+ case 'n':
+ if (memeq("content-locatio", name, 15)) {
+ return NGHTTP2_TOKEN_CONTENT_LOCATION;
+ }
+ if (memeq("proxy-connectio", name, 15)) {
+ return NGHTTP2_TOKEN_PROXY_CONNECTION;
+ }
+ break;
+ }
+ break;
+ case 17:
+ switch (name[16]) {
+ case 'e':
+ if (memeq("if-modified-sinc", name, 16)) {
+ return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
+ }
+ break;
+ case 'g':
+ if (memeq("transfer-encodin", name, 16)) {
+ return NGHTTP2_TOKEN_TRANSFER_ENCODING;
+ }
+ break;
+ }
+ break;
+ case 18:
+ switch (name[17]) {
+ case 'e':
+ if (memeq("proxy-authenticat", name, 17)) {
+ return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
+ }
+ break;
+ }
+ break;
+ case 19:
+ switch (name[18]) {
+ case 'e':
+ if (memeq("if-unmodified-sinc", name, 18)) {
+ return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
+ }
+ break;
+ case 'n':
+ if (memeq("content-dispositio", name, 18)) {
+ return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
+ }
+ if (memeq("proxy-authorizatio", name, 18)) {
+ return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
+ }
+ break;
+ }
+ break;
+ case 25:
+ switch (name[24]) {
+ case 'y':
+ if (memeq("strict-transport-securit", name, 24)) {
+ return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
+ }
+ break;
+ }
+ break;
+ case 27:
+ switch (name[26]) {
+ case 'n':
+ if (memeq("access-control-allow-origi", name, 26)) {
+ return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
+ }
+ break;
+ }
+ break;
+ }
+ return -1;
+}
+
+void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
+ ent->nv = *nv;
+ ent->cnv.name = nv->name->base;
+ ent->cnv.namelen = nv->name->len;
+ ent->cnv.value = nv->value->base;
+ ent->cnv.valuelen = nv->value->len;
+ ent->cnv.flags = nv->flags;
+ ent->next = NULL;
+ ent->hash = 0;
+
+ nghttp2_rcbuf_incref(ent->nv.name);
+ nghttp2_rcbuf_incref(ent->nv.value);
+}
+
+void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
+ nghttp2_rcbuf_decref(ent->nv.value);
+ nghttp2_rcbuf_decref(ent->nv.name);
+}
+
+static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
+ return a->name->len == b->namelen &&
+ memeq(a->name->base, b->name, b->namelen);
+}
+
+static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
+ return a->value->len == b->valuelen &&
+ memeq(a->value->base, b->value, b->valuelen);
+}
+
+static uint32_t name_hash(const nghttp2_nv *nv) {
+ /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
+ uint32_t h = 2166136261u;
+ size_t i;
+
+ for (i = 0; i < nv->namelen; ++i) {
+ h ^= nv->name[i];
+ h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
+ }
+
+ return h;
+}
+
+static void hd_map_init(nghttp2_hd_map *map) {
+ memset(map, 0, sizeof(nghttp2_hd_map));
+}
+
+static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
+ nghttp2_hd_entry **bucket;
+
+ bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+
+ if (*bucket == NULL) {
+ *bucket = ent;
+ return;
+ }
+
+ /* lower index is linked near the root */
+ ent->next = *bucket;
+ *bucket = ent;
+}
+
+static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
+ const nghttp2_nv *nv, int32_t token,
+ uint32_t hash, int name_only) {
+ nghttp2_hd_entry *p;
+ nghttp2_hd_entry *res = NULL;
+
+ *exact_match = 0;
+
+ for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
+ if (token != p->nv.token ||
+ (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
+ continue;
+ }
+ if (!res) {
+ res = p;
+ if (name_only) {
+ break;
+ }
+ }
+ if (value_eq(&p->nv, nv)) {
+ res = p;
+ *exact_match = 1;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
+ nghttp2_hd_entry **dst;
+
+ dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+
+ for (; *dst; dst = &(*dst)->next) {
+ if (*dst != ent) {
+ continue;
+ }
+
+ *dst = ent->next;
+ ent->next = NULL;
+ return;
+ }
+}
+
+static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
+ nghttp2_mem *mem) {
+ size_t size;
+ for (size = 1; size < bufsize; size <<= 1)
+ ;
+ ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
+ if (ringbuf->buffer == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ ringbuf->mask = size - 1;
+ ringbuf->first = 0;
+ ringbuf->len = 0;
+ return 0;
+}
+
+static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
+ size_t idx) {
+ assert(idx < ringbuf->len);
+ return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
+}
+
+static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
+ nghttp2_mem *mem) {
+ size_t i;
+ size_t size;
+ nghttp2_hd_entry **buffer;
+
+ if (ringbuf->mask + 1 >= bufsize) {
+ return 0;
+ }
+ for (size = 1; size < bufsize; size <<= 1)
+ ;
+ buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
+ if (buffer == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ for (i = 0; i < ringbuf->len; ++i) {
+ buffer[i] = hd_ringbuf_get(ringbuf, i);
+ }
+ nghttp2_mem_free(mem, ringbuf->buffer);
+ ringbuf->buffer = buffer;
+ ringbuf->mask = size - 1;
+ ringbuf->first = 0;
+ return 0;
+}
+
+static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
+ size_t i;
+ if (ringbuf == NULL) {
+ return;
+ }
+ for (i = 0; i < ringbuf->len; ++i) {
+ nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
+ }
+ nghttp2_mem_free(mem, ringbuf->buffer);
+}
+
+static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
+ nghttp2_hd_entry *ent, nghttp2_mem *mem) {
+ int rv;
+
+ rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
+ ++ringbuf->len;
+
+ return 0;
+}
+
+static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
+ assert(ringbuf->len > 0);
+ --ringbuf->len;
+}
+
+static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
+ int rv;
+ context->mem = mem;
+ context->bad = 0;
+ context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
+ rv = hd_ringbuf_init(
+ &context->hd_table,
+ context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ context->hd_table_bufsize = 0;
+ context->next_seq = 0;
+
+ return 0;
+}
+
+static void hd_context_free(nghttp2_hd_context *context) {
+ hd_ringbuf_free(&context->hd_table, context->mem);
+}
+
+int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
+ return nghttp2_hd_deflate_init2(
+ deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
+}
+
+int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
+ size_t max_deflate_dynamic_table_size,
+ nghttp2_mem *mem) {
+ int rv;
+ rv = hd_context_init(&deflater->ctx, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ hd_map_init(&deflater->map);
+
+ if (max_deflate_dynamic_table_size < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
+ deflater->notify_table_size_change = 1;
+ deflater->ctx.hd_table_bufsize_max = max_deflate_dynamic_table_size;
+ } else {
+ deflater->notify_table_size_change = 0;
+ }
+
+ deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
+ deflater->min_hd_table_bufsize_max = UINT32_MAX;
+
+ return 0;
+}
+
+int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
+ int rv;
+
+ rv = hd_context_init(&inflater->ctx, mem);
+ if (rv != 0) {
+ goto fail;
+ }
+
+ inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
+ inflater->min_hd_table_bufsize_max = UINT32_MAX;
+
+ inflater->nv_name_keep = NULL;
+ inflater->nv_value_keep = NULL;
+
+ inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
+
+ nghttp2_buf_init(&inflater->namebuf);
+ nghttp2_buf_init(&inflater->valuebuf);
+
+ inflater->namercbuf = NULL;
+ inflater->valuercbuf = NULL;
+
+ inflater->huffman_encoded = 0;
+ inflater->index = 0;
+ inflater->left = 0;
+ inflater->shift = 0;
+ inflater->index_required = 0;
+ inflater->no_index = 0;
+
+ return 0;
+
+fail:
+ return rv;
+}
+
+static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
+ nghttp2_rcbuf_decref(inflater->nv_value_keep);
+ nghttp2_rcbuf_decref(inflater->nv_name_keep);
+
+ inflater->nv_value_keep = NULL;
+ inflater->nv_name_keep = NULL;
+}
+
+void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
+ hd_context_free(&deflater->ctx);
+}
+
+void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
+ hd_inflate_keep_free(inflater);
+
+ nghttp2_rcbuf_decref(inflater->valuercbuf);
+ nghttp2_rcbuf_decref(inflater->namercbuf);
+
+ hd_context_free(&inflater->ctx);
+}
+
+static size_t entry_room(size_t namelen, size_t valuelen) {
+ return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
+}
+
+static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
+ DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
+ nv->value->base);
+ /* ent->ref may be 0. This happens if the encoder emits literal
+ block larger than header table capacity with indexing. */
+ *nv_out = *nv;
+}
+
+static size_t count_encoded_length(size_t n, size_t prefix) {
+ size_t k = (size_t)((1 << prefix) - 1);
+ size_t len = 0;
+
+ if (n < k) {
+ return 1;
+ }
+
+ n -= k;
+ ++len;
+
+ for (; n >= 128; n >>= 7, ++len)
+ ;
+
+ return len + 1;
+}
+
+static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
+ size_t k = (size_t)((1 << prefix) - 1);
+ uint8_t *begin = buf;
+
+ *buf = (uint8_t)(*buf & ~k);
+
+ if (n < k) {
+ *buf = (uint8_t)(*buf | n);
+ return 1;
+ }
+
+ *buf = (uint8_t)(*buf | k);
+ ++buf;
+
+ n -= k;
+
+ for (; n >= 128; n >>= 7) {
+ *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
+ }
+
+ *buf++ = (uint8_t)n;
+
+ return (size_t)(buf - begin);
+}
+
+/*
+ * Decodes |prefix| prefixed integer stored from |in|. The |last|
+ * represents the 1 beyond the last of the valid contiguous memory
+ * region from |in|. The decoded integer must be less than or equal
+ * to UINT32_MAX.
+ *
+ * If the |initial| is nonzero, it is used as a initial value, this
+ * function assumes the |in| starts with intermediate data.
+ *
+ * An entire integer is decoded successfully, decoded, the |*fin| is
+ * set to nonzero.
+ *
+ * This function stores the decoded integer in |*res| if it succeed,
+ * including partial decoding (in this case, number of shift to make
+ * in the next call will be stored in |*shift_ptr|) and returns number
+ * of bytes processed, or returns -1, indicating decoding error.
+ */
+static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
+ uint32_t initial, size_t shift, const uint8_t *in,
+ const uint8_t *last, size_t prefix) {
+ uint32_t k = (uint8_t)((1 << prefix) - 1);
+ uint32_t n = initial;
+ const uint8_t *start = in;
+
+ *shift_ptr = 0;
+ *fin = 0;
+
+ if (n == 0) {
+ if ((*in & k) != k) {
+ *res = (*in) & k;
+ *fin = 1;
+ return 1;
+ }
+
+ n = k;
+
+ if (++in == last) {
+ *res = n;
+ return (ssize_t)(in - start);
+ }
+ }
+
+ for (; in != last; ++in, shift += 7) {
+ uint32_t add = *in & 0x7f;
+
+ if (shift >= 32) {
+ DEBUGF("inflate: shift exponent overflow\n");
+ return -1;
+ }
+
+ if ((UINT32_MAX >> shift) < add) {
+ DEBUGF("inflate: integer overflow on shift\n");
+ return -1;
+ }
+
+ add <<= shift;
+
+ if (UINT32_MAX - add < n) {
+ DEBUGF("inflate: integer overflow on addition\n");
+ return -1;
+ }
+
+ n += add;
+
+ if ((*in & (1 << 7)) == 0) {
+ break;
+ }
+ }
+
+ *shift_ptr = shift;
+
+ if (in == last) {
+ *res = n;
+ return (ssize_t)(in - start);
+ }
+
+ *res = n;
+ *fin = 1;
+ return (ssize_t)(in + 1 - start);
+}
+
+static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
+ int rv;
+ uint8_t *bufp;
+ size_t blocklen;
+ uint8_t sb[16];
+
+ DEBUGF("deflatehd: emit table_size=%zu\n", table_size);
+
+ blocklen = count_encoded_length(table_size, 5);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+
+ *bufp = 0x20u;
+
+ encode_length(bufp, table_size, 5);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
+ int rv;
+ size_t blocklen;
+ uint8_t sb[16];
+ uint8_t *bufp;
+
+ blocklen = count_encoded_length(idx + 1, 7);
+
+ DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+ *bufp = 0x80u;
+ encode_length(bufp, idx + 1, 7);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
+ int rv;
+ uint8_t sb[16];
+ uint8_t *bufp;
+ size_t blocklen;
+ size_t enclen;
+ int huffman = 0;
+
+ enclen = nghttp2_hd_huff_encode_count(str, len);
+
+ if (enclen < len) {
+ huffman = 1;
+ } else {
+ enclen = len;
+ }
+
+ blocklen = count_encoded_length(enclen, 7);
+
+ DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
+ "encoded_length=%zu\n",
+ (int)len, (const char *)str, len, huffman, enclen);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+ *bufp = huffman ? 1 << 7 : 0;
+ encode_length(bufp, enclen, 7);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (huffman) {
+ rv = nghttp2_hd_huff_encode(bufs, str, len);
+ } else {
+ assert(enclen == len);
+ rv = nghttp2_bufs_add(bufs, str, len);
+ }
+
+ return rv;
+}
+
+static uint8_t pack_first_byte(int indexing_mode) {
+ switch (indexing_mode) {
+ case NGHTTP2_HD_WITH_INDEXING:
+ return 0x40u;
+ case NGHTTP2_HD_WITHOUT_INDEXING:
+ return 0;
+ case NGHTTP2_HD_NEVER_INDEXING:
+ return 0x10u;
+ default:
+ assert(0);
+ }
+ /* This is required to compile with android NDK r10d +
+ --enable-werror */
+ return 0;
+}
+
+static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
+ const nghttp2_nv *nv, int indexing_mode) {
+ int rv;
+ uint8_t *bufp;
+ size_t blocklen;
+ uint8_t sb[16];
+ size_t prefixlen;
+
+ if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
+ prefixlen = 6;
+ } else {
+ prefixlen = 4;
+ }
+
+ DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
+ idx, nv->valuelen, indexing_mode);
+
+ blocklen = count_encoded_length(idx + 1, prefixlen);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+
+ *bufp = pack_first_byte(indexing_mode);
+
+ encode_length(bufp, idx + 1, prefixlen);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = emit_string(bufs, nv->value, nv->valuelen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
+ int indexing_mode) {
+ int rv;
+
+ DEBUGF(
+ "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
+ nv->namelen, nv->valuelen, indexing_mode);
+
+ rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = emit_string(bufs, nv->name, nv->namelen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = emit_string(bufs, nv->value, nv->valuelen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int add_hd_table_incremental(nghttp2_hd_context *context,
+ nghttp2_hd_nv *nv, nghttp2_hd_map *map,
+ uint32_t hash) {
+ int rv;
+ nghttp2_hd_entry *new_ent;
+ size_t room;
+ nghttp2_mem *mem;
+
+ mem = context->mem;
+ room = entry_room(nv->name->len, nv->value->len);
+
+ while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
+ context->hd_table.len > 0) {
+
+ size_t idx = context->hd_table.len - 1;
+ nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
+
+ context->hd_table_bufsize -=
+ entry_room(ent->nv.name->len, ent->nv.value->len);
+
+ DEBUGF("hpack: remove item from header table: %s: %s\n",
+ (char *)ent->nv.name->base, (char *)ent->nv.value->base);
+
+ hd_ringbuf_pop_back(&context->hd_table);
+ if (map) {
+ hd_map_remove(map, ent);
+ }
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
+ }
+
+ if (room > context->hd_table_bufsize_max) {
+ /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
+ immediately evicted. So we don't allocate memory for it. */
+ return 0;
+ }
+
+ new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
+ if (new_ent == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_hd_entry_init(new_ent, nv);
+
+ rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
+
+ if (rv != 0) {
+ nghttp2_hd_entry_free(new_ent);
+ nghttp2_mem_free(mem, new_ent);
+
+ return rv;
+ }
+
+ new_ent->seq = context->next_seq++;
+ new_ent->hash = hash;
+
+ if (map) {
+ hd_map_insert(map, new_ent);
+ }
+
+ context->hd_table_bufsize += room;
+
+ return 0;
+}
+
+typedef struct {
+ ssize_t index;
+ /* Nonzero if both name and value are matched. */
+ int name_value_match;
+} search_result;
+
+static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
+ int name_only) {
+ search_result res = {token, 0};
+ int i;
+ nghttp2_hd_static_entry *ent;
+
+ if (name_only) {
+ return res;
+ }
+
+ for (i = token;
+ i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
+ ++i) {
+ ent = &static_table[i];
+ if (ent->value.len == nv->valuelen &&
+ memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
+ res.index = i;
+ res.name_value_match = 1;
+ return res;
+ }
+ }
+ return res;
+}
+
+static search_result search_hd_table(nghttp2_hd_context *context,
+ const nghttp2_nv *nv, int32_t token,
+ int indexing_mode, nghttp2_hd_map *map,
+ uint32_t hash) {
+ search_result res = {-1, 0};
+ nghttp2_hd_entry *ent;
+ int exact_match;
+ int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
+
+ exact_match = 0;
+ ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
+
+ if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
+ return search_static_table(nv, token, name_only);
+ }
+
+ if (ent == NULL) {
+ return res;
+ }
+
+ res.index =
+ (ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH);
+ res.name_value_match = exact_match;
+
+ return res;
+}
+
+static void hd_context_shrink_table_size(nghttp2_hd_context *context,
+ nghttp2_hd_map *map) {
+ nghttp2_mem *mem;
+
+ mem = context->mem;
+
+ while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
+ context->hd_table.len > 0) {
+ size_t idx = context->hd_table.len - 1;
+ nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
+ context->hd_table_bufsize -=
+ entry_room(ent->nv.name->len, ent->nv.value->len);
+ hd_ringbuf_pop_back(&context->hd_table);
+ if (map) {
+ hd_map_remove(map, ent);
+ }
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
+ }
+}
+
+int nghttp2_hd_deflate_change_table_size(
+ nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
+ size_t next_bufsize = nghttp2_min(settings_max_dynamic_table_size,
+ deflater->deflate_hd_table_bufsize_max);
+
+ deflater->ctx.hd_table_bufsize_max = next_bufsize;
+
+ deflater->min_hd_table_bufsize_max =
+ nghttp2_min(deflater->min_hd_table_bufsize_max, next_bufsize);
+
+ deflater->notify_table_size_change = 1;
+
+ hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
+ return 0;
+}
+
+int nghttp2_hd_inflate_change_table_size(
+ nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
+ switch (inflater->state) {
+ case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
+ case NGHTTP2_HD_STATE_INFLATE_START:
+ break;
+ default:
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ /* It seems that encoder is not required to send dynamic table size
+ update if the table size is not changed after applying
+ SETTINGS_HEADER_TABLE_SIZE. RFC 7541 is ambiguous here, but this
+ is the intention of the editor. If new maximum table size is
+ strictly smaller than the current negotiated maximum size,
+ encoder must send dynamic table size update. In other cases, we
+ cannot expect it to do so. */
+ if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
+ inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
+ /* Remember minimum value, and validate that encoder sends the
+ value less than or equal to this. */
+ inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
+ }
+
+ inflater->settings_hd_table_bufsize_max = settings_max_dynamic_table_size;
+
+ inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
+
+ hd_context_shrink_table_size(&inflater->ctx, NULL);
+ return 0;
+}
+
+#define INDEX_RANGE_VALID(context, idx) \
+ ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
+
+static size_t get_max_index(nghttp2_hd_context *context) {
+ return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
+}
+
+nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
+ assert(INDEX_RANGE_VALID(context, idx));
+ if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
+ return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
+ ->nv;
+ } else {
+ nghttp2_hd_static_entry *ent = &static_table[idx];
+ nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token,
+ NGHTTP2_NV_FLAG_NONE};
+ return nv;
+ }
+}
+
+static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
+ size_t idx) {
+ assert(INDEX_RANGE_VALID(context, idx));
+ if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
+ return &hd_ringbuf_get(&context->hd_table,
+ idx - NGHTTP2_STATIC_TABLE_LENGTH)
+ ->cnv;
+ }
+
+ return &static_table[idx].cnv;
+}
+
+static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
+ const nghttp2_nv *nv, int32_t token) {
+ if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
+ token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
+ token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
+ token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
+ token == NGHTTP2_TOKEN_SET_COOKIE ||
+ entry_room(nv->namelen, nv->valuelen) >
+ deflater->ctx.hd_table_bufsize_max * 3 / 4) {
+ return NGHTTP2_HD_WITHOUT_INDEXING;
+ }
+
+ return NGHTTP2_HD_WITH_INDEXING;
+}
+
+static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
+ const nghttp2_nv *nv) {
+ int rv;
+ search_result res;
+ ssize_t idx;
+ int indexing_mode;
+ int32_t token;
+ nghttp2_mem *mem;
+ uint32_t hash = 0;
+
+ DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
+ (int)nv->valuelen, nv->value);
+
+ mem = deflater->ctx.mem;
+
+ token = lookup_token(nv->name, nv->namelen);
+ if (token == -1) {
+ hash = name_hash(nv);
+ } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
+ hash = static_table[token].hash;
+ }
+
+ /* Don't index authorization header field since it may contain low
+ entropy secret data (e.g., id/password). Also cookie header
+ field with less than 20 bytes value is also never indexed. This
+ is the same criteria used in Firefox codebase. */
+ indexing_mode =
+ token == NGHTTP2_TOKEN_AUTHORIZATION ||
+ (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
+ (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
+ ? NGHTTP2_HD_NEVER_INDEXING
+ : hd_deflate_decide_indexing(deflater, nv, token);
+
+ res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
+ &deflater->map, hash);
+
+ idx = res.index;
+
+ if (res.name_value_match) {
+
+ DEBUGF("deflatehd: name/value match index=%zd\n", idx);
+
+ rv = emit_indexed_block(bufs, (size_t)idx);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+ }
+
+ if (res.index != -1) {
+ DEBUGF("deflatehd: name match index=%zd\n", res.index);
+ }
+
+ if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
+ nghttp2_hd_nv hd_nv;
+
+ if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) {
+ hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
+ nghttp2_rcbuf_incref(hd_nv.name);
+ } else {
+ rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
+
+ if (rv != 0) {
+ nghttp2_rcbuf_decref(hd_nv.name);
+ return rv;
+ }
+
+ hd_nv.token = token;
+ hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
+
+ rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
+
+ nghttp2_rcbuf_decref(hd_nv.value);
+ nghttp2_rcbuf_decref(hd_nv.name);
+
+ if (rv != 0) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ }
+ if (idx == -1) {
+ rv = emit_newname_block(bufs, nv, indexing_mode);
+ } else {
+ rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
+ }
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
+ nghttp2_bufs *bufs, const nghttp2_nv *nv,
+ size_t nvlen) {
+ size_t i;
+ int rv = 0;
+
+ if (deflater->ctx.bad) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ if (deflater->notify_table_size_change) {
+ size_t min_hd_table_bufsize_max;
+
+ min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
+
+ deflater->notify_table_size_change = 0;
+ deflater->min_hd_table_bufsize_max = UINT32_MAX;
+
+ if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
+
+ rv = emit_table_size(bufs, min_hd_table_bufsize_max);
+
+ if (rv != 0) {
+ goto fail;
+ }
+ }
+
+ rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
+
+ if (rv != 0) {
+ goto fail;
+ }
+ }
+
+ for (i = 0; i < nvlen; ++i) {
+ rv = deflate_nv(deflater, bufs, &nv[i]);
+ if (rv != 0) {
+ goto fail;
+ }
+ }
+
+ DEBUGF("deflatehd: all input name/value pairs were deflated\n");
+
+ return 0;
+fail:
+ DEBUGF("deflatehd: error return %d\n", rv);
+
+ deflater->ctx.bad = 1;
+ return rv;
+}
+
+ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
+ size_t buflen, const nghttp2_nv *nv,
+ size_t nvlen) {
+ nghttp2_bufs bufs;
+ int rv;
+ nghttp2_mem *mem;
+
+ mem = deflater->ctx.mem;
+
+ rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
+
+ buflen = nghttp2_bufs_len(&bufs);
+
+ nghttp2_bufs_wrap_free(&bufs);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ return NGHTTP2_ERR_INSUFF_BUFSIZE;
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return (ssize_t)buflen;
+}
+
+ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
+ const nghttp2_vec *vec, size_t veclen,
+ const nghttp2_nv *nv, size_t nvlen) {
+ nghttp2_bufs bufs;
+ int rv;
+ nghttp2_mem *mem;
+ size_t buflen;
+
+ mem = deflater->ctx.mem;
+
+ rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
+
+ buflen = nghttp2_bufs_len(&bufs);
+
+ nghttp2_bufs_wrap_free(&bufs);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ return NGHTTP2_ERR_INSUFF_BUFSIZE;
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return (ssize_t)buflen;
+}
+
+size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
+ const nghttp2_nv *nva, size_t nvlen) {
+ size_t n = 0;
+ size_t i;
+ (void)deflater;
+
+ /* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
+ 1 using 4 bit prefix requires 6 bytes. We may emit this at most
+ twice. */
+ n += 12;
+
+ /* Use Literal Header Field without indexing - New Name, since it is
+ most space consuming format. Also we choose the less one between
+ non-huffman and huffman, so using literal byte count is
+ sufficient for upper bound.
+
+ Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes. We
+ need 2 of this for |nvlen| header fields. */
+ n += 6 * 2 * nvlen;
+
+ for (i = 0; i < nvlen; ++i) {
+ n += nva[i].namelen + nva[i].valuelen;
+ }
+
+ return n;
+}
+
+int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
+ size_t deflate_hd_table_bufsize_max) {
+ return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
+ NULL);
+}
+
+int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
+ size_t deflate_hd_table_bufsize_max,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_hd_deflater *deflater;
+
+ if (mem == NULL) {
+ mem = nghttp2_mem_default();
+ }
+
+ deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
+
+ if (deflater == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
+
+ if (rv != 0) {
+ nghttp2_mem_free(mem, deflater);
+
+ return rv;
+ }
+
+ *deflater_ptr = deflater;
+
+ return 0;
+}
+
+void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
+ nghttp2_mem *mem;
+
+ mem = deflater->ctx.mem;
+
+ nghttp2_hd_deflate_free(deflater);
+
+ nghttp2_mem_free(mem, deflater);
+}
+
+static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
+ const uint8_t *in) {
+ inflater->huffman_encoded = (*in & (1 << 7)) != 0;
+}
+
+/*
+ * Decodes the integer from the range [in, last). The result is
+ * assigned to |inflater->left|. If the |inflater->left| is 0, then
+ * it performs variable integer decoding from scratch. Otherwise, it
+ * uses the |inflater->left| as the initial value and continues to
+ * decode assuming that [in, last) begins with intermediary sequence.
+ *
+ * This function returns the number of bytes read if it succeeds, or
+ * one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * Integer decoding failed
+ */
+static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
+ const uint8_t *in, const uint8_t *last,
+ size_t prefix, size_t maxlen) {
+ ssize_t rv;
+ uint32_t out;
+
+ *rfin = 0;
+
+ rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
+ inflater->shift, in, last, prefix);
+
+ if (rv == -1) {
+ DEBUGF("inflatehd: integer decoding failed\n");
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ if (out > maxlen) {
+ DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ inflater->left = out;
+
+ DEBUGF("inflatehd: decoded integer is %u\n", out);
+
+ return rv;
+}
+
+/*
+ * Reads |inflater->left| bytes from the range [in, last) and performs
+ * huffman decoding against them and pushes the result into the
+ * |buffer|.
+ *
+ * This function returns the number of bytes read if it succeeds, or
+ * one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_HEADER_COMP
+ * Huffman decoding failed
+ */
+static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
+ nghttp2_buf *buf, const uint8_t *in,
+ const uint8_t *last) {
+ ssize_t readlen;
+ int fin = 0;
+ if ((size_t)(last - in) >= inflater->left) {
+ last = in + inflater->left;
+ fin = 1;
+ }
+ readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
+ (size_t)(last - in), fin);
+
+ if (readlen < 0) {
+ DEBUGF("inflatehd: huffman decoding failed\n");
+ return readlen;
+ }
+ inflater->left -= (size_t)readlen;
+ return readlen;
+}
+
+/*
+ * Reads |inflater->left| bytes from the range [in, last) and copies
+ * them into the |buffer|.
+ *
+ * This function returns the number of bytes read if it succeeds, or
+ * one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_HEADER_COMP
+ * Header decompression failed
+ */
+static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
+ const uint8_t *in, const uint8_t *last) {
+ size_t len = nghttp2_min((size_t)(last - in), inflater->left);
+
+ buf->last = nghttp2_cpymem(buf->last, in, len);
+
+ inflater->left -= len;
+ return (ssize_t)len;
+}
+
+/*
+ * Finalize indexed header representation reception. The referenced
+ * header is always emitted, and |*nv_out| is filled with that value.
+ */
+static void hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
+
+ emit_header(nv_out, &nv);
+}
+
+/*
+ * Finalize literal header representation - new name- reception. If
+ * header is emitted, |*nv_out| is filled with that value and 0 is
+ * returned.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv;
+ int rv;
+
+ if (inflater->no_index) {
+ nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
+ } else {
+ nv.flags = NGHTTP2_NV_FLAG_NONE;
+ }
+
+ nv.name = inflater->namercbuf;
+ nv.value = inflater->valuercbuf;
+ nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
+
+ if (inflater->index_required) {
+ rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
+
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ emit_header(nv_out, &nv);
+
+ inflater->nv_name_keep = nv.name;
+ inflater->nv_value_keep = nv.value;
+
+ inflater->namercbuf = NULL;
+ inflater->valuercbuf = NULL;
+
+ return 0;
+}
+
+/*
+ * Finalize literal header representation - indexed name-
+ * reception. If header is emitted, |*nv_out| is filled with that
+ * value and 0 is returned.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv;
+ int rv;
+
+ nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
+
+ if (inflater->no_index) {
+ nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
+ } else {
+ nv.flags = NGHTTP2_NV_FLAG_NONE;
+ }
+
+ nghttp2_rcbuf_incref(nv.name);
+
+ nv.value = inflater->valuercbuf;
+
+ if (inflater->index_required) {
+ rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
+ if (rv != 0) {
+ nghttp2_rcbuf_decref(nv.name);
+ return NGHTTP2_ERR_NOMEM;
+ }
+ }
+
+ emit_header(nv_out, &nv);
+
+ inflater->nv_name_keep = nv.name;
+ inflater->nv_value_keep = nv.value;
+
+ inflater->valuercbuf = NULL;
+
+ return 0;
+}
+
+ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
+ int *inflate_flags, uint8_t *in, size_t inlen,
+ int in_final) {
+ return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
+ in_final);
+}
+
+ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen, int in_final) {
+ ssize_t rv;
+ nghttp2_hd_nv hd_nv;
+
+ rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
+ in_final);
+
+ if (rv < 0) {
+ return rv;
+ }
+
+ if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ nv_out->name = hd_nv.name->base;
+ nv_out->namelen = hd_nv.name->len;
+
+ nv_out->value = hd_nv.value->base;
+ nv_out->valuelen = hd_nv.value->len;
+
+ nv_out->flags = hd_nv.flags;
+ }
+
+ return rv;
+}
+
+ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen,
+ int in_final) {
+ ssize_t rv = 0;
+ const uint8_t *first = in;
+ const uint8_t *last = in + inlen;
+ int rfin = 0;
+ int busy = 0;
+ nghttp2_mem *mem;
+
+ mem = inflater->ctx.mem;
+
+ if (inflater->ctx.bad) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ DEBUGF("inflatehd: start state=%d\n", inflater->state);
+ hd_inflate_keep_free(inflater);
+ *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
+ for (; in != last || busy;) {
+ busy = 0;
+ switch (inflater->state) {
+ case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
+ if ((*in & 0xe0u) != 0x20u) {
+ DEBUGF("inflatehd: header table size change was expected, but saw "
+ "0x%02x as first byte",
+ *in);
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+ /* fall through */
+ case NGHTTP2_HD_STATE_INFLATE_START:
+ case NGHTTP2_HD_STATE_OPCODE:
+ if ((*in & 0xe0u) == 0x20u) {
+ DEBUGF("inflatehd: header table size change\n");
+ if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
+ DEBUGF("inflatehd: header table size change must appear at the head "
+ "of header block\n");
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+ inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
+ inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
+ } else if (*in & 0x80u) {
+ DEBUGF("inflatehd: indexed repr\n");
+ inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
+ inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
+ } else {
+ if (*in == 0x40u || *in == 0 || *in == 0x10u) {
+ DEBUGF("inflatehd: literal header repr - new name\n");
+ inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
+ } else {
+ DEBUGF("inflatehd: literal header repr - indexed name\n");
+ inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
+ inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
+ }
+ inflater->index_required = (*in & 0x40) != 0;
+ inflater->no_index = (*in & 0xf0u) == 0x10u;
+ DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
+ inflater->index_required, inflater->no_index);
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
+ ++in;
+ }
+ }
+ inflater->left = 0;
+ inflater->shift = 0;
+ break;
+ case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
+ rfin = 0;
+ rv = hd_inflate_read_len(
+ inflater, &rfin, in, last, 5,
+ nghttp2_min(inflater->min_hd_table_bufsize_max,
+ inflater->settings_hd_table_bufsize_max));
+ if (rv < 0) {
+ goto fail;
+ }
+ in += rv;
+ if (!rfin) {
+ goto almost_ok;
+ }
+ DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
+ inflater->min_hd_table_bufsize_max = UINT32_MAX;
+ inflater->ctx.hd_table_bufsize_max = inflater->left;
+ hd_context_shrink_table_size(&inflater->ctx, NULL);
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
+ break;
+ case NGHTTP2_HD_STATE_READ_INDEX: {
+ size_t prefixlen;
+
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
+ prefixlen = 7;
+ } else if (inflater->index_required) {
+ prefixlen = 6;
+ } else {
+ prefixlen = 4;
+ }
+
+ rfin = 0;
+ rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
+ get_max_index(&inflater->ctx));
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ if (!rfin) {
+ goto almost_ok;
+ }
+
+ if (inflater->left == 0) {
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+
+ DEBUGF("inflatehd: index=%zu\n", inflater->left);
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
+ inflater->index = inflater->left;
+ --inflater->index;
+
+ hd_inflate_commit_indexed(inflater, nv_out);
+
+ inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
+ return (ssize_t)(in - first);
+ } else {
+ inflater->index = inflater->left;
+ --inflater->index;
+
+ inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
+ }
+ break;
+ }
+ case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
+ hd_inflate_set_huffman_encoded(inflater, in);
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
+ inflater->left = 0;
+ inflater->shift = 0;
+ DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
+ /* Fall through */
+ case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
+ rfin = 0;
+ rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
+ if (rv < 0) {
+ goto fail;
+ }
+ in += rv;
+ if (!rfin) {
+ DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
+ inflater->left);
+
+ goto almost_ok;
+ }
+
+ if (inflater->huffman_encoded) {
+ nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
+
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
+
+ rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
+ mem);
+ } else {
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
+ rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
+ inflater->namercbuf->len);
+
+ break;
+ case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
+ rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+
+ goto almost_ok;
+ }
+
+ *inflater->namebuf.last = '\0';
+ inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
+
+ inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
+
+ break;
+ case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
+ rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+
+ goto almost_ok;
+ }
+
+ *inflater->namebuf.last = '\0';
+ inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
+
+ inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
+
+ break;
+ case NGHTTP2_HD_STATE_CHECK_VALUELEN:
+ hd_inflate_set_huffman_encoded(inflater, in);
+ inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
+ inflater->left = 0;
+ inflater->shift = 0;
+ DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
+ /* Fall through */
+ case NGHTTP2_HD_STATE_READ_VALUELEN:
+ rfin = 0;
+ rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ if (!rfin) {
+ goto almost_ok;
+ }
+
+ DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
+
+ if (inflater->huffman_encoded) {
+ nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
+
+ inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
+
+ rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
+ mem);
+ } else {
+ inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
+
+ rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
+ inflater->valuercbuf->len);
+
+ busy = 1;
+
+ break;
+ case NGHTTP2_HD_STATE_READ_VALUEHUFF:
+ rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+
+ goto almost_ok;
+ }
+
+ *inflater->valuebuf.last = '\0';
+ inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
+
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
+ rv = hd_inflate_commit_newname(inflater, nv_out);
+ } else {
+ rv = hd_inflate_commit_indname(inflater, nv_out);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
+
+ return (ssize_t)(in - first);
+ case NGHTTP2_HD_STATE_READ_VALUE:
+ rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
+ if (rv < 0) {
+ DEBUGF("inflatehd: value read failure %zd: %s\n", rv,
+ nghttp2_strerror((int)rv));
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+ goto almost_ok;
+ }
+
+ *inflater->valuebuf.last = '\0';
+ inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
+
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
+ rv = hd_inflate_commit_newname(inflater, nv_out);
+ } else {
+ rv = hd_inflate_commit_indname(inflater, nv_out);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
+
+ return (ssize_t)(in - first);
+ }
+ }
+
+ assert(in == last);
+
+ DEBUGF("inflatehd: all input bytes were processed\n");
+
+ if (in_final) {
+ DEBUGF("inflatehd: in_final set\n");
+
+ if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
+ inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
+ DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
+ rv = NGHTTP2_ERR_HEADER_COMP;
+
+ goto fail;
+ }
+ *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
+ }
+ return (ssize_t)(in - first);
+
+almost_ok:
+ if (in_final) {
+ DEBUGF("inflatehd: input ended prematurely\n");
+
+ rv = NGHTTP2_ERR_HEADER_COMP;
+
+ goto fail;
+ }
+ return (ssize_t)(in - first);
+
+fail:
+ DEBUGF("inflatehd: error return %zd\n", rv);
+
+ inflater->ctx.bad = 1;
+ return rv;
+}
+
+int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
+ hd_inflate_keep_free(inflater);
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
+ return 0;
+}
+
+int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) {
+ return nghttp2_hd_inflate_new2(inflater_ptr, NULL);
+}
+
+int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_hd_inflater *inflater;
+
+ if (mem == NULL) {
+ mem = nghttp2_mem_default();
+ }
+
+ inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater));
+
+ if (inflater == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ rv = nghttp2_hd_inflate_init(inflater, mem);
+
+ if (rv != 0) {
+ nghttp2_mem_free(mem, inflater);
+
+ return rv;
+ }
+
+ *inflater_ptr = inflater;
+
+ return 0;
+}
+
+void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
+ nghttp2_mem *mem;
+
+ mem = inflater->ctx.mem;
+ nghttp2_hd_inflate_free(inflater);
+
+ nghttp2_mem_free(mem, inflater);
+}
+
+int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
+ nghttp2_nv *nv, int indexing_mode) {
+
+ return emit_indname_block(bufs, idx, nv, indexing_mode);
+}
+
+int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
+ int indexing_mode) {
+ return emit_newname_block(bufs, nv, indexing_mode);
+}
+
+int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
+ return emit_table_size(bufs, table_size);
+}
+
+ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
+ uint32_t initial, size_t shift, uint8_t *in,
+ uint8_t *last, size_t prefix) {
+ return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
+}
+
+static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
+ size_t idx) {
+ if (idx == 0) {
+ return NULL;
+ }
+
+ --idx;
+
+ if (!INDEX_RANGE_VALID(context, idx)) {
+ return NULL;
+ }
+
+ return nghttp2_hd_table_get2(context, idx);
+}
+
+size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) {
+ return get_max_index(&deflater->ctx);
+}
+
+const nghttp2_nv *
+nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) {
+ return hd_get_table_entry(&deflater->ctx, idx);
+}
+
+size_t
+nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) {
+ return deflater->ctx.hd_table_bufsize;
+}
+
+size_t
+nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) {
+ return deflater->ctx.hd_table_bufsize_max;
+}
+
+size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) {
+ return get_max_index(&inflater->ctx);
+}
+
+const nghttp2_nv *
+nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) {
+ return hd_get_table_entry(&inflater->ctx, idx);
+}
+
+size_t
+nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) {
+ return inflater->ctx.hd_table_bufsize;
+}
+
+size_t
+nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) {
+ return inflater->ctx.hd_table_bufsize_max;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd.h
new file mode 100644
index 00000000..584dad39
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd.h
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HD_H
+#define NGHTTP2_HD_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#include "nghttp2_hd_huffman.h"
+#include "nghttp2_buf.h"
+#include "nghttp2_mem.h"
+#include "nghttp2_rcbuf.h"
+
+#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
+#define NGHTTP2_HD_ENTRY_OVERHEAD 32
+
+/* The maximum length of one name/value pair. This is the sum of the
+ length of name and value. This is not specified by the spec. We
+ just chose the arbitrary size */
+#define NGHTTP2_HD_MAX_NV 65536
+
+/* Default size of maximum table buffer size for encoder. Even if
+ remote decoder notifies larger buffer size for its decoding,
+ encoder only uses the memory up to this value. */
+#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
+
+/* Exported for unit test */
+#define NGHTTP2_STATIC_TABLE_LENGTH 61
+
+/* Generated by genlibtokenlookup.py */
+typedef enum {
+ NGHTTP2_TOKEN__AUTHORITY = 0,
+ NGHTTP2_TOKEN__METHOD = 1,
+ NGHTTP2_TOKEN__PATH = 3,
+ NGHTTP2_TOKEN__SCHEME = 5,
+ NGHTTP2_TOKEN__STATUS = 7,
+ NGHTTP2_TOKEN_ACCEPT_CHARSET = 14,
+ NGHTTP2_TOKEN_ACCEPT_ENCODING = 15,
+ NGHTTP2_TOKEN_ACCEPT_LANGUAGE = 16,
+ NGHTTP2_TOKEN_ACCEPT_RANGES = 17,
+ NGHTTP2_TOKEN_ACCEPT = 18,
+ NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 19,
+ NGHTTP2_TOKEN_AGE = 20,
+ NGHTTP2_TOKEN_ALLOW = 21,
+ NGHTTP2_TOKEN_AUTHORIZATION = 22,
+ NGHTTP2_TOKEN_CACHE_CONTROL = 23,
+ NGHTTP2_TOKEN_CONTENT_DISPOSITION = 24,
+ NGHTTP2_TOKEN_CONTENT_ENCODING = 25,
+ NGHTTP2_TOKEN_CONTENT_LANGUAGE = 26,
+ NGHTTP2_TOKEN_CONTENT_LENGTH = 27,
+ NGHTTP2_TOKEN_CONTENT_LOCATION = 28,
+ NGHTTP2_TOKEN_CONTENT_RANGE = 29,
+ NGHTTP2_TOKEN_CONTENT_TYPE = 30,
+ NGHTTP2_TOKEN_COOKIE = 31,
+ NGHTTP2_TOKEN_DATE = 32,
+ NGHTTP2_TOKEN_ETAG = 33,
+ NGHTTP2_TOKEN_EXPECT = 34,
+ NGHTTP2_TOKEN_EXPIRES = 35,
+ NGHTTP2_TOKEN_FROM = 36,
+ NGHTTP2_TOKEN_HOST = 37,
+ NGHTTP2_TOKEN_IF_MATCH = 38,
+ NGHTTP2_TOKEN_IF_MODIFIED_SINCE = 39,
+ NGHTTP2_TOKEN_IF_NONE_MATCH = 40,
+ NGHTTP2_TOKEN_IF_RANGE = 41,
+ NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE = 42,
+ NGHTTP2_TOKEN_LAST_MODIFIED = 43,
+ NGHTTP2_TOKEN_LINK = 44,
+ NGHTTP2_TOKEN_LOCATION = 45,
+ NGHTTP2_TOKEN_MAX_FORWARDS = 46,
+ NGHTTP2_TOKEN_PROXY_AUTHENTICATE = 47,
+ NGHTTP2_TOKEN_PROXY_AUTHORIZATION = 48,
+ NGHTTP2_TOKEN_RANGE = 49,
+ NGHTTP2_TOKEN_REFERER = 50,
+ NGHTTP2_TOKEN_REFRESH = 51,
+ NGHTTP2_TOKEN_RETRY_AFTER = 52,
+ NGHTTP2_TOKEN_SERVER = 53,
+ NGHTTP2_TOKEN_SET_COOKIE = 54,
+ NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY = 55,
+ NGHTTP2_TOKEN_TRANSFER_ENCODING = 56,
+ NGHTTP2_TOKEN_USER_AGENT = 57,
+ NGHTTP2_TOKEN_VARY = 58,
+ NGHTTP2_TOKEN_VIA = 59,
+ NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,
+ NGHTTP2_TOKEN_TE,
+ NGHTTP2_TOKEN_CONNECTION,
+ NGHTTP2_TOKEN_KEEP_ALIVE,
+ NGHTTP2_TOKEN_PROXY_CONNECTION,
+ NGHTTP2_TOKEN_UPGRADE,
+} nghttp2_token;
+
+struct nghttp2_hd_entry;
+typedef struct nghttp2_hd_entry nghttp2_hd_entry;
+
+typedef struct {
+ /* The buffer containing header field name. NULL-termination is
+ guaranteed. */
+ nghttp2_rcbuf *name;
+ /* The buffer containing header field value. NULL-termination is
+ guaranteed. */
+ nghttp2_rcbuf *value;
+ /* nghttp2_token value for name. It could be -1 if we have no token
+ for that header field name. */
+ int32_t token;
+ /* Bitwise OR of one or more of nghttp2_nv_flag. */
+ uint8_t flags;
+} nghttp2_hd_nv;
+
+struct nghttp2_hd_entry {
+ /* The header field name/value pair */
+ nghttp2_hd_nv nv;
+ /* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry
+ APIs to keep backward compatibility. */
+ nghttp2_nv cnv;
+ /* The next entry which shares same bucket in hash table. */
+ nghttp2_hd_entry *next;
+ /* The sequence number. We will increment it by one whenever we
+ store nghttp2_hd_entry to dynamic header table. */
+ uint32_t seq;
+ /* The hash value for header name (nv.name). */
+ uint32_t hash;
+};
+
+/* The entry used for static header table. */
+typedef struct {
+ nghttp2_rcbuf name;
+ nghttp2_rcbuf value;
+ nghttp2_nv cnv;
+ int32_t token;
+ uint32_t hash;
+} nghttp2_hd_static_entry;
+
+typedef struct {
+ nghttp2_hd_entry **buffer;
+ size_t mask;
+ size_t first;
+ size_t len;
+} nghttp2_hd_ringbuf;
+
+typedef enum {
+ NGHTTP2_HD_OPCODE_NONE,
+ NGHTTP2_HD_OPCODE_INDEXED,
+ NGHTTP2_HD_OPCODE_NEWNAME,
+ NGHTTP2_HD_OPCODE_INDNAME
+} nghttp2_hd_opcode;
+
+typedef enum {
+ NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE,
+ NGHTTP2_HD_STATE_INFLATE_START,
+ NGHTTP2_HD_STATE_OPCODE,
+ NGHTTP2_HD_STATE_READ_TABLE_SIZE,
+ NGHTTP2_HD_STATE_READ_INDEX,
+ NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,
+ NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN,
+ NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF,
+ NGHTTP2_HD_STATE_NEWNAME_READ_NAME,
+ NGHTTP2_HD_STATE_CHECK_VALUELEN,
+ NGHTTP2_HD_STATE_READ_VALUELEN,
+ NGHTTP2_HD_STATE_READ_VALUEHUFF,
+ NGHTTP2_HD_STATE_READ_VALUE
+} nghttp2_hd_inflate_state;
+
+typedef enum {
+ NGHTTP2_HD_WITH_INDEXING,
+ NGHTTP2_HD_WITHOUT_INDEXING,
+ NGHTTP2_HD_NEVER_INDEXING
+} nghttp2_hd_indexing_mode;
+
+typedef struct {
+ /* dynamic header table */
+ nghttp2_hd_ringbuf hd_table;
+ /* Memory allocator */
+ nghttp2_mem *mem;
+ /* Abstract buffer size of hd_table as described in the spec. This
+ is the sum of length of name/value in hd_table +
+ NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */
+ size_t hd_table_bufsize;
+ /* The effective header table size. */
+ size_t hd_table_bufsize_max;
+ /* Next sequence number for nghttp2_hd_entry */
+ uint32_t next_seq;
+ /* If inflate/deflate error occurred, this value is set to 1 and
+ further invocation of inflate/deflate will fail with
+ NGHTTP2_ERR_HEADER_COMP. */
+ uint8_t bad;
+} nghttp2_hd_context;
+
+#define HD_MAP_SIZE 128
+
+typedef struct {
+ nghttp2_hd_entry *table[HD_MAP_SIZE];
+} nghttp2_hd_map;
+
+struct nghttp2_hd_deflater {
+ nghttp2_hd_context ctx;
+ nghttp2_hd_map map;
+ /* The upper limit of the header table size the deflater accepts. */
+ size_t deflate_hd_table_bufsize_max;
+ /* Minimum header table size notified in the next context update */
+ size_t min_hd_table_bufsize_max;
+ /* If nonzero, send header table size using encoding context update
+ in the next deflate process */
+ uint8_t notify_table_size_change;
+};
+
+struct nghttp2_hd_inflater {
+ nghttp2_hd_context ctx;
+ /* Stores current state of huffman decoding */
+ nghttp2_hd_huff_decode_context huff_decode_ctx;
+ /* header buffer */
+ nghttp2_buf namebuf, valuebuf;
+ nghttp2_rcbuf *namercbuf, *valuercbuf;
+ /* Pointer to the name/value pair which are used in the current
+ header emission. */
+ nghttp2_rcbuf *nv_name_keep, *nv_value_keep;
+ /* The number of bytes to read */
+ size_t left;
+ /* The index in indexed repr or indexed name */
+ size_t index;
+ /* The maximum header table size the inflater supports. This is the
+ same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
+ size_t settings_hd_table_bufsize_max;
+ /* Minimum header table size set by nghttp2_hd_inflate_change_table_size */
+ size_t min_hd_table_bufsize_max;
+ /* The number of next shift to decode integer */
+ size_t shift;
+ nghttp2_hd_opcode opcode;
+ nghttp2_hd_inflate_state state;
+ /* nonzero if string is huffman encoded */
+ uint8_t huffman_encoded;
+ /* nonzero if deflater requires that current entry is indexed */
+ uint8_t index_required;
+ /* nonzero if deflater requires that current entry must not be
+ indexed */
+ uint8_t no_index;
+};
+
+/*
+ * Initializes the |ent| members. The reference counts of nv->name
+ * and nv->value are increased by one for each.
+ */
+void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv);
+
+/*
+ * This function decreases the reference counts of nv->name and
+ * nv->value.
+ */
+void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
+
+/*
+ * Initializes |deflater| for deflating name/values pairs.
+ *
+ * The encoder only uses up to
+ * NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE bytes for header table
+ * even if the larger value is specified later in
+ * nghttp2_hd_change_table_size().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
+
+/*
+ * Initializes |deflater| for deflating name/values pairs.
+ *
+ * The encoder only uses up to |max_deflate_dynamic_table_size| bytes
+ * for header table even if the larger value is specified later in
+ * nghttp2_hd_change_table_size().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
+ size_t max_deflate_dynamic_table_size,
+ nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |deflater|.
+ */
+void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
+
+/*
+ * Deflates the |nva|, which has the |nvlen| name/value pairs, into
+ * the |bufs|.
+ *
+ * This function expands |bufs| as necessary to store the result. If
+ * buffers is full and the process still requires more space, this
+ * function fails and returns NGHTTP2_ERR_HEADER_COMP.
+ *
+ * After this function returns, it is safe to delete the |nva|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_HEADER_COMP
+ * Deflation process has failed.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
+ nghttp2_bufs *bufs, const nghttp2_nv *nva,
+ size_t nvlen);
+
+/*
+ * Initializes |inflater| for inflating name/values pairs.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |inflater|.
+ */
+void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
+
+/*
+ * Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv
+ * instead of nghttp2_nv as output parameter |nv_out|. Other than
+ * that return values and semantics are the same as
+ * nghttp2_hd_inflate_hd().
+ */
+ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen, int in_final);
+
+/* For unittesting purpose */
+int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
+ nghttp2_nv *nv, int indexing_mode);
+
+/* For unittesting purpose */
+int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
+ int indexing_mode);
+
+/* For unittesting purpose */
+int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
+
+/* For unittesting purpose */
+nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
+
+/* For unittesting purpose */
+ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
+ uint32_t initial, size_t shift, uint8_t *in,
+ uint8_t *last, size_t prefix);
+
+/* Huffman encoding/decoding functions */
+
+/*
+ * Counts the required bytes to encode |src| with length |len|.
+ *
+ * This function returns the number of required bytes to encode given
+ * data, including padding of prefix of terminal symbol code. This
+ * function always succeeds.
+ */
+size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);
+
+/*
+ * Encodes the given data |src| with length |srclen| to the |bufs|.
+ * This function expands extra buffers in |bufs| if necessary.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
+ size_t srclen);
+
+void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
+
+/*
+ * Decodes the given data |src| with length |srclen|. The |ctx| must
+ * be initialized by nghttp2_hd_huff_decode_context_init(). The result
+ * will be written to |buf|. This function assumes that |buf| has the
+ * enough room to store the decoded byte string.
+ *
+ * The caller must set the |fin| to nonzero if the given input is the
+ * final block.
+ *
+ * This function returns the number of read bytes from the |in|.
+ *
+ * If this function fails, it returns one of the following negative
+ * return codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_HEADER_COMP
+ * Decoding process has failed.
+ */
+ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
+ nghttp2_buf *buf, const uint8_t *src,
+ size_t srclen, int fin);
+
+#endif /* NGHTTP2_HD_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman.c
new file mode 100644
index 00000000..661668de
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_hd_huffman.h"
+
+#include
+#include
+#include
+
+#include "nghttp2_hd.h"
+
+/*
+ * Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
+ * bits are not filled yet. The |rembits| must be in range [1, 8],
+ * inclusive. At the end of the process, the |*dest_ptr| is updated
+ * and points where next output should be placed. The number of
+ * unfilled bits in the pointed location is returned.
+ */
+static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
+ size_t rembits, const nghttp2_huff_sym *sym) {
+ int rv;
+ size_t nbits = sym->nbits;
+ uint32_t code = sym->code;
+
+ /* We assume that sym->nbits <= 32 */
+ if (rembits > nbits) {
+ nghttp2_bufs_fast_orb_hold(bufs, (uint8_t)(code << (rembits - nbits)));
+ return (ssize_t)(rembits - nbits);
+ }
+
+ if (rembits == nbits) {
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)code);
+ --*avail_ptr;
+ return 8;
+ }
+
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)(code >> (nbits - rembits)));
+ --*avail_ptr;
+
+ nbits -= rembits;
+ if (nbits & 0x7) {
+ /* align code to MSB byte boundary */
+ code <<= 8 - (nbits & 0x7);
+ }
+
+ if (*avail_ptr < (nbits + 7) / 8) {
+ /* slow path */
+ if (nbits > 24) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 24));
+ if (rv != 0) {
+ return rv;
+ }
+ nbits -= 8;
+ }
+ if (nbits > 16) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 16));
+ if (rv != 0) {
+ return rv;
+ }
+ nbits -= 8;
+ }
+ if (nbits > 8) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 8));
+ if (rv != 0) {
+ return rv;
+ }
+ nbits -= 8;
+ }
+ if (nbits == 8) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)code);
+ if (rv != 0) {
+ return rv;
+ }
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return 8;
+ }
+
+ rv = nghttp2_bufs_addb_hold(bufs, (uint8_t)code);
+ if (rv != 0) {
+ return rv;
+ }
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return (ssize_t)(8 - nbits);
+ }
+
+ /* fast path, since most code is less than 8 */
+ if (nbits < 8) {
+ nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return (ssize_t)(8 - nbits);
+ }
+
+ /* handle longer code path */
+ if (nbits > 24) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 24));
+ nbits -= 8;
+ }
+
+ if (nbits > 16) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 16));
+ nbits -= 8;
+ }
+
+ if (nbits > 8) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 8));
+ nbits -= 8;
+ }
+
+ if (nbits == 8) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)code);
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return 8;
+ }
+
+ nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return (ssize_t)(8 - nbits);
+}
+
+size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
+ size_t i;
+ size_t nbits = 0;
+
+ for (i = 0; i < len; ++i) {
+ nbits += huff_sym_table[src[i]].nbits;
+ }
+ /* pad the prefix of EOS (256) */
+ return (nbits + 7) / 8;
+}
+
+int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
+ size_t srclen) {
+ int rv;
+ ssize_t rembits = 8;
+ size_t i;
+ size_t avail;
+
+ avail = nghttp2_bufs_cur_avail(bufs);
+
+ for (i = 0; i < srclen; ++i) {
+ const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
+ if (rembits == 8) {
+ if (avail) {
+ nghttp2_bufs_fast_addb_hold(bufs, 0);
+ } else {
+ rv = nghttp2_bufs_addb_hold(bufs, 0);
+ if (rv != 0) {
+ return rv;
+ }
+ avail = nghttp2_bufs_cur_avail(bufs);
+ }
+ }
+ rembits = huff_encode_sym(bufs, &avail, (size_t)rembits, sym);
+ if (rembits < 0) {
+ return (int)rembits;
+ }
+ }
+ /* 256 is special terminal symbol, pad with its prefix */
+ if (rembits < 8) {
+ /* if rembits < 8, we should have at least 1 buffer space
+ available */
+ const nghttp2_huff_sym *sym = &huff_sym_table[256];
+ assert(avail);
+ /* Caution we no longer adjust avail here */
+ nghttp2_bufs_fast_orb(
+ bufs, (uint8_t)(sym->code >> (sym->nbits - (size_t)rembits)));
+ }
+
+ return 0;
+}
+
+void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
+ ctx->state = 0;
+ ctx->accept = 1;
+}
+
+ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
+ nghttp2_buf *buf, const uint8_t *src,
+ size_t srclen, int final) {
+ size_t i;
+
+ /* We use the decoding algorithm described in
+ http://graphics.ics.uci.edu/pub/Prefix.pdf */
+ for (i = 0; i < srclen; ++i) {
+ const nghttp2_huff_decode *t;
+
+ t = &huff_decode_table[ctx->state][src[i] >> 4];
+ if (t->flags & NGHTTP2_HUFF_FAIL) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ if (t->flags & NGHTTP2_HUFF_SYM) {
+ *buf->last++ = t->sym;
+ }
+
+ t = &huff_decode_table[t->state][src[i] & 0xf];
+ if (t->flags & NGHTTP2_HUFF_FAIL) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ if (t->flags & NGHTTP2_HUFF_SYM) {
+ *buf->last++ = t->sym;
+ }
+
+ ctx->state = t->state;
+ ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
+ }
+ if (final && !ctx->accept) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ return (ssize_t)i;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman.h
new file mode 100644
index 00000000..979f6b12
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HD_HUFFMAN_H
+#define NGHTTP2_HD_HUFFMAN_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+typedef enum {
+ /* FSA accepts this state as the end of huffman encoding
+ sequence. */
+ NGHTTP2_HUFF_ACCEPTED = 1,
+ /* This state emits symbol */
+ NGHTTP2_HUFF_SYM = (1 << 1),
+ /* If state machine reaches this state, decoding fails. */
+ NGHTTP2_HUFF_FAIL = (1 << 2)
+} nghttp2_huff_decode_flag;
+
+typedef struct {
+ /* huffman decoding state, which is actually the node ID of internal
+ huffman tree. We have 257 leaf nodes, but they are identical to
+ root node other than emitting a symbol, so we have 256 internal
+ nodes [1..255], inclusive. */
+ uint8_t state;
+ /* bitwise OR of zero or more of the nghttp2_huff_decode_flag */
+ uint8_t flags;
+ /* symbol if NGHTTP2_HUFF_SYM flag set */
+ uint8_t sym;
+} nghttp2_huff_decode;
+
+typedef nghttp2_huff_decode huff_decode_table_type[16];
+
+typedef struct {
+ /* Current huffman decoding state. We stripped leaf nodes, so the
+ value range is [0..255], inclusive. */
+ uint8_t state;
+ /* nonzero if we can say that the decoding process succeeds at this
+ state */
+ uint8_t accept;
+} nghttp2_hd_huff_decode_context;
+
+typedef struct {
+ /* The number of bits in this code */
+ uint32_t nbits;
+ /* Huffman code aligned to LSB */
+ uint32_t code;
+} nghttp2_huff_sym;
+
+extern const nghttp2_huff_sym huff_sym_table[];
+extern const nghttp2_huff_decode huff_decode_table[][16];
+
+#endif /* NGHTTP2_HD_HUFFMAN_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman_data.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman_data.c
new file mode 100644
index 00000000..085b2e92
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_hd_huffman_data.c
@@ -0,0 +1,4942 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_hd_huffman.h"
+
+/* Generated by mkhufftbl.py */
+
+const nghttp2_huff_sym huff_sym_table[] = {
+ {13, 0x1ff8u}, {23, 0x7fffd8u}, {28, 0xfffffe2u}, {28, 0xfffffe3u},
+ {28, 0xfffffe4u}, {28, 0xfffffe5u}, {28, 0xfffffe6u}, {28, 0xfffffe7u},
+ {28, 0xfffffe8u}, {24, 0xffffeau}, {30, 0x3ffffffcu}, {28, 0xfffffe9u},
+ {28, 0xfffffeau}, {30, 0x3ffffffdu}, {28, 0xfffffebu}, {28, 0xfffffecu},
+ {28, 0xfffffedu}, {28, 0xfffffeeu}, {28, 0xfffffefu}, {28, 0xffffff0u},
+ {28, 0xffffff1u}, {28, 0xffffff2u}, {30, 0x3ffffffeu}, {28, 0xffffff3u},
+ {28, 0xffffff4u}, {28, 0xffffff5u}, {28, 0xffffff6u}, {28, 0xffffff7u},
+ {28, 0xffffff8u}, {28, 0xffffff9u}, {28, 0xffffffau}, {28, 0xffffffbu},
+ {6, 0x14u}, {10, 0x3f8u}, {10, 0x3f9u}, {12, 0xffau},
+ {13, 0x1ff9u}, {6, 0x15u}, {8, 0xf8u}, {11, 0x7fau},
+ {10, 0x3fau}, {10, 0x3fbu}, {8, 0xf9u}, {11, 0x7fbu},
+ {8, 0xfau}, {6, 0x16u}, {6, 0x17u}, {6, 0x18u},
+ {5, 0x0u}, {5, 0x1u}, {5, 0x2u}, {6, 0x19u},
+ {6, 0x1au}, {6, 0x1bu}, {6, 0x1cu}, {6, 0x1du},
+ {6, 0x1eu}, {6, 0x1fu}, {7, 0x5cu}, {8, 0xfbu},
+ {15, 0x7ffcu}, {6, 0x20u}, {12, 0xffbu}, {10, 0x3fcu},
+ {13, 0x1ffau}, {6, 0x21u}, {7, 0x5du}, {7, 0x5eu},
+ {7, 0x5fu}, {7, 0x60u}, {7, 0x61u}, {7, 0x62u},
+ {7, 0x63u}, {7, 0x64u}, {7, 0x65u}, {7, 0x66u},
+ {7, 0x67u}, {7, 0x68u}, {7, 0x69u}, {7, 0x6au},
+ {7, 0x6bu}, {7, 0x6cu}, {7, 0x6du}, {7, 0x6eu},
+ {7, 0x6fu}, {7, 0x70u}, {7, 0x71u}, {7, 0x72u},
+ {8, 0xfcu}, {7, 0x73u}, {8, 0xfdu}, {13, 0x1ffbu},
+ {19, 0x7fff0u}, {13, 0x1ffcu}, {14, 0x3ffcu}, {6, 0x22u},
+ {15, 0x7ffdu}, {5, 0x3u}, {6, 0x23u}, {5, 0x4u},
+ {6, 0x24u}, {5, 0x5u}, {6, 0x25u}, {6, 0x26u},
+ {6, 0x27u}, {5, 0x6u}, {7, 0x74u}, {7, 0x75u},
+ {6, 0x28u}, {6, 0x29u}, {6, 0x2au}, {5, 0x7u},
+ {6, 0x2bu}, {7, 0x76u}, {6, 0x2cu}, {5, 0x8u},
+ {5, 0x9u}, {6, 0x2du}, {7, 0x77u}, {7, 0x78u},
+ {7, 0x79u}, {7, 0x7au}, {7, 0x7bu}, {15, 0x7ffeu},
+ {11, 0x7fcu}, {14, 0x3ffdu}, {13, 0x1ffdu}, {28, 0xffffffcu},
+ {20, 0xfffe6u}, {22, 0x3fffd2u}, {20, 0xfffe7u}, {20, 0xfffe8u},
+ {22, 0x3fffd3u}, {22, 0x3fffd4u}, {22, 0x3fffd5u}, {23, 0x7fffd9u},
+ {22, 0x3fffd6u}, {23, 0x7fffdau}, {23, 0x7fffdbu}, {23, 0x7fffdcu},
+ {23, 0x7fffddu}, {23, 0x7fffdeu}, {24, 0xffffebu}, {23, 0x7fffdfu},
+ {24, 0xffffecu}, {24, 0xffffedu}, {22, 0x3fffd7u}, {23, 0x7fffe0u},
+ {24, 0xffffeeu}, {23, 0x7fffe1u}, {23, 0x7fffe2u}, {23, 0x7fffe3u},
+ {23, 0x7fffe4u}, {21, 0x1fffdcu}, {22, 0x3fffd8u}, {23, 0x7fffe5u},
+ {22, 0x3fffd9u}, {23, 0x7fffe6u}, {23, 0x7fffe7u}, {24, 0xffffefu},
+ {22, 0x3fffdau}, {21, 0x1fffddu}, {20, 0xfffe9u}, {22, 0x3fffdbu},
+ {22, 0x3fffdcu}, {23, 0x7fffe8u}, {23, 0x7fffe9u}, {21, 0x1fffdeu},
+ {23, 0x7fffeau}, {22, 0x3fffddu}, {22, 0x3fffdeu}, {24, 0xfffff0u},
+ {21, 0x1fffdfu}, {22, 0x3fffdfu}, {23, 0x7fffebu}, {23, 0x7fffecu},
+ {21, 0x1fffe0u}, {21, 0x1fffe1u}, {22, 0x3fffe0u}, {21, 0x1fffe2u},
+ {23, 0x7fffedu}, {22, 0x3fffe1u}, {23, 0x7fffeeu}, {23, 0x7fffefu},
+ {20, 0xfffeau}, {22, 0x3fffe2u}, {22, 0x3fffe3u}, {22, 0x3fffe4u},
+ {23, 0x7ffff0u}, {22, 0x3fffe5u}, {22, 0x3fffe6u}, {23, 0x7ffff1u},
+ {26, 0x3ffffe0u}, {26, 0x3ffffe1u}, {20, 0xfffebu}, {19, 0x7fff1u},
+ {22, 0x3fffe7u}, {23, 0x7ffff2u}, {22, 0x3fffe8u}, {25, 0x1ffffecu},
+ {26, 0x3ffffe2u}, {26, 0x3ffffe3u}, {26, 0x3ffffe4u}, {27, 0x7ffffdeu},
+ {27, 0x7ffffdfu}, {26, 0x3ffffe5u}, {24, 0xfffff1u}, {25, 0x1ffffedu},
+ {19, 0x7fff2u}, {21, 0x1fffe3u}, {26, 0x3ffffe6u}, {27, 0x7ffffe0u},
+ {27, 0x7ffffe1u}, {26, 0x3ffffe7u}, {27, 0x7ffffe2u}, {24, 0xfffff2u},
+ {21, 0x1fffe4u}, {21, 0x1fffe5u}, {26, 0x3ffffe8u}, {26, 0x3ffffe9u},
+ {28, 0xffffffdu}, {27, 0x7ffffe3u}, {27, 0x7ffffe4u}, {27, 0x7ffffe5u},
+ {20, 0xfffecu}, {24, 0xfffff3u}, {20, 0xfffedu}, {21, 0x1fffe6u},
+ {22, 0x3fffe9u}, {21, 0x1fffe7u}, {21, 0x1fffe8u}, {23, 0x7ffff3u},
+ {22, 0x3fffeau}, {22, 0x3fffebu}, {25, 0x1ffffeeu}, {25, 0x1ffffefu},
+ {24, 0xfffff4u}, {24, 0xfffff5u}, {26, 0x3ffffeau}, {23, 0x7ffff4u},
+ {26, 0x3ffffebu}, {27, 0x7ffffe6u}, {26, 0x3ffffecu}, {26, 0x3ffffedu},
+ {27, 0x7ffffe7u}, {27, 0x7ffffe8u}, {27, 0x7ffffe9u}, {27, 0x7ffffeau},
+ {27, 0x7ffffebu}, {28, 0xffffffeu}, {27, 0x7ffffecu}, {27, 0x7ffffedu},
+ {27, 0x7ffffeeu}, {27, 0x7ffffefu}, {27, 0x7fffff0u}, {26, 0x3ffffeeu},
+ {30, 0x3fffffffu}};
+
+const nghttp2_huff_decode huff_decode_table[][16] = {
+ /* 0 */
+ {
+ {4, 0x00, 0},
+ {5, 0x00, 0},
+ {7, 0x00, 0},
+ {8, 0x00, 0},
+ {11, 0x00, 0},
+ {12, 0x00, 0},
+ {16, 0x00, 0},
+ {19, 0x00, 0},
+ {25, 0x00, 0},
+ {28, 0x00, 0},
+ {32, 0x00, 0},
+ {35, 0x00, 0},
+ {42, 0x00, 0},
+ {49, 0x00, 0},
+ {57, 0x00, 0},
+ {64, 0x01, 0},
+ },
+ /* 1 */
+ {
+ {0, 0x03, 48},
+ {0, 0x03, 49},
+ {0, 0x03, 50},
+ {0, 0x03, 97},
+ {0, 0x03, 99},
+ {0, 0x03, 101},
+ {0, 0x03, 105},
+ {0, 0x03, 111},
+ {0, 0x03, 115},
+ {0, 0x03, 116},
+ {13, 0x00, 0},
+ {14, 0x00, 0},
+ {17, 0x00, 0},
+ {18, 0x00, 0},
+ {20, 0x00, 0},
+ {21, 0x00, 0},
+ },
+ /* 2 */
+ {
+ {1, 0x02, 48},
+ {22, 0x03, 48},
+ {1, 0x02, 49},
+ {22, 0x03, 49},
+ {1, 0x02, 50},
+ {22, 0x03, 50},
+ {1, 0x02, 97},
+ {22, 0x03, 97},
+ {1, 0x02, 99},
+ {22, 0x03, 99},
+ {1, 0x02, 101},
+ {22, 0x03, 101},
+ {1, 0x02, 105},
+ {22, 0x03, 105},
+ {1, 0x02, 111},
+ {22, 0x03, 111},
+ },
+ /* 3 */
+ {
+ {2, 0x02, 48},
+ {9, 0x02, 48},
+ {23, 0x02, 48},
+ {40, 0x03, 48},
+ {2, 0x02, 49},
+ {9, 0x02, 49},
+ {23, 0x02, 49},
+ {40, 0x03, 49},
+ {2, 0x02, 50},
+ {9, 0x02, 50},
+ {23, 0x02, 50},
+ {40, 0x03, 50},
+ {2, 0x02, 97},
+ {9, 0x02, 97},
+ {23, 0x02, 97},
+ {40, 0x03, 97},
+ },
+ /* 4 */
+ {
+ {3, 0x02, 48},
+ {6, 0x02, 48},
+ {10, 0x02, 48},
+ {15, 0x02, 48},
+ {24, 0x02, 48},
+ {31, 0x02, 48},
+ {41, 0x02, 48},
+ {56, 0x03, 48},
+ {3, 0x02, 49},
+ {6, 0x02, 49},
+ {10, 0x02, 49},
+ {15, 0x02, 49},
+ {24, 0x02, 49},
+ {31, 0x02, 49},
+ {41, 0x02, 49},
+ {56, 0x03, 49},
+ },
+ /* 5 */
+ {
+ {3, 0x02, 50},
+ {6, 0x02, 50},
+ {10, 0x02, 50},
+ {15, 0x02, 50},
+ {24, 0x02, 50},
+ {31, 0x02, 50},
+ {41, 0x02, 50},
+ {56, 0x03, 50},
+ {3, 0x02, 97},
+ {6, 0x02, 97},
+ {10, 0x02, 97},
+ {15, 0x02, 97},
+ {24, 0x02, 97},
+ {31, 0x02, 97},
+ {41, 0x02, 97},
+ {56, 0x03, 97},
+ },
+ /* 6 */
+ {
+ {2, 0x02, 99},
+ {9, 0x02, 99},
+ {23, 0x02, 99},
+ {40, 0x03, 99},
+ {2, 0x02, 101},
+ {9, 0x02, 101},
+ {23, 0x02, 101},
+ {40, 0x03, 101},
+ {2, 0x02, 105},
+ {9, 0x02, 105},
+ {23, 0x02, 105},
+ {40, 0x03, 105},
+ {2, 0x02, 111},
+ {9, 0x02, 111},
+ {23, 0x02, 111},
+ {40, 0x03, 111},
+ },
+ /* 7 */
+ {
+ {3, 0x02, 99},
+ {6, 0x02, 99},
+ {10, 0x02, 99},
+ {15, 0x02, 99},
+ {24, 0x02, 99},
+ {31, 0x02, 99},
+ {41, 0x02, 99},
+ {56, 0x03, 99},
+ {3, 0x02, 101},
+ {6, 0x02, 101},
+ {10, 0x02, 101},
+ {15, 0x02, 101},
+ {24, 0x02, 101},
+ {31, 0x02, 101},
+ {41, 0x02, 101},
+ {56, 0x03, 101},
+ },
+ /* 8 */
+ {
+ {3, 0x02, 105},
+ {6, 0x02, 105},
+ {10, 0x02, 105},
+ {15, 0x02, 105},
+ {24, 0x02, 105},
+ {31, 0x02, 105},
+ {41, 0x02, 105},
+ {56, 0x03, 105},
+ {3, 0x02, 111},
+ {6, 0x02, 111},
+ {10, 0x02, 111},
+ {15, 0x02, 111},
+ {24, 0x02, 111},
+ {31, 0x02, 111},
+ {41, 0x02, 111},
+ {56, 0x03, 111},
+ },
+ /* 9 */
+ {
+ {1, 0x02, 115},
+ {22, 0x03, 115},
+ {1, 0x02, 116},
+ {22, 0x03, 116},
+ {0, 0x03, 32},
+ {0, 0x03, 37},
+ {0, 0x03, 45},
+ {0, 0x03, 46},
+ {0, 0x03, 47},
+ {0, 0x03, 51},
+ {0, 0x03, 52},
+ {0, 0x03, 53},
+ {0, 0x03, 54},
+ {0, 0x03, 55},
+ {0, 0x03, 56},
+ {0, 0x03, 57},
+ },
+ /* 10 */
+ {
+ {2, 0x02, 115},
+ {9, 0x02, 115},
+ {23, 0x02, 115},
+ {40, 0x03, 115},
+ {2, 0x02, 116},
+ {9, 0x02, 116},
+ {23, 0x02, 116},
+ {40, 0x03, 116},
+ {1, 0x02, 32},
+ {22, 0x03, 32},
+ {1, 0x02, 37},
+ {22, 0x03, 37},
+ {1, 0x02, 45},
+ {22, 0x03, 45},
+ {1, 0x02, 46},
+ {22, 0x03, 46},
+ },
+ /* 11 */
+ {
+ {3, 0x02, 115},
+ {6, 0x02, 115},
+ {10, 0x02, 115},
+ {15, 0x02, 115},
+ {24, 0x02, 115},
+ {31, 0x02, 115},
+ {41, 0x02, 115},
+ {56, 0x03, 115},
+ {3, 0x02, 116},
+ {6, 0x02, 116},
+ {10, 0x02, 116},
+ {15, 0x02, 116},
+ {24, 0x02, 116},
+ {31, 0x02, 116},
+ {41, 0x02, 116},
+ {56, 0x03, 116},
+ },
+ /* 12 */
+ {
+ {2, 0x02, 32},
+ {9, 0x02, 32},
+ {23, 0x02, 32},
+ {40, 0x03, 32},
+ {2, 0x02, 37},
+ {9, 0x02, 37},
+ {23, 0x02, 37},
+ {40, 0x03, 37},
+ {2, 0x02, 45},
+ {9, 0x02, 45},
+ {23, 0x02, 45},
+ {40, 0x03, 45},
+ {2, 0x02, 46},
+ {9, 0x02, 46},
+ {23, 0x02, 46},
+ {40, 0x03, 46},
+ },
+ /* 13 */
+ {
+ {3, 0x02, 32},
+ {6, 0x02, 32},
+ {10, 0x02, 32},
+ {15, 0x02, 32},
+ {24, 0x02, 32},
+ {31, 0x02, 32},
+ {41, 0x02, 32},
+ {56, 0x03, 32},
+ {3, 0x02, 37},
+ {6, 0x02, 37},
+ {10, 0x02, 37},
+ {15, 0x02, 37},
+ {24, 0x02, 37},
+ {31, 0x02, 37},
+ {41, 0x02, 37},
+ {56, 0x03, 37},
+ },
+ /* 14 */
+ {
+ {3, 0x02, 45},
+ {6, 0x02, 45},
+ {10, 0x02, 45},
+ {15, 0x02, 45},
+ {24, 0x02, 45},
+ {31, 0x02, 45},
+ {41, 0x02, 45},
+ {56, 0x03, 45},
+ {3, 0x02, 46},
+ {6, 0x02, 46},
+ {10, 0x02, 46},
+ {15, 0x02, 46},
+ {24, 0x02, 46},
+ {31, 0x02, 46},
+ {41, 0x02, 46},
+ {56, 0x03, 46},
+ },
+ /* 15 */
+ {
+ {1, 0x02, 47},
+ {22, 0x03, 47},
+ {1, 0x02, 51},
+ {22, 0x03, 51},
+ {1, 0x02, 52},
+ {22, 0x03, 52},
+ {1, 0x02, 53},
+ {22, 0x03, 53},
+ {1, 0x02, 54},
+ {22, 0x03, 54},
+ {1, 0x02, 55},
+ {22, 0x03, 55},
+ {1, 0x02, 56},
+ {22, 0x03, 56},
+ {1, 0x02, 57},
+ {22, 0x03, 57},
+ },
+ /* 16 */
+ {
+ {2, 0x02, 47},
+ {9, 0x02, 47},
+ {23, 0x02, 47},
+ {40, 0x03, 47},
+ {2, 0x02, 51},
+ {9, 0x02, 51},
+ {23, 0x02, 51},
+ {40, 0x03, 51},
+ {2, 0x02, 52},
+ {9, 0x02, 52},
+ {23, 0x02, 52},
+ {40, 0x03, 52},
+ {2, 0x02, 53},
+ {9, 0x02, 53},
+ {23, 0x02, 53},
+ {40, 0x03, 53},
+ },
+ /* 17 */
+ {
+ {3, 0x02, 47},
+ {6, 0x02, 47},
+ {10, 0x02, 47},
+ {15, 0x02, 47},
+ {24, 0x02, 47},
+ {31, 0x02, 47},
+ {41, 0x02, 47},
+ {56, 0x03, 47},
+ {3, 0x02, 51},
+ {6, 0x02, 51},
+ {10, 0x02, 51},
+ {15, 0x02, 51},
+ {24, 0x02, 51},
+ {31, 0x02, 51},
+ {41, 0x02, 51},
+ {56, 0x03, 51},
+ },
+ /* 18 */
+ {
+ {3, 0x02, 52},
+ {6, 0x02, 52},
+ {10, 0x02, 52},
+ {15, 0x02, 52},
+ {24, 0x02, 52},
+ {31, 0x02, 52},
+ {41, 0x02, 52},
+ {56, 0x03, 52},
+ {3, 0x02, 53},
+ {6, 0x02, 53},
+ {10, 0x02, 53},
+ {15, 0x02, 53},
+ {24, 0x02, 53},
+ {31, 0x02, 53},
+ {41, 0x02, 53},
+ {56, 0x03, 53},
+ },
+ /* 19 */
+ {
+ {2, 0x02, 54},
+ {9, 0x02, 54},
+ {23, 0x02, 54},
+ {40, 0x03, 54},
+ {2, 0x02, 55},
+ {9, 0x02, 55},
+ {23, 0x02, 55},
+ {40, 0x03, 55},
+ {2, 0x02, 56},
+ {9, 0x02, 56},
+ {23, 0x02, 56},
+ {40, 0x03, 56},
+ {2, 0x02, 57},
+ {9, 0x02, 57},
+ {23, 0x02, 57},
+ {40, 0x03, 57},
+ },
+ /* 20 */
+ {
+ {3, 0x02, 54},
+ {6, 0x02, 54},
+ {10, 0x02, 54},
+ {15, 0x02, 54},
+ {24, 0x02, 54},
+ {31, 0x02, 54},
+ {41, 0x02, 54},
+ {56, 0x03, 54},
+ {3, 0x02, 55},
+ {6, 0x02, 55},
+ {10, 0x02, 55},
+ {15, 0x02, 55},
+ {24, 0x02, 55},
+ {31, 0x02, 55},
+ {41, 0x02, 55},
+ {56, 0x03, 55},
+ },
+ /* 21 */
+ {
+ {3, 0x02, 56},
+ {6, 0x02, 56},
+ {10, 0x02, 56},
+ {15, 0x02, 56},
+ {24, 0x02, 56},
+ {31, 0x02, 56},
+ {41, 0x02, 56},
+ {56, 0x03, 56},
+ {3, 0x02, 57},
+ {6, 0x02, 57},
+ {10, 0x02, 57},
+ {15, 0x02, 57},
+ {24, 0x02, 57},
+ {31, 0x02, 57},
+ {41, 0x02, 57},
+ {56, 0x03, 57},
+ },
+ /* 22 */
+ {
+ {26, 0x00, 0},
+ {27, 0x00, 0},
+ {29, 0x00, 0},
+ {30, 0x00, 0},
+ {33, 0x00, 0},
+ {34, 0x00, 0},
+ {36, 0x00, 0},
+ {37, 0x00, 0},
+ {43, 0x00, 0},
+ {46, 0x00, 0},
+ {50, 0x00, 0},
+ {53, 0x00, 0},
+ {58, 0x00, 0},
+ {61, 0x00, 0},
+ {65, 0x00, 0},
+ {68, 0x01, 0},
+ },
+ /* 23 */
+ {
+ {0, 0x03, 61},
+ {0, 0x03, 65},
+ {0, 0x03, 95},
+ {0, 0x03, 98},
+ {0, 0x03, 100},
+ {0, 0x03, 102},
+ {0, 0x03, 103},
+ {0, 0x03, 104},
+ {0, 0x03, 108},
+ {0, 0x03, 109},
+ {0, 0x03, 110},
+ {0, 0x03, 112},
+ {0, 0x03, 114},
+ {0, 0x03, 117},
+ {38, 0x00, 0},
+ {39, 0x00, 0},
+ },
+ /* 24 */
+ {
+ {1, 0x02, 61},
+ {22, 0x03, 61},
+ {1, 0x02, 65},
+ {22, 0x03, 65},
+ {1, 0x02, 95},
+ {22, 0x03, 95},
+ {1, 0x02, 98},
+ {22, 0x03, 98},
+ {1, 0x02, 100},
+ {22, 0x03, 100},
+ {1, 0x02, 102},
+ {22, 0x03, 102},
+ {1, 0x02, 103},
+ {22, 0x03, 103},
+ {1, 0x02, 104},
+ {22, 0x03, 104},
+ },
+ /* 25 */
+ {
+ {2, 0x02, 61},
+ {9, 0x02, 61},
+ {23, 0x02, 61},
+ {40, 0x03, 61},
+ {2, 0x02, 65},
+ {9, 0x02, 65},
+ {23, 0x02, 65},
+ {40, 0x03, 65},
+ {2, 0x02, 95},
+ {9, 0x02, 95},
+ {23, 0x02, 95},
+ {40, 0x03, 95},
+ {2, 0x02, 98},
+ {9, 0x02, 98},
+ {23, 0x02, 98},
+ {40, 0x03, 98},
+ },
+ /* 26 */
+ {
+ {3, 0x02, 61},
+ {6, 0x02, 61},
+ {10, 0x02, 61},
+ {15, 0x02, 61},
+ {24, 0x02, 61},
+ {31, 0x02, 61},
+ {41, 0x02, 61},
+ {56, 0x03, 61},
+ {3, 0x02, 65},
+ {6, 0x02, 65},
+ {10, 0x02, 65},
+ {15, 0x02, 65},
+ {24, 0x02, 65},
+ {31, 0x02, 65},
+ {41, 0x02, 65},
+ {56, 0x03, 65},
+ },
+ /* 27 */
+ {
+ {3, 0x02, 95},
+ {6, 0x02, 95},
+ {10, 0x02, 95},
+ {15, 0x02, 95},
+ {24, 0x02, 95},
+ {31, 0x02, 95},
+ {41, 0x02, 95},
+ {56, 0x03, 95},
+ {3, 0x02, 98},
+ {6, 0x02, 98},
+ {10, 0x02, 98},
+ {15, 0x02, 98},
+ {24, 0x02, 98},
+ {31, 0x02, 98},
+ {41, 0x02, 98},
+ {56, 0x03, 98},
+ },
+ /* 28 */
+ {
+ {2, 0x02, 100},
+ {9, 0x02, 100},
+ {23, 0x02, 100},
+ {40, 0x03, 100},
+ {2, 0x02, 102},
+ {9, 0x02, 102},
+ {23, 0x02, 102},
+ {40, 0x03, 102},
+ {2, 0x02, 103},
+ {9, 0x02, 103},
+ {23, 0x02, 103},
+ {40, 0x03, 103},
+ {2, 0x02, 104},
+ {9, 0x02, 104},
+ {23, 0x02, 104},
+ {40, 0x03, 104},
+ },
+ /* 29 */
+ {
+ {3, 0x02, 100},
+ {6, 0x02, 100},
+ {10, 0x02, 100},
+ {15, 0x02, 100},
+ {24, 0x02, 100},
+ {31, 0x02, 100},
+ {41, 0x02, 100},
+ {56, 0x03, 100},
+ {3, 0x02, 102},
+ {6, 0x02, 102},
+ {10, 0x02, 102},
+ {15, 0x02, 102},
+ {24, 0x02, 102},
+ {31, 0x02, 102},
+ {41, 0x02, 102},
+ {56, 0x03, 102},
+ },
+ /* 30 */
+ {
+ {3, 0x02, 103},
+ {6, 0x02, 103},
+ {10, 0x02, 103},
+ {15, 0x02, 103},
+ {24, 0x02, 103},
+ {31, 0x02, 103},
+ {41, 0x02, 103},
+ {56, 0x03, 103},
+ {3, 0x02, 104},
+ {6, 0x02, 104},
+ {10, 0x02, 104},
+ {15, 0x02, 104},
+ {24, 0x02, 104},
+ {31, 0x02, 104},
+ {41, 0x02, 104},
+ {56, 0x03, 104},
+ },
+ /* 31 */
+ {
+ {1, 0x02, 108},
+ {22, 0x03, 108},
+ {1, 0x02, 109},
+ {22, 0x03, 109},
+ {1, 0x02, 110},
+ {22, 0x03, 110},
+ {1, 0x02, 112},
+ {22, 0x03, 112},
+ {1, 0x02, 114},
+ {22, 0x03, 114},
+ {1, 0x02, 117},
+ {22, 0x03, 117},
+ {0, 0x03, 58},
+ {0, 0x03, 66},
+ {0, 0x03, 67},
+ {0, 0x03, 68},
+ },
+ /* 32 */
+ {
+ {2, 0x02, 108},
+ {9, 0x02, 108},
+ {23, 0x02, 108},
+ {40, 0x03, 108},
+ {2, 0x02, 109},
+ {9, 0x02, 109},
+ {23, 0x02, 109},
+ {40, 0x03, 109},
+ {2, 0x02, 110},
+ {9, 0x02, 110},
+ {23, 0x02, 110},
+ {40, 0x03, 110},
+ {2, 0x02, 112},
+ {9, 0x02, 112},
+ {23, 0x02, 112},
+ {40, 0x03, 112},
+ },
+ /* 33 */
+ {
+ {3, 0x02, 108},
+ {6, 0x02, 108},
+ {10, 0x02, 108},
+ {15, 0x02, 108},
+ {24, 0x02, 108},
+ {31, 0x02, 108},
+ {41, 0x02, 108},
+ {56, 0x03, 108},
+ {3, 0x02, 109},
+ {6, 0x02, 109},
+ {10, 0x02, 109},
+ {15, 0x02, 109},
+ {24, 0x02, 109},
+ {31, 0x02, 109},
+ {41, 0x02, 109},
+ {56, 0x03, 109},
+ },
+ /* 34 */
+ {
+ {3, 0x02, 110},
+ {6, 0x02, 110},
+ {10, 0x02, 110},
+ {15, 0x02, 110},
+ {24, 0x02, 110},
+ {31, 0x02, 110},
+ {41, 0x02, 110},
+ {56, 0x03, 110},
+ {3, 0x02, 112},
+ {6, 0x02, 112},
+ {10, 0x02, 112},
+ {15, 0x02, 112},
+ {24, 0x02, 112},
+ {31, 0x02, 112},
+ {41, 0x02, 112},
+ {56, 0x03, 112},
+ },
+ /* 35 */
+ {
+ {2, 0x02, 114},
+ {9, 0x02, 114},
+ {23, 0x02, 114},
+ {40, 0x03, 114},
+ {2, 0x02, 117},
+ {9, 0x02, 117},
+ {23, 0x02, 117},
+ {40, 0x03, 117},
+ {1, 0x02, 58},
+ {22, 0x03, 58},
+ {1, 0x02, 66},
+ {22, 0x03, 66},
+ {1, 0x02, 67},
+ {22, 0x03, 67},
+ {1, 0x02, 68},
+ {22, 0x03, 68},
+ },
+ /* 36 */
+ {
+ {3, 0x02, 114},
+ {6, 0x02, 114},
+ {10, 0x02, 114},
+ {15, 0x02, 114},
+ {24, 0x02, 114},
+ {31, 0x02, 114},
+ {41, 0x02, 114},
+ {56, 0x03, 114},
+ {3, 0x02, 117},
+ {6, 0x02, 117},
+ {10, 0x02, 117},
+ {15, 0x02, 117},
+ {24, 0x02, 117},
+ {31, 0x02, 117},
+ {41, 0x02, 117},
+ {56, 0x03, 117},
+ },
+ /* 37 */
+ {
+ {2, 0x02, 58},
+ {9, 0x02, 58},
+ {23, 0x02, 58},
+ {40, 0x03, 58},
+ {2, 0x02, 66},
+ {9, 0x02, 66},
+ {23, 0x02, 66},
+ {40, 0x03, 66},
+ {2, 0x02, 67},
+ {9, 0x02, 67},
+ {23, 0x02, 67},
+ {40, 0x03, 67},
+ {2, 0x02, 68},
+ {9, 0x02, 68},
+ {23, 0x02, 68},
+ {40, 0x03, 68},
+ },
+ /* 38 */
+ {
+ {3, 0x02, 58},
+ {6, 0x02, 58},
+ {10, 0x02, 58},
+ {15, 0x02, 58},
+ {24, 0x02, 58},
+ {31, 0x02, 58},
+ {41, 0x02, 58},
+ {56, 0x03, 58},
+ {3, 0x02, 66},
+ {6, 0x02, 66},
+ {10, 0x02, 66},
+ {15, 0x02, 66},
+ {24, 0x02, 66},
+ {31, 0x02, 66},
+ {41, 0x02, 66},
+ {56, 0x03, 66},
+ },
+ /* 39 */
+ {
+ {3, 0x02, 67},
+ {6, 0x02, 67},
+ {10, 0x02, 67},
+ {15, 0x02, 67},
+ {24, 0x02, 67},
+ {31, 0x02, 67},
+ {41, 0x02, 67},
+ {56, 0x03, 67},
+ {3, 0x02, 68},
+ {6, 0x02, 68},
+ {10, 0x02, 68},
+ {15, 0x02, 68},
+ {24, 0x02, 68},
+ {31, 0x02, 68},
+ {41, 0x02, 68},
+ {56, 0x03, 68},
+ },
+ /* 40 */
+ {
+ {44, 0x00, 0},
+ {45, 0x00, 0},
+ {47, 0x00, 0},
+ {48, 0x00, 0},
+ {51, 0x00, 0},
+ {52, 0x00, 0},
+ {54, 0x00, 0},
+ {55, 0x00, 0},
+ {59, 0x00, 0},
+ {60, 0x00, 0},
+ {62, 0x00, 0},
+ {63, 0x00, 0},
+ {66, 0x00, 0},
+ {67, 0x00, 0},
+ {69, 0x00, 0},
+ {72, 0x01, 0},
+ },
+ /* 41 */
+ {
+ {0, 0x03, 69},
+ {0, 0x03, 70},
+ {0, 0x03, 71},
+ {0, 0x03, 72},
+ {0, 0x03, 73},
+ {0, 0x03, 74},
+ {0, 0x03, 75},
+ {0, 0x03, 76},
+ {0, 0x03, 77},
+ {0, 0x03, 78},
+ {0, 0x03, 79},
+ {0, 0x03, 80},
+ {0, 0x03, 81},
+ {0, 0x03, 82},
+ {0, 0x03, 83},
+ {0, 0x03, 84},
+ },
+ /* 42 */
+ {
+ {1, 0x02, 69},
+ {22, 0x03, 69},
+ {1, 0x02, 70},
+ {22, 0x03, 70},
+ {1, 0x02, 71},
+ {22, 0x03, 71},
+ {1, 0x02, 72},
+ {22, 0x03, 72},
+ {1, 0x02, 73},
+ {22, 0x03, 73},
+ {1, 0x02, 74},
+ {22, 0x03, 74},
+ {1, 0x02, 75},
+ {22, 0x03, 75},
+ {1, 0x02, 76},
+ {22, 0x03, 76},
+ },
+ /* 43 */
+ {
+ {2, 0x02, 69},
+ {9, 0x02, 69},
+ {23, 0x02, 69},
+ {40, 0x03, 69},
+ {2, 0x02, 70},
+ {9, 0x02, 70},
+ {23, 0x02, 70},
+ {40, 0x03, 70},
+ {2, 0x02, 71},
+ {9, 0x02, 71},
+ {23, 0x02, 71},
+ {40, 0x03, 71},
+ {2, 0x02, 72},
+ {9, 0x02, 72},
+ {23, 0x02, 72},
+ {40, 0x03, 72},
+ },
+ /* 44 */
+ {
+ {3, 0x02, 69},
+ {6, 0x02, 69},
+ {10, 0x02, 69},
+ {15, 0x02, 69},
+ {24, 0x02, 69},
+ {31, 0x02, 69},
+ {41, 0x02, 69},
+ {56, 0x03, 69},
+ {3, 0x02, 70},
+ {6, 0x02, 70},
+ {10, 0x02, 70},
+ {15, 0x02, 70},
+ {24, 0x02, 70},
+ {31, 0x02, 70},
+ {41, 0x02, 70},
+ {56, 0x03, 70},
+ },
+ /* 45 */
+ {
+ {3, 0x02, 71},
+ {6, 0x02, 71},
+ {10, 0x02, 71},
+ {15, 0x02, 71},
+ {24, 0x02, 71},
+ {31, 0x02, 71},
+ {41, 0x02, 71},
+ {56, 0x03, 71},
+ {3, 0x02, 72},
+ {6, 0x02, 72},
+ {10, 0x02, 72},
+ {15, 0x02, 72},
+ {24, 0x02, 72},
+ {31, 0x02, 72},
+ {41, 0x02, 72},
+ {56, 0x03, 72},
+ },
+ /* 46 */
+ {
+ {2, 0x02, 73},
+ {9, 0x02, 73},
+ {23, 0x02, 73},
+ {40, 0x03, 73},
+ {2, 0x02, 74},
+ {9, 0x02, 74},
+ {23, 0x02, 74},
+ {40, 0x03, 74},
+ {2, 0x02, 75},
+ {9, 0x02, 75},
+ {23, 0x02, 75},
+ {40, 0x03, 75},
+ {2, 0x02, 76},
+ {9, 0x02, 76},
+ {23, 0x02, 76},
+ {40, 0x03, 76},
+ },
+ /* 47 */
+ {
+ {3, 0x02, 73},
+ {6, 0x02, 73},
+ {10, 0x02, 73},
+ {15, 0x02, 73},
+ {24, 0x02, 73},
+ {31, 0x02, 73},
+ {41, 0x02, 73},
+ {56, 0x03, 73},
+ {3, 0x02, 74},
+ {6, 0x02, 74},
+ {10, 0x02, 74},
+ {15, 0x02, 74},
+ {24, 0x02, 74},
+ {31, 0x02, 74},
+ {41, 0x02, 74},
+ {56, 0x03, 74},
+ },
+ /* 48 */
+ {
+ {3, 0x02, 75},
+ {6, 0x02, 75},
+ {10, 0x02, 75},
+ {15, 0x02, 75},
+ {24, 0x02, 75},
+ {31, 0x02, 75},
+ {41, 0x02, 75},
+ {56, 0x03, 75},
+ {3, 0x02, 76},
+ {6, 0x02, 76},
+ {10, 0x02, 76},
+ {15, 0x02, 76},
+ {24, 0x02, 76},
+ {31, 0x02, 76},
+ {41, 0x02, 76},
+ {56, 0x03, 76},
+ },
+ /* 49 */
+ {
+ {1, 0x02, 77},
+ {22, 0x03, 77},
+ {1, 0x02, 78},
+ {22, 0x03, 78},
+ {1, 0x02, 79},
+ {22, 0x03, 79},
+ {1, 0x02, 80},
+ {22, 0x03, 80},
+ {1, 0x02, 81},
+ {22, 0x03, 81},
+ {1, 0x02, 82},
+ {22, 0x03, 82},
+ {1, 0x02, 83},
+ {22, 0x03, 83},
+ {1, 0x02, 84},
+ {22, 0x03, 84},
+ },
+ /* 50 */
+ {
+ {2, 0x02, 77},
+ {9, 0x02, 77},
+ {23, 0x02, 77},
+ {40, 0x03, 77},
+ {2, 0x02, 78},
+ {9, 0x02, 78},
+ {23, 0x02, 78},
+ {40, 0x03, 78},
+ {2, 0x02, 79},
+ {9, 0x02, 79},
+ {23, 0x02, 79},
+ {40, 0x03, 79},
+ {2, 0x02, 80},
+ {9, 0x02, 80},
+ {23, 0x02, 80},
+ {40, 0x03, 80},
+ },
+ /* 51 */
+ {
+ {3, 0x02, 77},
+ {6, 0x02, 77},
+ {10, 0x02, 77},
+ {15, 0x02, 77},
+ {24, 0x02, 77},
+ {31, 0x02, 77},
+ {41, 0x02, 77},
+ {56, 0x03, 77},
+ {3, 0x02, 78},
+ {6, 0x02, 78},
+ {10, 0x02, 78},
+ {15, 0x02, 78},
+ {24, 0x02, 78},
+ {31, 0x02, 78},
+ {41, 0x02, 78},
+ {56, 0x03, 78},
+ },
+ /* 52 */
+ {
+ {3, 0x02, 79},
+ {6, 0x02, 79},
+ {10, 0x02, 79},
+ {15, 0x02, 79},
+ {24, 0x02, 79},
+ {31, 0x02, 79},
+ {41, 0x02, 79},
+ {56, 0x03, 79},
+ {3, 0x02, 80},
+ {6, 0x02, 80},
+ {10, 0x02, 80},
+ {15, 0x02, 80},
+ {24, 0x02, 80},
+ {31, 0x02, 80},
+ {41, 0x02, 80},
+ {56, 0x03, 80},
+ },
+ /* 53 */
+ {
+ {2, 0x02, 81},
+ {9, 0x02, 81},
+ {23, 0x02, 81},
+ {40, 0x03, 81},
+ {2, 0x02, 82},
+ {9, 0x02, 82},
+ {23, 0x02, 82},
+ {40, 0x03, 82},
+ {2, 0x02, 83},
+ {9, 0x02, 83},
+ {23, 0x02, 83},
+ {40, 0x03, 83},
+ {2, 0x02, 84},
+ {9, 0x02, 84},
+ {23, 0x02, 84},
+ {40, 0x03, 84},
+ },
+ /* 54 */
+ {
+ {3, 0x02, 81},
+ {6, 0x02, 81},
+ {10, 0x02, 81},
+ {15, 0x02, 81},
+ {24, 0x02, 81},
+ {31, 0x02, 81},
+ {41, 0x02, 81},
+ {56, 0x03, 81},
+ {3, 0x02, 82},
+ {6, 0x02, 82},
+ {10, 0x02, 82},
+ {15, 0x02, 82},
+ {24, 0x02, 82},
+ {31, 0x02, 82},
+ {41, 0x02, 82},
+ {56, 0x03, 82},
+ },
+ /* 55 */
+ {
+ {3, 0x02, 83},
+ {6, 0x02, 83},
+ {10, 0x02, 83},
+ {15, 0x02, 83},
+ {24, 0x02, 83},
+ {31, 0x02, 83},
+ {41, 0x02, 83},
+ {56, 0x03, 83},
+ {3, 0x02, 84},
+ {6, 0x02, 84},
+ {10, 0x02, 84},
+ {15, 0x02, 84},
+ {24, 0x02, 84},
+ {31, 0x02, 84},
+ {41, 0x02, 84},
+ {56, 0x03, 84},
+ },
+ /* 56 */
+ {
+ {0, 0x03, 85},
+ {0, 0x03, 86},
+ {0, 0x03, 87},
+ {0, 0x03, 89},
+ {0, 0x03, 106},
+ {0, 0x03, 107},
+ {0, 0x03, 113},
+ {0, 0x03, 118},
+ {0, 0x03, 119},
+ {0, 0x03, 120},
+ {0, 0x03, 121},
+ {0, 0x03, 122},
+ {70, 0x00, 0},
+ {71, 0x00, 0},
+ {73, 0x00, 0},
+ {74, 0x01, 0},
+ },
+ /* 57 */
+ {
+ {1, 0x02, 85},
+ {22, 0x03, 85},
+ {1, 0x02, 86},
+ {22, 0x03, 86},
+ {1, 0x02, 87},
+ {22, 0x03, 87},
+ {1, 0x02, 89},
+ {22, 0x03, 89},
+ {1, 0x02, 106},
+ {22, 0x03, 106},
+ {1, 0x02, 107},
+ {22, 0x03, 107},
+ {1, 0x02, 113},
+ {22, 0x03, 113},
+ {1, 0x02, 118},
+ {22, 0x03, 118},
+ },
+ /* 58 */
+ {
+ {2, 0x02, 85},
+ {9, 0x02, 85},
+ {23, 0x02, 85},
+ {40, 0x03, 85},
+ {2, 0x02, 86},
+ {9, 0x02, 86},
+ {23, 0x02, 86},
+ {40, 0x03, 86},
+ {2, 0x02, 87},
+ {9, 0x02, 87},
+ {23, 0x02, 87},
+ {40, 0x03, 87},
+ {2, 0x02, 89},
+ {9, 0x02, 89},
+ {23, 0x02, 89},
+ {40, 0x03, 89},
+ },
+ /* 59 */
+ {
+ {3, 0x02, 85},
+ {6, 0x02, 85},
+ {10, 0x02, 85},
+ {15, 0x02, 85},
+ {24, 0x02, 85},
+ {31, 0x02, 85},
+ {41, 0x02, 85},
+ {56, 0x03, 85},
+ {3, 0x02, 86},
+ {6, 0x02, 86},
+ {10, 0x02, 86},
+ {15, 0x02, 86},
+ {24, 0x02, 86},
+ {31, 0x02, 86},
+ {41, 0x02, 86},
+ {56, 0x03, 86},
+ },
+ /* 60 */
+ {
+ {3, 0x02, 87},
+ {6, 0x02, 87},
+ {10, 0x02, 87},
+ {15, 0x02, 87},
+ {24, 0x02, 87},
+ {31, 0x02, 87},
+ {41, 0x02, 87},
+ {56, 0x03, 87},
+ {3, 0x02, 89},
+ {6, 0x02, 89},
+ {10, 0x02, 89},
+ {15, 0x02, 89},
+ {24, 0x02, 89},
+ {31, 0x02, 89},
+ {41, 0x02, 89},
+ {56, 0x03, 89},
+ },
+ /* 61 */
+ {
+ {2, 0x02, 106},
+ {9, 0x02, 106},
+ {23, 0x02, 106},
+ {40, 0x03, 106},
+ {2, 0x02, 107},
+ {9, 0x02, 107},
+ {23, 0x02, 107},
+ {40, 0x03, 107},
+ {2, 0x02, 113},
+ {9, 0x02, 113},
+ {23, 0x02, 113},
+ {40, 0x03, 113},
+ {2, 0x02, 118},
+ {9, 0x02, 118},
+ {23, 0x02, 118},
+ {40, 0x03, 118},
+ },
+ /* 62 */
+ {
+ {3, 0x02, 106},
+ {6, 0x02, 106},
+ {10, 0x02, 106},
+ {15, 0x02, 106},
+ {24, 0x02, 106},
+ {31, 0x02, 106},
+ {41, 0x02, 106},
+ {56, 0x03, 106},
+ {3, 0x02, 107},
+ {6, 0x02, 107},
+ {10, 0x02, 107},
+ {15, 0x02, 107},
+ {24, 0x02, 107},
+ {31, 0x02, 107},
+ {41, 0x02, 107},
+ {56, 0x03, 107},
+ },
+ /* 63 */
+ {
+ {3, 0x02, 113},
+ {6, 0x02, 113},
+ {10, 0x02, 113},
+ {15, 0x02, 113},
+ {24, 0x02, 113},
+ {31, 0x02, 113},
+ {41, 0x02, 113},
+ {56, 0x03, 113},
+ {3, 0x02, 118},
+ {6, 0x02, 118},
+ {10, 0x02, 118},
+ {15, 0x02, 118},
+ {24, 0x02, 118},
+ {31, 0x02, 118},
+ {41, 0x02, 118},
+ {56, 0x03, 118},
+ },
+ /* 64 */
+ {
+ {1, 0x02, 119},
+ {22, 0x03, 119},
+ {1, 0x02, 120},
+ {22, 0x03, 120},
+ {1, 0x02, 121},
+ {22, 0x03, 121},
+ {1, 0x02, 122},
+ {22, 0x03, 122},
+ {0, 0x03, 38},
+ {0, 0x03, 42},
+ {0, 0x03, 44},
+ {0, 0x03, 59},
+ {0, 0x03, 88},
+ {0, 0x03, 90},
+ {75, 0x00, 0},
+ {78, 0x00, 0},
+ },
+ /* 65 */
+ {
+ {2, 0x02, 119},
+ {9, 0x02, 119},
+ {23, 0x02, 119},
+ {40, 0x03, 119},
+ {2, 0x02, 120},
+ {9, 0x02, 120},
+ {23, 0x02, 120},
+ {40, 0x03, 120},
+ {2, 0x02, 121},
+ {9, 0x02, 121},
+ {23, 0x02, 121},
+ {40, 0x03, 121},
+ {2, 0x02, 122},
+ {9, 0x02, 122},
+ {23, 0x02, 122},
+ {40, 0x03, 122},
+ },
+ /* 66 */
+ {
+ {3, 0x02, 119},
+ {6, 0x02, 119},
+ {10, 0x02, 119},
+ {15, 0x02, 119},
+ {24, 0x02, 119},
+ {31, 0x02, 119},
+ {41, 0x02, 119},
+ {56, 0x03, 119},
+ {3, 0x02, 120},
+ {6, 0x02, 120},
+ {10, 0x02, 120},
+ {15, 0x02, 120},
+ {24, 0x02, 120},
+ {31, 0x02, 120},
+ {41, 0x02, 120},
+ {56, 0x03, 120},
+ },
+ /* 67 */
+ {
+ {3, 0x02, 121},
+ {6, 0x02, 121},
+ {10, 0x02, 121},
+ {15, 0x02, 121},
+ {24, 0x02, 121},
+ {31, 0x02, 121},
+ {41, 0x02, 121},
+ {56, 0x03, 121},
+ {3, 0x02, 122},
+ {6, 0x02, 122},
+ {10, 0x02, 122},
+ {15, 0x02, 122},
+ {24, 0x02, 122},
+ {31, 0x02, 122},
+ {41, 0x02, 122},
+ {56, 0x03, 122},
+ },
+ /* 68 */
+ {
+ {1, 0x02, 38},
+ {22, 0x03, 38},
+ {1, 0x02, 42},
+ {22, 0x03, 42},
+ {1, 0x02, 44},
+ {22, 0x03, 44},
+ {1, 0x02, 59},
+ {22, 0x03, 59},
+ {1, 0x02, 88},
+ {22, 0x03, 88},
+ {1, 0x02, 90},
+ {22, 0x03, 90},
+ {76, 0x00, 0},
+ {77, 0x00, 0},
+ {79, 0x00, 0},
+ {81, 0x00, 0},
+ },
+ /* 69 */
+ {
+ {2, 0x02, 38},
+ {9, 0x02, 38},
+ {23, 0x02, 38},
+ {40, 0x03, 38},
+ {2, 0x02, 42},
+ {9, 0x02, 42},
+ {23, 0x02, 42},
+ {40, 0x03, 42},
+ {2, 0x02, 44},
+ {9, 0x02, 44},
+ {23, 0x02, 44},
+ {40, 0x03, 44},
+ {2, 0x02, 59},
+ {9, 0x02, 59},
+ {23, 0x02, 59},
+ {40, 0x03, 59},
+ },
+ /* 70 */
+ {
+ {3, 0x02, 38},
+ {6, 0x02, 38},
+ {10, 0x02, 38},
+ {15, 0x02, 38},
+ {24, 0x02, 38},
+ {31, 0x02, 38},
+ {41, 0x02, 38},
+ {56, 0x03, 38},
+ {3, 0x02, 42},
+ {6, 0x02, 42},
+ {10, 0x02, 42},
+ {15, 0x02, 42},
+ {24, 0x02, 42},
+ {31, 0x02, 42},
+ {41, 0x02, 42},
+ {56, 0x03, 42},
+ },
+ /* 71 */
+ {
+ {3, 0x02, 44},
+ {6, 0x02, 44},
+ {10, 0x02, 44},
+ {15, 0x02, 44},
+ {24, 0x02, 44},
+ {31, 0x02, 44},
+ {41, 0x02, 44},
+ {56, 0x03, 44},
+ {3, 0x02, 59},
+ {6, 0x02, 59},
+ {10, 0x02, 59},
+ {15, 0x02, 59},
+ {24, 0x02, 59},
+ {31, 0x02, 59},
+ {41, 0x02, 59},
+ {56, 0x03, 59},
+ },
+ /* 72 */
+ {
+ {2, 0x02, 88},
+ {9, 0x02, 88},
+ {23, 0x02, 88},
+ {40, 0x03, 88},
+ {2, 0x02, 90},
+ {9, 0x02, 90},
+ {23, 0x02, 90},
+ {40, 0x03, 90},
+ {0, 0x03, 33},
+ {0, 0x03, 34},
+ {0, 0x03, 40},
+ {0, 0x03, 41},
+ {0, 0x03, 63},
+ {80, 0x00, 0},
+ {82, 0x00, 0},
+ {84, 0x00, 0},
+ },
+ /* 73 */
+ {
+ {3, 0x02, 88},
+ {6, 0x02, 88},
+ {10, 0x02, 88},
+ {15, 0x02, 88},
+ {24, 0x02, 88},
+ {31, 0x02, 88},
+ {41, 0x02, 88},
+ {56, 0x03, 88},
+ {3, 0x02, 90},
+ {6, 0x02, 90},
+ {10, 0x02, 90},
+ {15, 0x02, 90},
+ {24, 0x02, 90},
+ {31, 0x02, 90},
+ {41, 0x02, 90},
+ {56, 0x03, 90},
+ },
+ /* 74 */
+ {
+ {1, 0x02, 33},
+ {22, 0x03, 33},
+ {1, 0x02, 34},
+ {22, 0x03, 34},
+ {1, 0x02, 40},
+ {22, 0x03, 40},
+ {1, 0x02, 41},
+ {22, 0x03, 41},
+ {1, 0x02, 63},
+ {22, 0x03, 63},
+ {0, 0x03, 39},
+ {0, 0x03, 43},
+ {0, 0x03, 124},
+ {83, 0x00, 0},
+ {85, 0x00, 0},
+ {88, 0x00, 0},
+ },
+ /* 75 */
+ {
+ {2, 0x02, 33},
+ {9, 0x02, 33},
+ {23, 0x02, 33},
+ {40, 0x03, 33},
+ {2, 0x02, 34},
+ {9, 0x02, 34},
+ {23, 0x02, 34},
+ {40, 0x03, 34},
+ {2, 0x02, 40},
+ {9, 0x02, 40},
+ {23, 0x02, 40},
+ {40, 0x03, 40},
+ {2, 0x02, 41},
+ {9, 0x02, 41},
+ {23, 0x02, 41},
+ {40, 0x03, 41},
+ },
+ /* 76 */
+ {
+ {3, 0x02, 33},
+ {6, 0x02, 33},
+ {10, 0x02, 33},
+ {15, 0x02, 33},
+ {24, 0x02, 33},
+ {31, 0x02, 33},
+ {41, 0x02, 33},
+ {56, 0x03, 33},
+ {3, 0x02, 34},
+ {6, 0x02, 34},
+ {10, 0x02, 34},
+ {15, 0x02, 34},
+ {24, 0x02, 34},
+ {31, 0x02, 34},
+ {41, 0x02, 34},
+ {56, 0x03, 34},
+ },
+ /* 77 */
+ {
+ {3, 0x02, 40},
+ {6, 0x02, 40},
+ {10, 0x02, 40},
+ {15, 0x02, 40},
+ {24, 0x02, 40},
+ {31, 0x02, 40},
+ {41, 0x02, 40},
+ {56, 0x03, 40},
+ {3, 0x02, 41},
+ {6, 0x02, 41},
+ {10, 0x02, 41},
+ {15, 0x02, 41},
+ {24, 0x02, 41},
+ {31, 0x02, 41},
+ {41, 0x02, 41},
+ {56, 0x03, 41},
+ },
+ /* 78 */
+ {
+ {2, 0x02, 63},
+ {9, 0x02, 63},
+ {23, 0x02, 63},
+ {40, 0x03, 63},
+ {1, 0x02, 39},
+ {22, 0x03, 39},
+ {1, 0x02, 43},
+ {22, 0x03, 43},
+ {1, 0x02, 124},
+ {22, 0x03, 124},
+ {0, 0x03, 35},
+ {0, 0x03, 62},
+ {86, 0x00, 0},
+ {87, 0x00, 0},
+ {89, 0x00, 0},
+ {90, 0x00, 0},
+ },
+ /* 79 */
+ {
+ {3, 0x02, 63},
+ {6, 0x02, 63},
+ {10, 0x02, 63},
+ {15, 0x02, 63},
+ {24, 0x02, 63},
+ {31, 0x02, 63},
+ {41, 0x02, 63},
+ {56, 0x03, 63},
+ {2, 0x02, 39},
+ {9, 0x02, 39},
+ {23, 0x02, 39},
+ {40, 0x03, 39},
+ {2, 0x02, 43},
+ {9, 0x02, 43},
+ {23, 0x02, 43},
+ {40, 0x03, 43},
+ },
+ /* 80 */
+ {
+ {3, 0x02, 39},
+ {6, 0x02, 39},
+ {10, 0x02, 39},
+ {15, 0x02, 39},
+ {24, 0x02, 39},
+ {31, 0x02, 39},
+ {41, 0x02, 39},
+ {56, 0x03, 39},
+ {3, 0x02, 43},
+ {6, 0x02, 43},
+ {10, 0x02, 43},
+ {15, 0x02, 43},
+ {24, 0x02, 43},
+ {31, 0x02, 43},
+ {41, 0x02, 43},
+ {56, 0x03, 43},
+ },
+ /* 81 */
+ {
+ {2, 0x02, 124},
+ {9, 0x02, 124},
+ {23, 0x02, 124},
+ {40, 0x03, 124},
+ {1, 0x02, 35},
+ {22, 0x03, 35},
+ {1, 0x02, 62},
+ {22, 0x03, 62},
+ {0, 0x03, 0},
+ {0, 0x03, 36},
+ {0, 0x03, 64},
+ {0, 0x03, 91},
+ {0, 0x03, 93},
+ {0, 0x03, 126},
+ {91, 0x00, 0},
+ {92, 0x00, 0},
+ },
+ /* 82 */
+ {
+ {3, 0x02, 124},
+ {6, 0x02, 124},
+ {10, 0x02, 124},
+ {15, 0x02, 124},
+ {24, 0x02, 124},
+ {31, 0x02, 124},
+ {41, 0x02, 124},
+ {56, 0x03, 124},
+ {2, 0x02, 35},
+ {9, 0x02, 35},
+ {23, 0x02, 35},
+ {40, 0x03, 35},
+ {2, 0x02, 62},
+ {9, 0x02, 62},
+ {23, 0x02, 62},
+ {40, 0x03, 62},
+ },
+ /* 83 */
+ {
+ {3, 0x02, 35},
+ {6, 0x02, 35},
+ {10, 0x02, 35},
+ {15, 0x02, 35},
+ {24, 0x02, 35},
+ {31, 0x02, 35},
+ {41, 0x02, 35},
+ {56, 0x03, 35},
+ {3, 0x02, 62},
+ {6, 0x02, 62},
+ {10, 0x02, 62},
+ {15, 0x02, 62},
+ {24, 0x02, 62},
+ {31, 0x02, 62},
+ {41, 0x02, 62},
+ {56, 0x03, 62},
+ },
+ /* 84 */
+ {
+ {1, 0x02, 0},
+ {22, 0x03, 0},
+ {1, 0x02, 36},
+ {22, 0x03, 36},
+ {1, 0x02, 64},
+ {22, 0x03, 64},
+ {1, 0x02, 91},
+ {22, 0x03, 91},
+ {1, 0x02, 93},
+ {22, 0x03, 93},
+ {1, 0x02, 126},
+ {22, 0x03, 126},
+ {0, 0x03, 94},
+ {0, 0x03, 125},
+ {93, 0x00, 0},
+ {94, 0x00, 0},
+ },
+ /* 85 */
+ {
+ {2, 0x02, 0},
+ {9, 0x02, 0},
+ {23, 0x02, 0},
+ {40, 0x03, 0},
+ {2, 0x02, 36},
+ {9, 0x02, 36},
+ {23, 0x02, 36},
+ {40, 0x03, 36},
+ {2, 0x02, 64},
+ {9, 0x02, 64},
+ {23, 0x02, 64},
+ {40, 0x03, 64},
+ {2, 0x02, 91},
+ {9, 0x02, 91},
+ {23, 0x02, 91},
+ {40, 0x03, 91},
+ },
+ /* 86 */
+ {
+ {3, 0x02, 0},
+ {6, 0x02, 0},
+ {10, 0x02, 0},
+ {15, 0x02, 0},
+ {24, 0x02, 0},
+ {31, 0x02, 0},
+ {41, 0x02, 0},
+ {56, 0x03, 0},
+ {3, 0x02, 36},
+ {6, 0x02, 36},
+ {10, 0x02, 36},
+ {15, 0x02, 36},
+ {24, 0x02, 36},
+ {31, 0x02, 36},
+ {41, 0x02, 36},
+ {56, 0x03, 36},
+ },
+ /* 87 */
+ {
+ {3, 0x02, 64},
+ {6, 0x02, 64},
+ {10, 0x02, 64},
+ {15, 0x02, 64},
+ {24, 0x02, 64},
+ {31, 0x02, 64},
+ {41, 0x02, 64},
+ {56, 0x03, 64},
+ {3, 0x02, 91},
+ {6, 0x02, 91},
+ {10, 0x02, 91},
+ {15, 0x02, 91},
+ {24, 0x02, 91},
+ {31, 0x02, 91},
+ {41, 0x02, 91},
+ {56, 0x03, 91},
+ },
+ /* 88 */
+ {
+ {2, 0x02, 93},
+ {9, 0x02, 93},
+ {23, 0x02, 93},
+ {40, 0x03, 93},
+ {2, 0x02, 126},
+ {9, 0x02, 126},
+ {23, 0x02, 126},
+ {40, 0x03, 126},
+ {1, 0x02, 94},
+ {22, 0x03, 94},
+ {1, 0x02, 125},
+ {22, 0x03, 125},
+ {0, 0x03, 60},
+ {0, 0x03, 96},
+ {0, 0x03, 123},
+ {95, 0x00, 0},
+ },
+ /* 89 */
+ {
+ {3, 0x02, 93},
+ {6, 0x02, 93},
+ {10, 0x02, 93},
+ {15, 0x02, 93},
+ {24, 0x02, 93},
+ {31, 0x02, 93},
+ {41, 0x02, 93},
+ {56, 0x03, 93},
+ {3, 0x02, 126},
+ {6, 0x02, 126},
+ {10, 0x02, 126},
+ {15, 0x02, 126},
+ {24, 0x02, 126},
+ {31, 0x02, 126},
+ {41, 0x02, 126},
+ {56, 0x03, 126},
+ },
+ /* 90 */
+ {
+ {2, 0x02, 94},
+ {9, 0x02, 94},
+ {23, 0x02, 94},
+ {40, 0x03, 94},
+ {2, 0x02, 125},
+ {9, 0x02, 125},
+ {23, 0x02, 125},
+ {40, 0x03, 125},
+ {1, 0x02, 60},
+ {22, 0x03, 60},
+ {1, 0x02, 96},
+ {22, 0x03, 96},
+ {1, 0x02, 123},
+ {22, 0x03, 123},
+ {96, 0x00, 0},
+ {110, 0x00, 0},
+ },
+ /* 91 */
+ {
+ {3, 0x02, 94},
+ {6, 0x02, 94},
+ {10, 0x02, 94},
+ {15, 0x02, 94},
+ {24, 0x02, 94},
+ {31, 0x02, 94},
+ {41, 0x02, 94},
+ {56, 0x03, 94},
+ {3, 0x02, 125},
+ {6, 0x02, 125},
+ {10, 0x02, 125},
+ {15, 0x02, 125},
+ {24, 0x02, 125},
+ {31, 0x02, 125},
+ {41, 0x02, 125},
+ {56, 0x03, 125},
+ },
+ /* 92 */
+ {
+ {2, 0x02, 60},
+ {9, 0x02, 60},
+ {23, 0x02, 60},
+ {40, 0x03, 60},
+ {2, 0x02, 96},
+ {9, 0x02, 96},
+ {23, 0x02, 96},
+ {40, 0x03, 96},
+ {2, 0x02, 123},
+ {9, 0x02, 123},
+ {23, 0x02, 123},
+ {40, 0x03, 123},
+ {97, 0x00, 0},
+ {101, 0x00, 0},
+ {111, 0x00, 0},
+ {133, 0x00, 0},
+ },
+ /* 93 */
+ {
+ {3, 0x02, 60},
+ {6, 0x02, 60},
+ {10, 0x02, 60},
+ {15, 0x02, 60},
+ {24, 0x02, 60},
+ {31, 0x02, 60},
+ {41, 0x02, 60},
+ {56, 0x03, 60},
+ {3, 0x02, 96},
+ {6, 0x02, 96},
+ {10, 0x02, 96},
+ {15, 0x02, 96},
+ {24, 0x02, 96},
+ {31, 0x02, 96},
+ {41, 0x02, 96},
+ {56, 0x03, 96},
+ },
+ /* 94 */
+ {
+ {3, 0x02, 123},
+ {6, 0x02, 123},
+ {10, 0x02, 123},
+ {15, 0x02, 123},
+ {24, 0x02, 123},
+ {31, 0x02, 123},
+ {41, 0x02, 123},
+ {56, 0x03, 123},
+ {98, 0x00, 0},
+ {99, 0x00, 0},
+ {102, 0x00, 0},
+ {105, 0x00, 0},
+ {112, 0x00, 0},
+ {119, 0x00, 0},
+ {134, 0x00, 0},
+ {153, 0x00, 0},
+ },
+ /* 95 */
+ {
+ {0, 0x03, 92},
+ {0, 0x03, 195},
+ {0, 0x03, 208},
+ {100, 0x00, 0},
+ {103, 0x00, 0},
+ {104, 0x00, 0},
+ {106, 0x00, 0},
+ {107, 0x00, 0},
+ {113, 0x00, 0},
+ {116, 0x00, 0},
+ {120, 0x00, 0},
+ {126, 0x00, 0},
+ {135, 0x00, 0},
+ {142, 0x00, 0},
+ {154, 0x00, 0},
+ {169, 0x00, 0},
+ },
+ /* 96 */
+ {
+ {1, 0x02, 92},
+ {22, 0x03, 92},
+ {1, 0x02, 195},
+ {22, 0x03, 195},
+ {1, 0x02, 208},
+ {22, 0x03, 208},
+ {0, 0x03, 128},
+ {0, 0x03, 130},
+ {0, 0x03, 131},
+ {0, 0x03, 162},
+ {0, 0x03, 184},
+ {0, 0x03, 194},
+ {0, 0x03, 224},
+ {0, 0x03, 226},
+ {108, 0x00, 0},
+ {109, 0x00, 0},
+ },
+ /* 97 */
+ {
+ {2, 0x02, 92},
+ {9, 0x02, 92},
+ {23, 0x02, 92},
+ {40, 0x03, 92},
+ {2, 0x02, 195},
+ {9, 0x02, 195},
+ {23, 0x02, 195},
+ {40, 0x03, 195},
+ {2, 0x02, 208},
+ {9, 0x02, 208},
+ {23, 0x02, 208},
+ {40, 0x03, 208},
+ {1, 0x02, 128},
+ {22, 0x03, 128},
+ {1, 0x02, 130},
+ {22, 0x03, 130},
+ },
+ /* 98 */
+ {
+ {3, 0x02, 92},
+ {6, 0x02, 92},
+ {10, 0x02, 92},
+ {15, 0x02, 92},
+ {24, 0x02, 92},
+ {31, 0x02, 92},
+ {41, 0x02, 92},
+ {56, 0x03, 92},
+ {3, 0x02, 195},
+ {6, 0x02, 195},
+ {10, 0x02, 195},
+ {15, 0x02, 195},
+ {24, 0x02, 195},
+ {31, 0x02, 195},
+ {41, 0x02, 195},
+ {56, 0x03, 195},
+ },
+ /* 99 */
+ {
+ {3, 0x02, 208},
+ {6, 0x02, 208},
+ {10, 0x02, 208},
+ {15, 0x02, 208},
+ {24, 0x02, 208},
+ {31, 0x02, 208},
+ {41, 0x02, 208},
+ {56, 0x03, 208},
+ {2, 0x02, 128},
+ {9, 0x02, 128},
+ {23, 0x02, 128},
+ {40, 0x03, 128},
+ {2, 0x02, 130},
+ {9, 0x02, 130},
+ {23, 0x02, 130},
+ {40, 0x03, 130},
+ },
+ /* 100 */
+ {
+ {3, 0x02, 128},
+ {6, 0x02, 128},
+ {10, 0x02, 128},
+ {15, 0x02, 128},
+ {24, 0x02, 128},
+ {31, 0x02, 128},
+ {41, 0x02, 128},
+ {56, 0x03, 128},
+ {3, 0x02, 130},
+ {6, 0x02, 130},
+ {10, 0x02, 130},
+ {15, 0x02, 130},
+ {24, 0x02, 130},
+ {31, 0x02, 130},
+ {41, 0x02, 130},
+ {56, 0x03, 130},
+ },
+ /* 101 */
+ {
+ {1, 0x02, 131},
+ {22, 0x03, 131},
+ {1, 0x02, 162},
+ {22, 0x03, 162},
+ {1, 0x02, 184},
+ {22, 0x03, 184},
+ {1, 0x02, 194},
+ {22, 0x03, 194},
+ {1, 0x02, 224},
+ {22, 0x03, 224},
+ {1, 0x02, 226},
+ {22, 0x03, 226},
+ {0, 0x03, 153},
+ {0, 0x03, 161},
+ {0, 0x03, 167},
+ {0, 0x03, 172},
+ },
+ /* 102 */
+ {
+ {2, 0x02, 131},
+ {9, 0x02, 131},
+ {23, 0x02, 131},
+ {40, 0x03, 131},
+ {2, 0x02, 162},
+ {9, 0x02, 162},
+ {23, 0x02, 162},
+ {40, 0x03, 162},
+ {2, 0x02, 184},
+ {9, 0x02, 184},
+ {23, 0x02, 184},
+ {40, 0x03, 184},
+ {2, 0x02, 194},
+ {9, 0x02, 194},
+ {23, 0x02, 194},
+ {40, 0x03, 194},
+ },
+ /* 103 */
+ {
+ {3, 0x02, 131},
+ {6, 0x02, 131},
+ {10, 0x02, 131},
+ {15, 0x02, 131},
+ {24, 0x02, 131},
+ {31, 0x02, 131},
+ {41, 0x02, 131},
+ {56, 0x03, 131},
+ {3, 0x02, 162},
+ {6, 0x02, 162},
+ {10, 0x02, 162},
+ {15, 0x02, 162},
+ {24, 0x02, 162},
+ {31, 0x02, 162},
+ {41, 0x02, 162},
+ {56, 0x03, 162},
+ },
+ /* 104 */
+ {
+ {3, 0x02, 184},
+ {6, 0x02, 184},
+ {10, 0x02, 184},
+ {15, 0x02, 184},
+ {24, 0x02, 184},
+ {31, 0x02, 184},
+ {41, 0x02, 184},
+ {56, 0x03, 184},
+ {3, 0x02, 194},
+ {6, 0x02, 194},
+ {10, 0x02, 194},
+ {15, 0x02, 194},
+ {24, 0x02, 194},
+ {31, 0x02, 194},
+ {41, 0x02, 194},
+ {56, 0x03, 194},
+ },
+ /* 105 */
+ {
+ {2, 0x02, 224},
+ {9, 0x02, 224},
+ {23, 0x02, 224},
+ {40, 0x03, 224},
+ {2, 0x02, 226},
+ {9, 0x02, 226},
+ {23, 0x02, 226},
+ {40, 0x03, 226},
+ {1, 0x02, 153},
+ {22, 0x03, 153},
+ {1, 0x02, 161},
+ {22, 0x03, 161},
+ {1, 0x02, 167},
+ {22, 0x03, 167},
+ {1, 0x02, 172},
+ {22, 0x03, 172},
+ },
+ /* 106 */
+ {
+ {3, 0x02, 224},
+ {6, 0x02, 224},
+ {10, 0x02, 224},
+ {15, 0x02, 224},
+ {24, 0x02, 224},
+ {31, 0x02, 224},
+ {41, 0x02, 224},
+ {56, 0x03, 224},
+ {3, 0x02, 226},
+ {6, 0x02, 226},
+ {10, 0x02, 226},
+ {15, 0x02, 226},
+ {24, 0x02, 226},
+ {31, 0x02, 226},
+ {41, 0x02, 226},
+ {56, 0x03, 226},
+ },
+ /* 107 */
+ {
+ {2, 0x02, 153},
+ {9, 0x02, 153},
+ {23, 0x02, 153},
+ {40, 0x03, 153},
+ {2, 0x02, 161},
+ {9, 0x02, 161},
+ {23, 0x02, 161},
+ {40, 0x03, 161},
+ {2, 0x02, 167},
+ {9, 0x02, 167},
+ {23, 0x02, 167},
+ {40, 0x03, 167},
+ {2, 0x02, 172},
+ {9, 0x02, 172},
+ {23, 0x02, 172},
+ {40, 0x03, 172},
+ },
+ /* 108 */
+ {
+ {3, 0x02, 153},
+ {6, 0x02, 153},
+ {10, 0x02, 153},
+ {15, 0x02, 153},
+ {24, 0x02, 153},
+ {31, 0x02, 153},
+ {41, 0x02, 153},
+ {56, 0x03, 153},
+ {3, 0x02, 161},
+ {6, 0x02, 161},
+ {10, 0x02, 161},
+ {15, 0x02, 161},
+ {24, 0x02, 161},
+ {31, 0x02, 161},
+ {41, 0x02, 161},
+ {56, 0x03, 161},
+ },
+ /* 109 */
+ {
+ {3, 0x02, 167},
+ {6, 0x02, 167},
+ {10, 0x02, 167},
+ {15, 0x02, 167},
+ {24, 0x02, 167},
+ {31, 0x02, 167},
+ {41, 0x02, 167},
+ {56, 0x03, 167},
+ {3, 0x02, 172},
+ {6, 0x02, 172},
+ {10, 0x02, 172},
+ {15, 0x02, 172},
+ {24, 0x02, 172},
+ {31, 0x02, 172},
+ {41, 0x02, 172},
+ {56, 0x03, 172},
+ },
+ /* 110 */
+ {
+ {114, 0x00, 0},
+ {115, 0x00, 0},
+ {117, 0x00, 0},
+ {118, 0x00, 0},
+ {121, 0x00, 0},
+ {123, 0x00, 0},
+ {127, 0x00, 0},
+ {130, 0x00, 0},
+ {136, 0x00, 0},
+ {139, 0x00, 0},
+ {143, 0x00, 0},
+ {146, 0x00, 0},
+ {155, 0x00, 0},
+ {162, 0x00, 0},
+ {170, 0x00, 0},
+ {180, 0x00, 0},
+ },
+ /* 111 */
+ {
+ {0, 0x03, 176},
+ {0, 0x03, 177},
+ {0, 0x03, 179},
+ {0, 0x03, 209},
+ {0, 0x03, 216},
+ {0, 0x03, 217},
+ {0, 0x03, 227},
+ {0, 0x03, 229},
+ {0, 0x03, 230},
+ {122, 0x00, 0},
+ {124, 0x00, 0},
+ {125, 0x00, 0},
+ {128, 0x00, 0},
+ {129, 0x00, 0},
+ {131, 0x00, 0},
+ {132, 0x00, 0},
+ },
+ /* 112 */
+ {
+ {1, 0x02, 176},
+ {22, 0x03, 176},
+ {1, 0x02, 177},
+ {22, 0x03, 177},
+ {1, 0x02, 179},
+ {22, 0x03, 179},
+ {1, 0x02, 209},
+ {22, 0x03, 209},
+ {1, 0x02, 216},
+ {22, 0x03, 216},
+ {1, 0x02, 217},
+ {22, 0x03, 217},
+ {1, 0x02, 227},
+ {22, 0x03, 227},
+ {1, 0x02, 229},
+ {22, 0x03, 229},
+ },
+ /* 113 */
+ {
+ {2, 0x02, 176},
+ {9, 0x02, 176},
+ {23, 0x02, 176},
+ {40, 0x03, 176},
+ {2, 0x02, 177},
+ {9, 0x02, 177},
+ {23, 0x02, 177},
+ {40, 0x03, 177},
+ {2, 0x02, 179},
+ {9, 0x02, 179},
+ {23, 0x02, 179},
+ {40, 0x03, 179},
+ {2, 0x02, 209},
+ {9, 0x02, 209},
+ {23, 0x02, 209},
+ {40, 0x03, 209},
+ },
+ /* 114 */
+ {
+ {3, 0x02, 176},
+ {6, 0x02, 176},
+ {10, 0x02, 176},
+ {15, 0x02, 176},
+ {24, 0x02, 176},
+ {31, 0x02, 176},
+ {41, 0x02, 176},
+ {56, 0x03, 176},
+ {3, 0x02, 177},
+ {6, 0x02, 177},
+ {10, 0x02, 177},
+ {15, 0x02, 177},
+ {24, 0x02, 177},
+ {31, 0x02, 177},
+ {41, 0x02, 177},
+ {56, 0x03, 177},
+ },
+ /* 115 */
+ {
+ {3, 0x02, 179},
+ {6, 0x02, 179},
+ {10, 0x02, 179},
+ {15, 0x02, 179},
+ {24, 0x02, 179},
+ {31, 0x02, 179},
+ {41, 0x02, 179},
+ {56, 0x03, 179},
+ {3, 0x02, 209},
+ {6, 0x02, 209},
+ {10, 0x02, 209},
+ {15, 0x02, 209},
+ {24, 0x02, 209},
+ {31, 0x02, 209},
+ {41, 0x02, 209},
+ {56, 0x03, 209},
+ },
+ /* 116 */
+ {
+ {2, 0x02, 216},
+ {9, 0x02, 216},
+ {23, 0x02, 216},
+ {40, 0x03, 216},
+ {2, 0x02, 217},
+ {9, 0x02, 217},
+ {23, 0x02, 217},
+ {40, 0x03, 217},
+ {2, 0x02, 227},
+ {9, 0x02, 227},
+ {23, 0x02, 227},
+ {40, 0x03, 227},
+ {2, 0x02, 229},
+ {9, 0x02, 229},
+ {23, 0x02, 229},
+ {40, 0x03, 229},
+ },
+ /* 117 */
+ {
+ {3, 0x02, 216},
+ {6, 0x02, 216},
+ {10, 0x02, 216},
+ {15, 0x02, 216},
+ {24, 0x02, 216},
+ {31, 0x02, 216},
+ {41, 0x02, 216},
+ {56, 0x03, 216},
+ {3, 0x02, 217},
+ {6, 0x02, 217},
+ {10, 0x02, 217},
+ {15, 0x02, 217},
+ {24, 0x02, 217},
+ {31, 0x02, 217},
+ {41, 0x02, 217},
+ {56, 0x03, 217},
+ },
+ /* 118 */
+ {
+ {3, 0x02, 227},
+ {6, 0x02, 227},
+ {10, 0x02, 227},
+ {15, 0x02, 227},
+ {24, 0x02, 227},
+ {31, 0x02, 227},
+ {41, 0x02, 227},
+ {56, 0x03, 227},
+ {3, 0x02, 229},
+ {6, 0x02, 229},
+ {10, 0x02, 229},
+ {15, 0x02, 229},
+ {24, 0x02, 229},
+ {31, 0x02, 229},
+ {41, 0x02, 229},
+ {56, 0x03, 229},
+ },
+ /* 119 */
+ {
+ {1, 0x02, 230},
+ {22, 0x03, 230},
+ {0, 0x03, 129},
+ {0, 0x03, 132},
+ {0, 0x03, 133},
+ {0, 0x03, 134},
+ {0, 0x03, 136},
+ {0, 0x03, 146},
+ {0, 0x03, 154},
+ {0, 0x03, 156},
+ {0, 0x03, 160},
+ {0, 0x03, 163},
+ {0, 0x03, 164},
+ {0, 0x03, 169},
+ {0, 0x03, 170},
+ {0, 0x03, 173},
+ },
+ /* 120 */
+ {
+ {2, 0x02, 230},
+ {9, 0x02, 230},
+ {23, 0x02, 230},
+ {40, 0x03, 230},
+ {1, 0x02, 129},
+ {22, 0x03, 129},
+ {1, 0x02, 132},
+ {22, 0x03, 132},
+ {1, 0x02, 133},
+ {22, 0x03, 133},
+ {1, 0x02, 134},
+ {22, 0x03, 134},
+ {1, 0x02, 136},
+ {22, 0x03, 136},
+ {1, 0x02, 146},
+ {22, 0x03, 146},
+ },
+ /* 121 */
+ {
+ {3, 0x02, 230},
+ {6, 0x02, 230},
+ {10, 0x02, 230},
+ {15, 0x02, 230},
+ {24, 0x02, 230},
+ {31, 0x02, 230},
+ {41, 0x02, 230},
+ {56, 0x03, 230},
+ {2, 0x02, 129},
+ {9, 0x02, 129},
+ {23, 0x02, 129},
+ {40, 0x03, 129},
+ {2, 0x02, 132},
+ {9, 0x02, 132},
+ {23, 0x02, 132},
+ {40, 0x03, 132},
+ },
+ /* 122 */
+ {
+ {3, 0x02, 129},
+ {6, 0x02, 129},
+ {10, 0x02, 129},
+ {15, 0x02, 129},
+ {24, 0x02, 129},
+ {31, 0x02, 129},
+ {41, 0x02, 129},
+ {56, 0x03, 129},
+ {3, 0x02, 132},
+ {6, 0x02, 132},
+ {10, 0x02, 132},
+ {15, 0x02, 132},
+ {24, 0x02, 132},
+ {31, 0x02, 132},
+ {41, 0x02, 132},
+ {56, 0x03, 132},
+ },
+ /* 123 */
+ {
+ {2, 0x02, 133},
+ {9, 0x02, 133},
+ {23, 0x02, 133},
+ {40, 0x03, 133},
+ {2, 0x02, 134},
+ {9, 0x02, 134},
+ {23, 0x02, 134},
+ {40, 0x03, 134},
+ {2, 0x02, 136},
+ {9, 0x02, 136},
+ {23, 0x02, 136},
+ {40, 0x03, 136},
+ {2, 0x02, 146},
+ {9, 0x02, 146},
+ {23, 0x02, 146},
+ {40, 0x03, 146},
+ },
+ /* 124 */
+ {
+ {3, 0x02, 133},
+ {6, 0x02, 133},
+ {10, 0x02, 133},
+ {15, 0x02, 133},
+ {24, 0x02, 133},
+ {31, 0x02, 133},
+ {41, 0x02, 133},
+ {56, 0x03, 133},
+ {3, 0x02, 134},
+ {6, 0x02, 134},
+ {10, 0x02, 134},
+ {15, 0x02, 134},
+ {24, 0x02, 134},
+ {31, 0x02, 134},
+ {41, 0x02, 134},
+ {56, 0x03, 134},
+ },
+ /* 125 */
+ {
+ {3, 0x02, 136},
+ {6, 0x02, 136},
+ {10, 0x02, 136},
+ {15, 0x02, 136},
+ {24, 0x02, 136},
+ {31, 0x02, 136},
+ {41, 0x02, 136},
+ {56, 0x03, 136},
+ {3, 0x02, 146},
+ {6, 0x02, 146},
+ {10, 0x02, 146},
+ {15, 0x02, 146},
+ {24, 0x02, 146},
+ {31, 0x02, 146},
+ {41, 0x02, 146},
+ {56, 0x03, 146},
+ },
+ /* 126 */
+ {
+ {1, 0x02, 154},
+ {22, 0x03, 154},
+ {1, 0x02, 156},
+ {22, 0x03, 156},
+ {1, 0x02, 160},
+ {22, 0x03, 160},
+ {1, 0x02, 163},
+ {22, 0x03, 163},
+ {1, 0x02, 164},
+ {22, 0x03, 164},
+ {1, 0x02, 169},
+ {22, 0x03, 169},
+ {1, 0x02, 170},
+ {22, 0x03, 170},
+ {1, 0x02, 173},
+ {22, 0x03, 173},
+ },
+ /* 127 */
+ {
+ {2, 0x02, 154},
+ {9, 0x02, 154},
+ {23, 0x02, 154},
+ {40, 0x03, 154},
+ {2, 0x02, 156},
+ {9, 0x02, 156},
+ {23, 0x02, 156},
+ {40, 0x03, 156},
+ {2, 0x02, 160},
+ {9, 0x02, 160},
+ {23, 0x02, 160},
+ {40, 0x03, 160},
+ {2, 0x02, 163},
+ {9, 0x02, 163},
+ {23, 0x02, 163},
+ {40, 0x03, 163},
+ },
+ /* 128 */
+ {
+ {3, 0x02, 154},
+ {6, 0x02, 154},
+ {10, 0x02, 154},
+ {15, 0x02, 154},
+ {24, 0x02, 154},
+ {31, 0x02, 154},
+ {41, 0x02, 154},
+ {56, 0x03, 154},
+ {3, 0x02, 156},
+ {6, 0x02, 156},
+ {10, 0x02, 156},
+ {15, 0x02, 156},
+ {24, 0x02, 156},
+ {31, 0x02, 156},
+ {41, 0x02, 156},
+ {56, 0x03, 156},
+ },
+ /* 129 */
+ {
+ {3, 0x02, 160},
+ {6, 0x02, 160},
+ {10, 0x02, 160},
+ {15, 0x02, 160},
+ {24, 0x02, 160},
+ {31, 0x02, 160},
+ {41, 0x02, 160},
+ {56, 0x03, 160},
+ {3, 0x02, 163},
+ {6, 0x02, 163},
+ {10, 0x02, 163},
+ {15, 0x02, 163},
+ {24, 0x02, 163},
+ {31, 0x02, 163},
+ {41, 0x02, 163},
+ {56, 0x03, 163},
+ },
+ /* 130 */
+ {
+ {2, 0x02, 164},
+ {9, 0x02, 164},
+ {23, 0x02, 164},
+ {40, 0x03, 164},
+ {2, 0x02, 169},
+ {9, 0x02, 169},
+ {23, 0x02, 169},
+ {40, 0x03, 169},
+ {2, 0x02, 170},
+ {9, 0x02, 170},
+ {23, 0x02, 170},
+ {40, 0x03, 170},
+ {2, 0x02, 173},
+ {9, 0x02, 173},
+ {23, 0x02, 173},
+ {40, 0x03, 173},
+ },
+ /* 131 */
+ {
+ {3, 0x02, 164},
+ {6, 0x02, 164},
+ {10, 0x02, 164},
+ {15, 0x02, 164},
+ {24, 0x02, 164},
+ {31, 0x02, 164},
+ {41, 0x02, 164},
+ {56, 0x03, 164},
+ {3, 0x02, 169},
+ {6, 0x02, 169},
+ {10, 0x02, 169},
+ {15, 0x02, 169},
+ {24, 0x02, 169},
+ {31, 0x02, 169},
+ {41, 0x02, 169},
+ {56, 0x03, 169},
+ },
+ /* 132 */
+ {
+ {3, 0x02, 170},
+ {6, 0x02, 170},
+ {10, 0x02, 170},
+ {15, 0x02, 170},
+ {24, 0x02, 170},
+ {31, 0x02, 170},
+ {41, 0x02, 170},
+ {56, 0x03, 170},
+ {3, 0x02, 173},
+ {6, 0x02, 173},
+ {10, 0x02, 173},
+ {15, 0x02, 173},
+ {24, 0x02, 173},
+ {31, 0x02, 173},
+ {41, 0x02, 173},
+ {56, 0x03, 173},
+ },
+ /* 133 */
+ {
+ {137, 0x00, 0},
+ {138, 0x00, 0},
+ {140, 0x00, 0},
+ {141, 0x00, 0},
+ {144, 0x00, 0},
+ {145, 0x00, 0},
+ {147, 0x00, 0},
+ {150, 0x00, 0},
+ {156, 0x00, 0},
+ {159, 0x00, 0},
+ {163, 0x00, 0},
+ {166, 0x00, 0},
+ {171, 0x00, 0},
+ {174, 0x00, 0},
+ {181, 0x00, 0},
+ {190, 0x00, 0},
+ },
+ /* 134 */
+ {
+ {0, 0x03, 178},
+ {0, 0x03, 181},
+ {0, 0x03, 185},
+ {0, 0x03, 186},
+ {0, 0x03, 187},
+ {0, 0x03, 189},
+ {0, 0x03, 190},
+ {0, 0x03, 196},
+ {0, 0x03, 198},
+ {0, 0x03, 228},
+ {0, 0x03, 232},
+ {0, 0x03, 233},
+ {148, 0x00, 0},
+ {149, 0x00, 0},
+ {151, 0x00, 0},
+ {152, 0x00, 0},
+ },
+ /* 135 */
+ {
+ {1, 0x02, 178},
+ {22, 0x03, 178},
+ {1, 0x02, 181},
+ {22, 0x03, 181},
+ {1, 0x02, 185},
+ {22, 0x03, 185},
+ {1, 0x02, 186},
+ {22, 0x03, 186},
+ {1, 0x02, 187},
+ {22, 0x03, 187},
+ {1, 0x02, 189},
+ {22, 0x03, 189},
+ {1, 0x02, 190},
+ {22, 0x03, 190},
+ {1, 0x02, 196},
+ {22, 0x03, 196},
+ },
+ /* 136 */
+ {
+ {2, 0x02, 178},
+ {9, 0x02, 178},
+ {23, 0x02, 178},
+ {40, 0x03, 178},
+ {2, 0x02, 181},
+ {9, 0x02, 181},
+ {23, 0x02, 181},
+ {40, 0x03, 181},
+ {2, 0x02, 185},
+ {9, 0x02, 185},
+ {23, 0x02, 185},
+ {40, 0x03, 185},
+ {2, 0x02, 186},
+ {9, 0x02, 186},
+ {23, 0x02, 186},
+ {40, 0x03, 186},
+ },
+ /* 137 */
+ {
+ {3, 0x02, 178},
+ {6, 0x02, 178},
+ {10, 0x02, 178},
+ {15, 0x02, 178},
+ {24, 0x02, 178},
+ {31, 0x02, 178},
+ {41, 0x02, 178},
+ {56, 0x03, 178},
+ {3, 0x02, 181},
+ {6, 0x02, 181},
+ {10, 0x02, 181},
+ {15, 0x02, 181},
+ {24, 0x02, 181},
+ {31, 0x02, 181},
+ {41, 0x02, 181},
+ {56, 0x03, 181},
+ },
+ /* 138 */
+ {
+ {3, 0x02, 185},
+ {6, 0x02, 185},
+ {10, 0x02, 185},
+ {15, 0x02, 185},
+ {24, 0x02, 185},
+ {31, 0x02, 185},
+ {41, 0x02, 185},
+ {56, 0x03, 185},
+ {3, 0x02, 186},
+ {6, 0x02, 186},
+ {10, 0x02, 186},
+ {15, 0x02, 186},
+ {24, 0x02, 186},
+ {31, 0x02, 186},
+ {41, 0x02, 186},
+ {56, 0x03, 186},
+ },
+ /* 139 */
+ {
+ {2, 0x02, 187},
+ {9, 0x02, 187},
+ {23, 0x02, 187},
+ {40, 0x03, 187},
+ {2, 0x02, 189},
+ {9, 0x02, 189},
+ {23, 0x02, 189},
+ {40, 0x03, 189},
+ {2, 0x02, 190},
+ {9, 0x02, 190},
+ {23, 0x02, 190},
+ {40, 0x03, 190},
+ {2, 0x02, 196},
+ {9, 0x02, 196},
+ {23, 0x02, 196},
+ {40, 0x03, 196},
+ },
+ /* 140 */
+ {
+ {3, 0x02, 187},
+ {6, 0x02, 187},
+ {10, 0x02, 187},
+ {15, 0x02, 187},
+ {24, 0x02, 187},
+ {31, 0x02, 187},
+ {41, 0x02, 187},
+ {56, 0x03, 187},
+ {3, 0x02, 189},
+ {6, 0x02, 189},
+ {10, 0x02, 189},
+ {15, 0x02, 189},
+ {24, 0x02, 189},
+ {31, 0x02, 189},
+ {41, 0x02, 189},
+ {56, 0x03, 189},
+ },
+ /* 141 */
+ {
+ {3, 0x02, 190},
+ {6, 0x02, 190},
+ {10, 0x02, 190},
+ {15, 0x02, 190},
+ {24, 0x02, 190},
+ {31, 0x02, 190},
+ {41, 0x02, 190},
+ {56, 0x03, 190},
+ {3, 0x02, 196},
+ {6, 0x02, 196},
+ {10, 0x02, 196},
+ {15, 0x02, 196},
+ {24, 0x02, 196},
+ {31, 0x02, 196},
+ {41, 0x02, 196},
+ {56, 0x03, 196},
+ },
+ /* 142 */
+ {
+ {1, 0x02, 198},
+ {22, 0x03, 198},
+ {1, 0x02, 228},
+ {22, 0x03, 228},
+ {1, 0x02, 232},
+ {22, 0x03, 232},
+ {1, 0x02, 233},
+ {22, 0x03, 233},
+ {0, 0x03, 1},
+ {0, 0x03, 135},
+ {0, 0x03, 137},
+ {0, 0x03, 138},
+ {0, 0x03, 139},
+ {0, 0x03, 140},
+ {0, 0x03, 141},
+ {0, 0x03, 143},
+ },
+ /* 143 */
+ {
+ {2, 0x02, 198},
+ {9, 0x02, 198},
+ {23, 0x02, 198},
+ {40, 0x03, 198},
+ {2, 0x02, 228},
+ {9, 0x02, 228},
+ {23, 0x02, 228},
+ {40, 0x03, 228},
+ {2, 0x02, 232},
+ {9, 0x02, 232},
+ {23, 0x02, 232},
+ {40, 0x03, 232},
+ {2, 0x02, 233},
+ {9, 0x02, 233},
+ {23, 0x02, 233},
+ {40, 0x03, 233},
+ },
+ /* 144 */
+ {
+ {3, 0x02, 198},
+ {6, 0x02, 198},
+ {10, 0x02, 198},
+ {15, 0x02, 198},
+ {24, 0x02, 198},
+ {31, 0x02, 198},
+ {41, 0x02, 198},
+ {56, 0x03, 198},
+ {3, 0x02, 228},
+ {6, 0x02, 228},
+ {10, 0x02, 228},
+ {15, 0x02, 228},
+ {24, 0x02, 228},
+ {31, 0x02, 228},
+ {41, 0x02, 228},
+ {56, 0x03, 228},
+ },
+ /* 145 */
+ {
+ {3, 0x02, 232},
+ {6, 0x02, 232},
+ {10, 0x02, 232},
+ {15, 0x02, 232},
+ {24, 0x02, 232},
+ {31, 0x02, 232},
+ {41, 0x02, 232},
+ {56, 0x03, 232},
+ {3, 0x02, 233},
+ {6, 0x02, 233},
+ {10, 0x02, 233},
+ {15, 0x02, 233},
+ {24, 0x02, 233},
+ {31, 0x02, 233},
+ {41, 0x02, 233},
+ {56, 0x03, 233},
+ },
+ /* 146 */
+ {
+ {1, 0x02, 1},
+ {22, 0x03, 1},
+ {1, 0x02, 135},
+ {22, 0x03, 135},
+ {1, 0x02, 137},
+ {22, 0x03, 137},
+ {1, 0x02, 138},
+ {22, 0x03, 138},
+ {1, 0x02, 139},
+ {22, 0x03, 139},
+ {1, 0x02, 140},
+ {22, 0x03, 140},
+ {1, 0x02, 141},
+ {22, 0x03, 141},
+ {1, 0x02, 143},
+ {22, 0x03, 143},
+ },
+ /* 147 */
+ {
+ {2, 0x02, 1},
+ {9, 0x02, 1},
+ {23, 0x02, 1},
+ {40, 0x03, 1},
+ {2, 0x02, 135},
+ {9, 0x02, 135},
+ {23, 0x02, 135},
+ {40, 0x03, 135},
+ {2, 0x02, 137},
+ {9, 0x02, 137},
+ {23, 0x02, 137},
+ {40, 0x03, 137},
+ {2, 0x02, 138},
+ {9, 0x02, 138},
+ {23, 0x02, 138},
+ {40, 0x03, 138},
+ },
+ /* 148 */
+ {
+ {3, 0x02, 1},
+ {6, 0x02, 1},
+ {10, 0x02, 1},
+ {15, 0x02, 1},
+ {24, 0x02, 1},
+ {31, 0x02, 1},
+ {41, 0x02, 1},
+ {56, 0x03, 1},
+ {3, 0x02, 135},
+ {6, 0x02, 135},
+ {10, 0x02, 135},
+ {15, 0x02, 135},
+ {24, 0x02, 135},
+ {31, 0x02, 135},
+ {41, 0x02, 135},
+ {56, 0x03, 135},
+ },
+ /* 149 */
+ {
+ {3, 0x02, 137},
+ {6, 0x02, 137},
+ {10, 0x02, 137},
+ {15, 0x02, 137},
+ {24, 0x02, 137},
+ {31, 0x02, 137},
+ {41, 0x02, 137},
+ {56, 0x03, 137},
+ {3, 0x02, 138},
+ {6, 0x02, 138},
+ {10, 0x02, 138},
+ {15, 0x02, 138},
+ {24, 0x02, 138},
+ {31, 0x02, 138},
+ {41, 0x02, 138},
+ {56, 0x03, 138},
+ },
+ /* 150 */
+ {
+ {2, 0x02, 139},
+ {9, 0x02, 139},
+ {23, 0x02, 139},
+ {40, 0x03, 139},
+ {2, 0x02, 140},
+ {9, 0x02, 140},
+ {23, 0x02, 140},
+ {40, 0x03, 140},
+ {2, 0x02, 141},
+ {9, 0x02, 141},
+ {23, 0x02, 141},
+ {40, 0x03, 141},
+ {2, 0x02, 143},
+ {9, 0x02, 143},
+ {23, 0x02, 143},
+ {40, 0x03, 143},
+ },
+ /* 151 */
+ {
+ {3, 0x02, 139},
+ {6, 0x02, 139},
+ {10, 0x02, 139},
+ {15, 0x02, 139},
+ {24, 0x02, 139},
+ {31, 0x02, 139},
+ {41, 0x02, 139},
+ {56, 0x03, 139},
+ {3, 0x02, 140},
+ {6, 0x02, 140},
+ {10, 0x02, 140},
+ {15, 0x02, 140},
+ {24, 0x02, 140},
+ {31, 0x02, 140},
+ {41, 0x02, 140},
+ {56, 0x03, 140},
+ },
+ /* 152 */
+ {
+ {3, 0x02, 141},
+ {6, 0x02, 141},
+ {10, 0x02, 141},
+ {15, 0x02, 141},
+ {24, 0x02, 141},
+ {31, 0x02, 141},
+ {41, 0x02, 141},
+ {56, 0x03, 141},
+ {3, 0x02, 143},
+ {6, 0x02, 143},
+ {10, 0x02, 143},
+ {15, 0x02, 143},
+ {24, 0x02, 143},
+ {31, 0x02, 143},
+ {41, 0x02, 143},
+ {56, 0x03, 143},
+ },
+ /* 153 */
+ {
+ {157, 0x00, 0},
+ {158, 0x00, 0},
+ {160, 0x00, 0},
+ {161, 0x00, 0},
+ {164, 0x00, 0},
+ {165, 0x00, 0},
+ {167, 0x00, 0},
+ {168, 0x00, 0},
+ {172, 0x00, 0},
+ {173, 0x00, 0},
+ {175, 0x00, 0},
+ {177, 0x00, 0},
+ {182, 0x00, 0},
+ {185, 0x00, 0},
+ {191, 0x00, 0},
+ {207, 0x00, 0},
+ },
+ /* 154 */
+ {
+ {0, 0x03, 147},
+ {0, 0x03, 149},
+ {0, 0x03, 150},
+ {0, 0x03, 151},
+ {0, 0x03, 152},
+ {0, 0x03, 155},
+ {0, 0x03, 157},
+ {0, 0x03, 158},
+ {0, 0x03, 165},
+ {0, 0x03, 166},
+ {0, 0x03, 168},
+ {0, 0x03, 174},
+ {0, 0x03, 175},
+ {0, 0x03, 180},
+ {0, 0x03, 182},
+ {0, 0x03, 183},
+ },
+ /* 155 */
+ {
+ {1, 0x02, 147},
+ {22, 0x03, 147},
+ {1, 0x02, 149},
+ {22, 0x03, 149},
+ {1, 0x02, 150},
+ {22, 0x03, 150},
+ {1, 0x02, 151},
+ {22, 0x03, 151},
+ {1, 0x02, 152},
+ {22, 0x03, 152},
+ {1, 0x02, 155},
+ {22, 0x03, 155},
+ {1, 0x02, 157},
+ {22, 0x03, 157},
+ {1, 0x02, 158},
+ {22, 0x03, 158},
+ },
+ /* 156 */
+ {
+ {2, 0x02, 147},
+ {9, 0x02, 147},
+ {23, 0x02, 147},
+ {40, 0x03, 147},
+ {2, 0x02, 149},
+ {9, 0x02, 149},
+ {23, 0x02, 149},
+ {40, 0x03, 149},
+ {2, 0x02, 150},
+ {9, 0x02, 150},
+ {23, 0x02, 150},
+ {40, 0x03, 150},
+ {2, 0x02, 151},
+ {9, 0x02, 151},
+ {23, 0x02, 151},
+ {40, 0x03, 151},
+ },
+ /* 157 */
+ {
+ {3, 0x02, 147},
+ {6, 0x02, 147},
+ {10, 0x02, 147},
+ {15, 0x02, 147},
+ {24, 0x02, 147},
+ {31, 0x02, 147},
+ {41, 0x02, 147},
+ {56, 0x03, 147},
+ {3, 0x02, 149},
+ {6, 0x02, 149},
+ {10, 0x02, 149},
+ {15, 0x02, 149},
+ {24, 0x02, 149},
+ {31, 0x02, 149},
+ {41, 0x02, 149},
+ {56, 0x03, 149},
+ },
+ /* 158 */
+ {
+ {3, 0x02, 150},
+ {6, 0x02, 150},
+ {10, 0x02, 150},
+ {15, 0x02, 150},
+ {24, 0x02, 150},
+ {31, 0x02, 150},
+ {41, 0x02, 150},
+ {56, 0x03, 150},
+ {3, 0x02, 151},
+ {6, 0x02, 151},
+ {10, 0x02, 151},
+ {15, 0x02, 151},
+ {24, 0x02, 151},
+ {31, 0x02, 151},
+ {41, 0x02, 151},
+ {56, 0x03, 151},
+ },
+ /* 159 */
+ {
+ {2, 0x02, 152},
+ {9, 0x02, 152},
+ {23, 0x02, 152},
+ {40, 0x03, 152},
+ {2, 0x02, 155},
+ {9, 0x02, 155},
+ {23, 0x02, 155},
+ {40, 0x03, 155},
+ {2, 0x02, 157},
+ {9, 0x02, 157},
+ {23, 0x02, 157},
+ {40, 0x03, 157},
+ {2, 0x02, 158},
+ {9, 0x02, 158},
+ {23, 0x02, 158},
+ {40, 0x03, 158},
+ },
+ /* 160 */
+ {
+ {3, 0x02, 152},
+ {6, 0x02, 152},
+ {10, 0x02, 152},
+ {15, 0x02, 152},
+ {24, 0x02, 152},
+ {31, 0x02, 152},
+ {41, 0x02, 152},
+ {56, 0x03, 152},
+ {3, 0x02, 155},
+ {6, 0x02, 155},
+ {10, 0x02, 155},
+ {15, 0x02, 155},
+ {24, 0x02, 155},
+ {31, 0x02, 155},
+ {41, 0x02, 155},
+ {56, 0x03, 155},
+ },
+ /* 161 */
+ {
+ {3, 0x02, 157},
+ {6, 0x02, 157},
+ {10, 0x02, 157},
+ {15, 0x02, 157},
+ {24, 0x02, 157},
+ {31, 0x02, 157},
+ {41, 0x02, 157},
+ {56, 0x03, 157},
+ {3, 0x02, 158},
+ {6, 0x02, 158},
+ {10, 0x02, 158},
+ {15, 0x02, 158},
+ {24, 0x02, 158},
+ {31, 0x02, 158},
+ {41, 0x02, 158},
+ {56, 0x03, 158},
+ },
+ /* 162 */
+ {
+ {1, 0x02, 165},
+ {22, 0x03, 165},
+ {1, 0x02, 166},
+ {22, 0x03, 166},
+ {1, 0x02, 168},
+ {22, 0x03, 168},
+ {1, 0x02, 174},
+ {22, 0x03, 174},
+ {1, 0x02, 175},
+ {22, 0x03, 175},
+ {1, 0x02, 180},
+ {22, 0x03, 180},
+ {1, 0x02, 182},
+ {22, 0x03, 182},
+ {1, 0x02, 183},
+ {22, 0x03, 183},
+ },
+ /* 163 */
+ {
+ {2, 0x02, 165},
+ {9, 0x02, 165},
+ {23, 0x02, 165},
+ {40, 0x03, 165},
+ {2, 0x02, 166},
+ {9, 0x02, 166},
+ {23, 0x02, 166},
+ {40, 0x03, 166},
+ {2, 0x02, 168},
+ {9, 0x02, 168},
+ {23, 0x02, 168},
+ {40, 0x03, 168},
+ {2, 0x02, 174},
+ {9, 0x02, 174},
+ {23, 0x02, 174},
+ {40, 0x03, 174},
+ },
+ /* 164 */
+ {
+ {3, 0x02, 165},
+ {6, 0x02, 165},
+ {10, 0x02, 165},
+ {15, 0x02, 165},
+ {24, 0x02, 165},
+ {31, 0x02, 165},
+ {41, 0x02, 165},
+ {56, 0x03, 165},
+ {3, 0x02, 166},
+ {6, 0x02, 166},
+ {10, 0x02, 166},
+ {15, 0x02, 166},
+ {24, 0x02, 166},
+ {31, 0x02, 166},
+ {41, 0x02, 166},
+ {56, 0x03, 166},
+ },
+ /* 165 */
+ {
+ {3, 0x02, 168},
+ {6, 0x02, 168},
+ {10, 0x02, 168},
+ {15, 0x02, 168},
+ {24, 0x02, 168},
+ {31, 0x02, 168},
+ {41, 0x02, 168},
+ {56, 0x03, 168},
+ {3, 0x02, 174},
+ {6, 0x02, 174},
+ {10, 0x02, 174},
+ {15, 0x02, 174},
+ {24, 0x02, 174},
+ {31, 0x02, 174},
+ {41, 0x02, 174},
+ {56, 0x03, 174},
+ },
+ /* 166 */
+ {
+ {2, 0x02, 175},
+ {9, 0x02, 175},
+ {23, 0x02, 175},
+ {40, 0x03, 175},
+ {2, 0x02, 180},
+ {9, 0x02, 180},
+ {23, 0x02, 180},
+ {40, 0x03, 180},
+ {2, 0x02, 182},
+ {9, 0x02, 182},
+ {23, 0x02, 182},
+ {40, 0x03, 182},
+ {2, 0x02, 183},
+ {9, 0x02, 183},
+ {23, 0x02, 183},
+ {40, 0x03, 183},
+ },
+ /* 167 */
+ {
+ {3, 0x02, 175},
+ {6, 0x02, 175},
+ {10, 0x02, 175},
+ {15, 0x02, 175},
+ {24, 0x02, 175},
+ {31, 0x02, 175},
+ {41, 0x02, 175},
+ {56, 0x03, 175},
+ {3, 0x02, 180},
+ {6, 0x02, 180},
+ {10, 0x02, 180},
+ {15, 0x02, 180},
+ {24, 0x02, 180},
+ {31, 0x02, 180},
+ {41, 0x02, 180},
+ {56, 0x03, 180},
+ },
+ /* 168 */
+ {
+ {3, 0x02, 182},
+ {6, 0x02, 182},
+ {10, 0x02, 182},
+ {15, 0x02, 182},
+ {24, 0x02, 182},
+ {31, 0x02, 182},
+ {41, 0x02, 182},
+ {56, 0x03, 182},
+ {3, 0x02, 183},
+ {6, 0x02, 183},
+ {10, 0x02, 183},
+ {15, 0x02, 183},
+ {24, 0x02, 183},
+ {31, 0x02, 183},
+ {41, 0x02, 183},
+ {56, 0x03, 183},
+ },
+ /* 169 */
+ {
+ {0, 0x03, 188},
+ {0, 0x03, 191},
+ {0, 0x03, 197},
+ {0, 0x03, 231},
+ {0, 0x03, 239},
+ {176, 0x00, 0},
+ {178, 0x00, 0},
+ {179, 0x00, 0},
+ {183, 0x00, 0},
+ {184, 0x00, 0},
+ {186, 0x00, 0},
+ {187, 0x00, 0},
+ {192, 0x00, 0},
+ {199, 0x00, 0},
+ {208, 0x00, 0},
+ {223, 0x00, 0},
+ },
+ /* 170 */
+ {
+ {1, 0x02, 188},
+ {22, 0x03, 188},
+ {1, 0x02, 191},
+ {22, 0x03, 191},
+ {1, 0x02, 197},
+ {22, 0x03, 197},
+ {1, 0x02, 231},
+ {22, 0x03, 231},
+ {1, 0x02, 239},
+ {22, 0x03, 239},
+ {0, 0x03, 9},
+ {0, 0x03, 142},
+ {0, 0x03, 144},
+ {0, 0x03, 145},
+ {0, 0x03, 148},
+ {0, 0x03, 159},
+ },
+ /* 171 */
+ {
+ {2, 0x02, 188},
+ {9, 0x02, 188},
+ {23, 0x02, 188},
+ {40, 0x03, 188},
+ {2, 0x02, 191},
+ {9, 0x02, 191},
+ {23, 0x02, 191},
+ {40, 0x03, 191},
+ {2, 0x02, 197},
+ {9, 0x02, 197},
+ {23, 0x02, 197},
+ {40, 0x03, 197},
+ {2, 0x02, 231},
+ {9, 0x02, 231},
+ {23, 0x02, 231},
+ {40, 0x03, 231},
+ },
+ /* 172 */
+ {
+ {3, 0x02, 188},
+ {6, 0x02, 188},
+ {10, 0x02, 188},
+ {15, 0x02, 188},
+ {24, 0x02, 188},
+ {31, 0x02, 188},
+ {41, 0x02, 188},
+ {56, 0x03, 188},
+ {3, 0x02, 191},
+ {6, 0x02, 191},
+ {10, 0x02, 191},
+ {15, 0x02, 191},
+ {24, 0x02, 191},
+ {31, 0x02, 191},
+ {41, 0x02, 191},
+ {56, 0x03, 191},
+ },
+ /* 173 */
+ {
+ {3, 0x02, 197},
+ {6, 0x02, 197},
+ {10, 0x02, 197},
+ {15, 0x02, 197},
+ {24, 0x02, 197},
+ {31, 0x02, 197},
+ {41, 0x02, 197},
+ {56, 0x03, 197},
+ {3, 0x02, 231},
+ {6, 0x02, 231},
+ {10, 0x02, 231},
+ {15, 0x02, 231},
+ {24, 0x02, 231},
+ {31, 0x02, 231},
+ {41, 0x02, 231},
+ {56, 0x03, 231},
+ },
+ /* 174 */
+ {
+ {2, 0x02, 239},
+ {9, 0x02, 239},
+ {23, 0x02, 239},
+ {40, 0x03, 239},
+ {1, 0x02, 9},
+ {22, 0x03, 9},
+ {1, 0x02, 142},
+ {22, 0x03, 142},
+ {1, 0x02, 144},
+ {22, 0x03, 144},
+ {1, 0x02, 145},
+ {22, 0x03, 145},
+ {1, 0x02, 148},
+ {22, 0x03, 148},
+ {1, 0x02, 159},
+ {22, 0x03, 159},
+ },
+ /* 175 */
+ {
+ {3, 0x02, 239},
+ {6, 0x02, 239},
+ {10, 0x02, 239},
+ {15, 0x02, 239},
+ {24, 0x02, 239},
+ {31, 0x02, 239},
+ {41, 0x02, 239},
+ {56, 0x03, 239},
+ {2, 0x02, 9},
+ {9, 0x02, 9},
+ {23, 0x02, 9},
+ {40, 0x03, 9},
+ {2, 0x02, 142},
+ {9, 0x02, 142},
+ {23, 0x02, 142},
+ {40, 0x03, 142},
+ },
+ /* 176 */
+ {
+ {3, 0x02, 9},
+ {6, 0x02, 9},
+ {10, 0x02, 9},
+ {15, 0x02, 9},
+ {24, 0x02, 9},
+ {31, 0x02, 9},
+ {41, 0x02, 9},
+ {56, 0x03, 9},
+ {3, 0x02, 142},
+ {6, 0x02, 142},
+ {10, 0x02, 142},
+ {15, 0x02, 142},
+ {24, 0x02, 142},
+ {31, 0x02, 142},
+ {41, 0x02, 142},
+ {56, 0x03, 142},
+ },
+ /* 177 */
+ {
+ {2, 0x02, 144},
+ {9, 0x02, 144},
+ {23, 0x02, 144},
+ {40, 0x03, 144},
+ {2, 0x02, 145},
+ {9, 0x02, 145},
+ {23, 0x02, 145},
+ {40, 0x03, 145},
+ {2, 0x02, 148},
+ {9, 0x02, 148},
+ {23, 0x02, 148},
+ {40, 0x03, 148},
+ {2, 0x02, 159},
+ {9, 0x02, 159},
+ {23, 0x02, 159},
+ {40, 0x03, 159},
+ },
+ /* 178 */
+ {
+ {3, 0x02, 144},
+ {6, 0x02, 144},
+ {10, 0x02, 144},
+ {15, 0x02, 144},
+ {24, 0x02, 144},
+ {31, 0x02, 144},
+ {41, 0x02, 144},
+ {56, 0x03, 144},
+ {3, 0x02, 145},
+ {6, 0x02, 145},
+ {10, 0x02, 145},
+ {15, 0x02, 145},
+ {24, 0x02, 145},
+ {31, 0x02, 145},
+ {41, 0x02, 145},
+ {56, 0x03, 145},
+ },
+ /* 179 */
+ {
+ {3, 0x02, 148},
+ {6, 0x02, 148},
+ {10, 0x02, 148},
+ {15, 0x02, 148},
+ {24, 0x02, 148},
+ {31, 0x02, 148},
+ {41, 0x02, 148},
+ {56, 0x03, 148},
+ {3, 0x02, 159},
+ {6, 0x02, 159},
+ {10, 0x02, 159},
+ {15, 0x02, 159},
+ {24, 0x02, 159},
+ {31, 0x02, 159},
+ {41, 0x02, 159},
+ {56, 0x03, 159},
+ },
+ /* 180 */
+ {
+ {0, 0x03, 171},
+ {0, 0x03, 206},
+ {0, 0x03, 215},
+ {0, 0x03, 225},
+ {0, 0x03, 236},
+ {0, 0x03, 237},
+ {188, 0x00, 0},
+ {189, 0x00, 0},
+ {193, 0x00, 0},
+ {196, 0x00, 0},
+ {200, 0x00, 0},
+ {203, 0x00, 0},
+ {209, 0x00, 0},
+ {216, 0x00, 0},
+ {224, 0x00, 0},
+ {238, 0x00, 0},
+ },
+ /* 181 */
+ {
+ {1, 0x02, 171},
+ {22, 0x03, 171},
+ {1, 0x02, 206},
+ {22, 0x03, 206},
+ {1, 0x02, 215},
+ {22, 0x03, 215},
+ {1, 0x02, 225},
+ {22, 0x03, 225},
+ {1, 0x02, 236},
+ {22, 0x03, 236},
+ {1, 0x02, 237},
+ {22, 0x03, 237},
+ {0, 0x03, 199},
+ {0, 0x03, 207},
+ {0, 0x03, 234},
+ {0, 0x03, 235},
+ },
+ /* 182 */
+ {
+ {2, 0x02, 171},
+ {9, 0x02, 171},
+ {23, 0x02, 171},
+ {40, 0x03, 171},
+ {2, 0x02, 206},
+ {9, 0x02, 206},
+ {23, 0x02, 206},
+ {40, 0x03, 206},
+ {2, 0x02, 215},
+ {9, 0x02, 215},
+ {23, 0x02, 215},
+ {40, 0x03, 215},
+ {2, 0x02, 225},
+ {9, 0x02, 225},
+ {23, 0x02, 225},
+ {40, 0x03, 225},
+ },
+ /* 183 */
+ {
+ {3, 0x02, 171},
+ {6, 0x02, 171},
+ {10, 0x02, 171},
+ {15, 0x02, 171},
+ {24, 0x02, 171},
+ {31, 0x02, 171},
+ {41, 0x02, 171},
+ {56, 0x03, 171},
+ {3, 0x02, 206},
+ {6, 0x02, 206},
+ {10, 0x02, 206},
+ {15, 0x02, 206},
+ {24, 0x02, 206},
+ {31, 0x02, 206},
+ {41, 0x02, 206},
+ {56, 0x03, 206},
+ },
+ /* 184 */
+ {
+ {3, 0x02, 215},
+ {6, 0x02, 215},
+ {10, 0x02, 215},
+ {15, 0x02, 215},
+ {24, 0x02, 215},
+ {31, 0x02, 215},
+ {41, 0x02, 215},
+ {56, 0x03, 215},
+ {3, 0x02, 225},
+ {6, 0x02, 225},
+ {10, 0x02, 225},
+ {15, 0x02, 225},
+ {24, 0x02, 225},
+ {31, 0x02, 225},
+ {41, 0x02, 225},
+ {56, 0x03, 225},
+ },
+ /* 185 */
+ {
+ {2, 0x02, 236},
+ {9, 0x02, 236},
+ {23, 0x02, 236},
+ {40, 0x03, 236},
+ {2, 0x02, 237},
+ {9, 0x02, 237},
+ {23, 0x02, 237},
+ {40, 0x03, 237},
+ {1, 0x02, 199},
+ {22, 0x03, 199},
+ {1, 0x02, 207},
+ {22, 0x03, 207},
+ {1, 0x02, 234},
+ {22, 0x03, 234},
+ {1, 0x02, 235},
+ {22, 0x03, 235},
+ },
+ /* 186 */
+ {
+ {3, 0x02, 236},
+ {6, 0x02, 236},
+ {10, 0x02, 236},
+ {15, 0x02, 236},
+ {24, 0x02, 236},
+ {31, 0x02, 236},
+ {41, 0x02, 236},
+ {56, 0x03, 236},
+ {3, 0x02, 237},
+ {6, 0x02, 237},
+ {10, 0x02, 237},
+ {15, 0x02, 237},
+ {24, 0x02, 237},
+ {31, 0x02, 237},
+ {41, 0x02, 237},
+ {56, 0x03, 237},
+ },
+ /* 187 */
+ {
+ {2, 0x02, 199},
+ {9, 0x02, 199},
+ {23, 0x02, 199},
+ {40, 0x03, 199},
+ {2, 0x02, 207},
+ {9, 0x02, 207},
+ {23, 0x02, 207},
+ {40, 0x03, 207},
+ {2, 0x02, 234},
+ {9, 0x02, 234},
+ {23, 0x02, 234},
+ {40, 0x03, 234},
+ {2, 0x02, 235},
+ {9, 0x02, 235},
+ {23, 0x02, 235},
+ {40, 0x03, 235},
+ },
+ /* 188 */
+ {
+ {3, 0x02, 199},
+ {6, 0x02, 199},
+ {10, 0x02, 199},
+ {15, 0x02, 199},
+ {24, 0x02, 199},
+ {31, 0x02, 199},
+ {41, 0x02, 199},
+ {56, 0x03, 199},
+ {3, 0x02, 207},
+ {6, 0x02, 207},
+ {10, 0x02, 207},
+ {15, 0x02, 207},
+ {24, 0x02, 207},
+ {31, 0x02, 207},
+ {41, 0x02, 207},
+ {56, 0x03, 207},
+ },
+ /* 189 */
+ {
+ {3, 0x02, 234},
+ {6, 0x02, 234},
+ {10, 0x02, 234},
+ {15, 0x02, 234},
+ {24, 0x02, 234},
+ {31, 0x02, 234},
+ {41, 0x02, 234},
+ {56, 0x03, 234},
+ {3, 0x02, 235},
+ {6, 0x02, 235},
+ {10, 0x02, 235},
+ {15, 0x02, 235},
+ {24, 0x02, 235},
+ {31, 0x02, 235},
+ {41, 0x02, 235},
+ {56, 0x03, 235},
+ },
+ /* 190 */
+ {
+ {194, 0x00, 0},
+ {195, 0x00, 0},
+ {197, 0x00, 0},
+ {198, 0x00, 0},
+ {201, 0x00, 0},
+ {202, 0x00, 0},
+ {204, 0x00, 0},
+ {205, 0x00, 0},
+ {210, 0x00, 0},
+ {213, 0x00, 0},
+ {217, 0x00, 0},
+ {220, 0x00, 0},
+ {225, 0x00, 0},
+ {231, 0x00, 0},
+ {239, 0x00, 0},
+ {246, 0x00, 0},
+ },
+ /* 191 */
+ {
+ {0, 0x03, 192},
+ {0, 0x03, 193},
+ {0, 0x03, 200},
+ {0, 0x03, 201},
+ {0, 0x03, 202},
+ {0, 0x03, 205},
+ {0, 0x03, 210},
+ {0, 0x03, 213},
+ {0, 0x03, 218},
+ {0, 0x03, 219},
+ {0, 0x03, 238},
+ {0, 0x03, 240},
+ {0, 0x03, 242},
+ {0, 0x03, 243},
+ {0, 0x03, 255},
+ {206, 0x00, 0},
+ },
+ /* 192 */
+ {
+ {1, 0x02, 192},
+ {22, 0x03, 192},
+ {1, 0x02, 193},
+ {22, 0x03, 193},
+ {1, 0x02, 200},
+ {22, 0x03, 200},
+ {1, 0x02, 201},
+ {22, 0x03, 201},
+ {1, 0x02, 202},
+ {22, 0x03, 202},
+ {1, 0x02, 205},
+ {22, 0x03, 205},
+ {1, 0x02, 210},
+ {22, 0x03, 210},
+ {1, 0x02, 213},
+ {22, 0x03, 213},
+ },
+ /* 193 */
+ {
+ {2, 0x02, 192},
+ {9, 0x02, 192},
+ {23, 0x02, 192},
+ {40, 0x03, 192},
+ {2, 0x02, 193},
+ {9, 0x02, 193},
+ {23, 0x02, 193},
+ {40, 0x03, 193},
+ {2, 0x02, 200},
+ {9, 0x02, 200},
+ {23, 0x02, 200},
+ {40, 0x03, 200},
+ {2, 0x02, 201},
+ {9, 0x02, 201},
+ {23, 0x02, 201},
+ {40, 0x03, 201},
+ },
+ /* 194 */
+ {
+ {3, 0x02, 192},
+ {6, 0x02, 192},
+ {10, 0x02, 192},
+ {15, 0x02, 192},
+ {24, 0x02, 192},
+ {31, 0x02, 192},
+ {41, 0x02, 192},
+ {56, 0x03, 192},
+ {3, 0x02, 193},
+ {6, 0x02, 193},
+ {10, 0x02, 193},
+ {15, 0x02, 193},
+ {24, 0x02, 193},
+ {31, 0x02, 193},
+ {41, 0x02, 193},
+ {56, 0x03, 193},
+ },
+ /* 195 */
+ {
+ {3, 0x02, 200},
+ {6, 0x02, 200},
+ {10, 0x02, 200},
+ {15, 0x02, 200},
+ {24, 0x02, 200},
+ {31, 0x02, 200},
+ {41, 0x02, 200},
+ {56, 0x03, 200},
+ {3, 0x02, 201},
+ {6, 0x02, 201},
+ {10, 0x02, 201},
+ {15, 0x02, 201},
+ {24, 0x02, 201},
+ {31, 0x02, 201},
+ {41, 0x02, 201},
+ {56, 0x03, 201},
+ },
+ /* 196 */
+ {
+ {2, 0x02, 202},
+ {9, 0x02, 202},
+ {23, 0x02, 202},
+ {40, 0x03, 202},
+ {2, 0x02, 205},
+ {9, 0x02, 205},
+ {23, 0x02, 205},
+ {40, 0x03, 205},
+ {2, 0x02, 210},
+ {9, 0x02, 210},
+ {23, 0x02, 210},
+ {40, 0x03, 210},
+ {2, 0x02, 213},
+ {9, 0x02, 213},
+ {23, 0x02, 213},
+ {40, 0x03, 213},
+ },
+ /* 197 */
+ {
+ {3, 0x02, 202},
+ {6, 0x02, 202},
+ {10, 0x02, 202},
+ {15, 0x02, 202},
+ {24, 0x02, 202},
+ {31, 0x02, 202},
+ {41, 0x02, 202},
+ {56, 0x03, 202},
+ {3, 0x02, 205},
+ {6, 0x02, 205},
+ {10, 0x02, 205},
+ {15, 0x02, 205},
+ {24, 0x02, 205},
+ {31, 0x02, 205},
+ {41, 0x02, 205},
+ {56, 0x03, 205},
+ },
+ /* 198 */
+ {
+ {3, 0x02, 210},
+ {6, 0x02, 210},
+ {10, 0x02, 210},
+ {15, 0x02, 210},
+ {24, 0x02, 210},
+ {31, 0x02, 210},
+ {41, 0x02, 210},
+ {56, 0x03, 210},
+ {3, 0x02, 213},
+ {6, 0x02, 213},
+ {10, 0x02, 213},
+ {15, 0x02, 213},
+ {24, 0x02, 213},
+ {31, 0x02, 213},
+ {41, 0x02, 213},
+ {56, 0x03, 213},
+ },
+ /* 199 */
+ {
+ {1, 0x02, 218},
+ {22, 0x03, 218},
+ {1, 0x02, 219},
+ {22, 0x03, 219},
+ {1, 0x02, 238},
+ {22, 0x03, 238},
+ {1, 0x02, 240},
+ {22, 0x03, 240},
+ {1, 0x02, 242},
+ {22, 0x03, 242},
+ {1, 0x02, 243},
+ {22, 0x03, 243},
+ {1, 0x02, 255},
+ {22, 0x03, 255},
+ {0, 0x03, 203},
+ {0, 0x03, 204},
+ },
+ /* 200 */
+ {
+ {2, 0x02, 218},
+ {9, 0x02, 218},
+ {23, 0x02, 218},
+ {40, 0x03, 218},
+ {2, 0x02, 219},
+ {9, 0x02, 219},
+ {23, 0x02, 219},
+ {40, 0x03, 219},
+ {2, 0x02, 238},
+ {9, 0x02, 238},
+ {23, 0x02, 238},
+ {40, 0x03, 238},
+ {2, 0x02, 240},
+ {9, 0x02, 240},
+ {23, 0x02, 240},
+ {40, 0x03, 240},
+ },
+ /* 201 */
+ {
+ {3, 0x02, 218},
+ {6, 0x02, 218},
+ {10, 0x02, 218},
+ {15, 0x02, 218},
+ {24, 0x02, 218},
+ {31, 0x02, 218},
+ {41, 0x02, 218},
+ {56, 0x03, 218},
+ {3, 0x02, 219},
+ {6, 0x02, 219},
+ {10, 0x02, 219},
+ {15, 0x02, 219},
+ {24, 0x02, 219},
+ {31, 0x02, 219},
+ {41, 0x02, 219},
+ {56, 0x03, 219},
+ },
+ /* 202 */
+ {
+ {3, 0x02, 238},
+ {6, 0x02, 238},
+ {10, 0x02, 238},
+ {15, 0x02, 238},
+ {24, 0x02, 238},
+ {31, 0x02, 238},
+ {41, 0x02, 238},
+ {56, 0x03, 238},
+ {3, 0x02, 240},
+ {6, 0x02, 240},
+ {10, 0x02, 240},
+ {15, 0x02, 240},
+ {24, 0x02, 240},
+ {31, 0x02, 240},
+ {41, 0x02, 240},
+ {56, 0x03, 240},
+ },
+ /* 203 */
+ {
+ {2, 0x02, 242},
+ {9, 0x02, 242},
+ {23, 0x02, 242},
+ {40, 0x03, 242},
+ {2, 0x02, 243},
+ {9, 0x02, 243},
+ {23, 0x02, 243},
+ {40, 0x03, 243},
+ {2, 0x02, 255},
+ {9, 0x02, 255},
+ {23, 0x02, 255},
+ {40, 0x03, 255},
+ {1, 0x02, 203},
+ {22, 0x03, 203},
+ {1, 0x02, 204},
+ {22, 0x03, 204},
+ },
+ /* 204 */
+ {
+ {3, 0x02, 242},
+ {6, 0x02, 242},
+ {10, 0x02, 242},
+ {15, 0x02, 242},
+ {24, 0x02, 242},
+ {31, 0x02, 242},
+ {41, 0x02, 242},
+ {56, 0x03, 242},
+ {3, 0x02, 243},
+ {6, 0x02, 243},
+ {10, 0x02, 243},
+ {15, 0x02, 243},
+ {24, 0x02, 243},
+ {31, 0x02, 243},
+ {41, 0x02, 243},
+ {56, 0x03, 243},
+ },
+ /* 205 */
+ {
+ {3, 0x02, 255},
+ {6, 0x02, 255},
+ {10, 0x02, 255},
+ {15, 0x02, 255},
+ {24, 0x02, 255},
+ {31, 0x02, 255},
+ {41, 0x02, 255},
+ {56, 0x03, 255},
+ {2, 0x02, 203},
+ {9, 0x02, 203},
+ {23, 0x02, 203},
+ {40, 0x03, 203},
+ {2, 0x02, 204},
+ {9, 0x02, 204},
+ {23, 0x02, 204},
+ {40, 0x03, 204},
+ },
+ /* 206 */
+ {
+ {3, 0x02, 203},
+ {6, 0x02, 203},
+ {10, 0x02, 203},
+ {15, 0x02, 203},
+ {24, 0x02, 203},
+ {31, 0x02, 203},
+ {41, 0x02, 203},
+ {56, 0x03, 203},
+ {3, 0x02, 204},
+ {6, 0x02, 204},
+ {10, 0x02, 204},
+ {15, 0x02, 204},
+ {24, 0x02, 204},
+ {31, 0x02, 204},
+ {41, 0x02, 204},
+ {56, 0x03, 204},
+ },
+ /* 207 */
+ {
+ {211, 0x00, 0},
+ {212, 0x00, 0},
+ {214, 0x00, 0},
+ {215, 0x00, 0},
+ {218, 0x00, 0},
+ {219, 0x00, 0},
+ {221, 0x00, 0},
+ {222, 0x00, 0},
+ {226, 0x00, 0},
+ {228, 0x00, 0},
+ {232, 0x00, 0},
+ {235, 0x00, 0},
+ {240, 0x00, 0},
+ {243, 0x00, 0},
+ {247, 0x00, 0},
+ {250, 0x00, 0},
+ },
+ /* 208 */
+ {
+ {0, 0x03, 211},
+ {0, 0x03, 212},
+ {0, 0x03, 214},
+ {0, 0x03, 221},
+ {0, 0x03, 222},
+ {0, 0x03, 223},
+ {0, 0x03, 241},
+ {0, 0x03, 244},
+ {0, 0x03, 245},
+ {0, 0x03, 246},
+ {0, 0x03, 247},
+ {0, 0x03, 248},
+ {0, 0x03, 250},
+ {0, 0x03, 251},
+ {0, 0x03, 252},
+ {0, 0x03, 253},
+ },
+ /* 209 */
+ {
+ {1, 0x02, 211},
+ {22, 0x03, 211},
+ {1, 0x02, 212},
+ {22, 0x03, 212},
+ {1, 0x02, 214},
+ {22, 0x03, 214},
+ {1, 0x02, 221},
+ {22, 0x03, 221},
+ {1, 0x02, 222},
+ {22, 0x03, 222},
+ {1, 0x02, 223},
+ {22, 0x03, 223},
+ {1, 0x02, 241},
+ {22, 0x03, 241},
+ {1, 0x02, 244},
+ {22, 0x03, 244},
+ },
+ /* 210 */
+ {
+ {2, 0x02, 211},
+ {9, 0x02, 211},
+ {23, 0x02, 211},
+ {40, 0x03, 211},
+ {2, 0x02, 212},
+ {9, 0x02, 212},
+ {23, 0x02, 212},
+ {40, 0x03, 212},
+ {2, 0x02, 214},
+ {9, 0x02, 214},
+ {23, 0x02, 214},
+ {40, 0x03, 214},
+ {2, 0x02, 221},
+ {9, 0x02, 221},
+ {23, 0x02, 221},
+ {40, 0x03, 221},
+ },
+ /* 211 */
+ {
+ {3, 0x02, 211},
+ {6, 0x02, 211},
+ {10, 0x02, 211},
+ {15, 0x02, 211},
+ {24, 0x02, 211},
+ {31, 0x02, 211},
+ {41, 0x02, 211},
+ {56, 0x03, 211},
+ {3, 0x02, 212},
+ {6, 0x02, 212},
+ {10, 0x02, 212},
+ {15, 0x02, 212},
+ {24, 0x02, 212},
+ {31, 0x02, 212},
+ {41, 0x02, 212},
+ {56, 0x03, 212},
+ },
+ /* 212 */
+ {
+ {3, 0x02, 214},
+ {6, 0x02, 214},
+ {10, 0x02, 214},
+ {15, 0x02, 214},
+ {24, 0x02, 214},
+ {31, 0x02, 214},
+ {41, 0x02, 214},
+ {56, 0x03, 214},
+ {3, 0x02, 221},
+ {6, 0x02, 221},
+ {10, 0x02, 221},
+ {15, 0x02, 221},
+ {24, 0x02, 221},
+ {31, 0x02, 221},
+ {41, 0x02, 221},
+ {56, 0x03, 221},
+ },
+ /* 213 */
+ {
+ {2, 0x02, 222},
+ {9, 0x02, 222},
+ {23, 0x02, 222},
+ {40, 0x03, 222},
+ {2, 0x02, 223},
+ {9, 0x02, 223},
+ {23, 0x02, 223},
+ {40, 0x03, 223},
+ {2, 0x02, 241},
+ {9, 0x02, 241},
+ {23, 0x02, 241},
+ {40, 0x03, 241},
+ {2, 0x02, 244},
+ {9, 0x02, 244},
+ {23, 0x02, 244},
+ {40, 0x03, 244},
+ },
+ /* 214 */
+ {
+ {3, 0x02, 222},
+ {6, 0x02, 222},
+ {10, 0x02, 222},
+ {15, 0x02, 222},
+ {24, 0x02, 222},
+ {31, 0x02, 222},
+ {41, 0x02, 222},
+ {56, 0x03, 222},
+ {3, 0x02, 223},
+ {6, 0x02, 223},
+ {10, 0x02, 223},
+ {15, 0x02, 223},
+ {24, 0x02, 223},
+ {31, 0x02, 223},
+ {41, 0x02, 223},
+ {56, 0x03, 223},
+ },
+ /* 215 */
+ {
+ {3, 0x02, 241},
+ {6, 0x02, 241},
+ {10, 0x02, 241},
+ {15, 0x02, 241},
+ {24, 0x02, 241},
+ {31, 0x02, 241},
+ {41, 0x02, 241},
+ {56, 0x03, 241},
+ {3, 0x02, 244},
+ {6, 0x02, 244},
+ {10, 0x02, 244},
+ {15, 0x02, 244},
+ {24, 0x02, 244},
+ {31, 0x02, 244},
+ {41, 0x02, 244},
+ {56, 0x03, 244},
+ },
+ /* 216 */
+ {
+ {1, 0x02, 245},
+ {22, 0x03, 245},
+ {1, 0x02, 246},
+ {22, 0x03, 246},
+ {1, 0x02, 247},
+ {22, 0x03, 247},
+ {1, 0x02, 248},
+ {22, 0x03, 248},
+ {1, 0x02, 250},
+ {22, 0x03, 250},
+ {1, 0x02, 251},
+ {22, 0x03, 251},
+ {1, 0x02, 252},
+ {22, 0x03, 252},
+ {1, 0x02, 253},
+ {22, 0x03, 253},
+ },
+ /* 217 */
+ {
+ {2, 0x02, 245},
+ {9, 0x02, 245},
+ {23, 0x02, 245},
+ {40, 0x03, 245},
+ {2, 0x02, 246},
+ {9, 0x02, 246},
+ {23, 0x02, 246},
+ {40, 0x03, 246},
+ {2, 0x02, 247},
+ {9, 0x02, 247},
+ {23, 0x02, 247},
+ {40, 0x03, 247},
+ {2, 0x02, 248},
+ {9, 0x02, 248},
+ {23, 0x02, 248},
+ {40, 0x03, 248},
+ },
+ /* 218 */
+ {
+ {3, 0x02, 245},
+ {6, 0x02, 245},
+ {10, 0x02, 245},
+ {15, 0x02, 245},
+ {24, 0x02, 245},
+ {31, 0x02, 245},
+ {41, 0x02, 245},
+ {56, 0x03, 245},
+ {3, 0x02, 246},
+ {6, 0x02, 246},
+ {10, 0x02, 246},
+ {15, 0x02, 246},
+ {24, 0x02, 246},
+ {31, 0x02, 246},
+ {41, 0x02, 246},
+ {56, 0x03, 246},
+ },
+ /* 219 */
+ {
+ {3, 0x02, 247},
+ {6, 0x02, 247},
+ {10, 0x02, 247},
+ {15, 0x02, 247},
+ {24, 0x02, 247},
+ {31, 0x02, 247},
+ {41, 0x02, 247},
+ {56, 0x03, 247},
+ {3, 0x02, 248},
+ {6, 0x02, 248},
+ {10, 0x02, 248},
+ {15, 0x02, 248},
+ {24, 0x02, 248},
+ {31, 0x02, 248},
+ {41, 0x02, 248},
+ {56, 0x03, 248},
+ },
+ /* 220 */
+ {
+ {2, 0x02, 250},
+ {9, 0x02, 250},
+ {23, 0x02, 250},
+ {40, 0x03, 250},
+ {2, 0x02, 251},
+ {9, 0x02, 251},
+ {23, 0x02, 251},
+ {40, 0x03, 251},
+ {2, 0x02, 252},
+ {9, 0x02, 252},
+ {23, 0x02, 252},
+ {40, 0x03, 252},
+ {2, 0x02, 253},
+ {9, 0x02, 253},
+ {23, 0x02, 253},
+ {40, 0x03, 253},
+ },
+ /* 221 */
+ {
+ {3, 0x02, 250},
+ {6, 0x02, 250},
+ {10, 0x02, 250},
+ {15, 0x02, 250},
+ {24, 0x02, 250},
+ {31, 0x02, 250},
+ {41, 0x02, 250},
+ {56, 0x03, 250},
+ {3, 0x02, 251},
+ {6, 0x02, 251},
+ {10, 0x02, 251},
+ {15, 0x02, 251},
+ {24, 0x02, 251},
+ {31, 0x02, 251},
+ {41, 0x02, 251},
+ {56, 0x03, 251},
+ },
+ /* 222 */
+ {
+ {3, 0x02, 252},
+ {6, 0x02, 252},
+ {10, 0x02, 252},
+ {15, 0x02, 252},
+ {24, 0x02, 252},
+ {31, 0x02, 252},
+ {41, 0x02, 252},
+ {56, 0x03, 252},
+ {3, 0x02, 253},
+ {6, 0x02, 253},
+ {10, 0x02, 253},
+ {15, 0x02, 253},
+ {24, 0x02, 253},
+ {31, 0x02, 253},
+ {41, 0x02, 253},
+ {56, 0x03, 253},
+ },
+ /* 223 */
+ {
+ {0, 0x03, 254},
+ {227, 0x00, 0},
+ {229, 0x00, 0},
+ {230, 0x00, 0},
+ {233, 0x00, 0},
+ {234, 0x00, 0},
+ {236, 0x00, 0},
+ {237, 0x00, 0},
+ {241, 0x00, 0},
+ {242, 0x00, 0},
+ {244, 0x00, 0},
+ {245, 0x00, 0},
+ {248, 0x00, 0},
+ {249, 0x00, 0},
+ {251, 0x00, 0},
+ {252, 0x00, 0},
+ },
+ /* 224 */
+ {
+ {1, 0x02, 254},
+ {22, 0x03, 254},
+ {0, 0x03, 2},
+ {0, 0x03, 3},
+ {0, 0x03, 4},
+ {0, 0x03, 5},
+ {0, 0x03, 6},
+ {0, 0x03, 7},
+ {0, 0x03, 8},
+ {0, 0x03, 11},
+ {0, 0x03, 12},
+ {0, 0x03, 14},
+ {0, 0x03, 15},
+ {0, 0x03, 16},
+ {0, 0x03, 17},
+ {0, 0x03, 18},
+ },
+ /* 225 */
+ {
+ {2, 0x02, 254},
+ {9, 0x02, 254},
+ {23, 0x02, 254},
+ {40, 0x03, 254},
+ {1, 0x02, 2},
+ {22, 0x03, 2},
+ {1, 0x02, 3},
+ {22, 0x03, 3},
+ {1, 0x02, 4},
+ {22, 0x03, 4},
+ {1, 0x02, 5},
+ {22, 0x03, 5},
+ {1, 0x02, 6},
+ {22, 0x03, 6},
+ {1, 0x02, 7},
+ {22, 0x03, 7},
+ },
+ /* 226 */
+ {
+ {3, 0x02, 254},
+ {6, 0x02, 254},
+ {10, 0x02, 254},
+ {15, 0x02, 254},
+ {24, 0x02, 254},
+ {31, 0x02, 254},
+ {41, 0x02, 254},
+ {56, 0x03, 254},
+ {2, 0x02, 2},
+ {9, 0x02, 2},
+ {23, 0x02, 2},
+ {40, 0x03, 2},
+ {2, 0x02, 3},
+ {9, 0x02, 3},
+ {23, 0x02, 3},
+ {40, 0x03, 3},
+ },
+ /* 227 */
+ {
+ {3, 0x02, 2},
+ {6, 0x02, 2},
+ {10, 0x02, 2},
+ {15, 0x02, 2},
+ {24, 0x02, 2},
+ {31, 0x02, 2},
+ {41, 0x02, 2},
+ {56, 0x03, 2},
+ {3, 0x02, 3},
+ {6, 0x02, 3},
+ {10, 0x02, 3},
+ {15, 0x02, 3},
+ {24, 0x02, 3},
+ {31, 0x02, 3},
+ {41, 0x02, 3},
+ {56, 0x03, 3},
+ },
+ /* 228 */
+ {
+ {2, 0x02, 4},
+ {9, 0x02, 4},
+ {23, 0x02, 4},
+ {40, 0x03, 4},
+ {2, 0x02, 5},
+ {9, 0x02, 5},
+ {23, 0x02, 5},
+ {40, 0x03, 5},
+ {2, 0x02, 6},
+ {9, 0x02, 6},
+ {23, 0x02, 6},
+ {40, 0x03, 6},
+ {2, 0x02, 7},
+ {9, 0x02, 7},
+ {23, 0x02, 7},
+ {40, 0x03, 7},
+ },
+ /* 229 */
+ {
+ {3, 0x02, 4},
+ {6, 0x02, 4},
+ {10, 0x02, 4},
+ {15, 0x02, 4},
+ {24, 0x02, 4},
+ {31, 0x02, 4},
+ {41, 0x02, 4},
+ {56, 0x03, 4},
+ {3, 0x02, 5},
+ {6, 0x02, 5},
+ {10, 0x02, 5},
+ {15, 0x02, 5},
+ {24, 0x02, 5},
+ {31, 0x02, 5},
+ {41, 0x02, 5},
+ {56, 0x03, 5},
+ },
+ /* 230 */
+ {
+ {3, 0x02, 6},
+ {6, 0x02, 6},
+ {10, 0x02, 6},
+ {15, 0x02, 6},
+ {24, 0x02, 6},
+ {31, 0x02, 6},
+ {41, 0x02, 6},
+ {56, 0x03, 6},
+ {3, 0x02, 7},
+ {6, 0x02, 7},
+ {10, 0x02, 7},
+ {15, 0x02, 7},
+ {24, 0x02, 7},
+ {31, 0x02, 7},
+ {41, 0x02, 7},
+ {56, 0x03, 7},
+ },
+ /* 231 */
+ {
+ {1, 0x02, 8},
+ {22, 0x03, 8},
+ {1, 0x02, 11},
+ {22, 0x03, 11},
+ {1, 0x02, 12},
+ {22, 0x03, 12},
+ {1, 0x02, 14},
+ {22, 0x03, 14},
+ {1, 0x02, 15},
+ {22, 0x03, 15},
+ {1, 0x02, 16},
+ {22, 0x03, 16},
+ {1, 0x02, 17},
+ {22, 0x03, 17},
+ {1, 0x02, 18},
+ {22, 0x03, 18},
+ },
+ /* 232 */
+ {
+ {2, 0x02, 8},
+ {9, 0x02, 8},
+ {23, 0x02, 8},
+ {40, 0x03, 8},
+ {2, 0x02, 11},
+ {9, 0x02, 11},
+ {23, 0x02, 11},
+ {40, 0x03, 11},
+ {2, 0x02, 12},
+ {9, 0x02, 12},
+ {23, 0x02, 12},
+ {40, 0x03, 12},
+ {2, 0x02, 14},
+ {9, 0x02, 14},
+ {23, 0x02, 14},
+ {40, 0x03, 14},
+ },
+ /* 233 */
+ {
+ {3, 0x02, 8},
+ {6, 0x02, 8},
+ {10, 0x02, 8},
+ {15, 0x02, 8},
+ {24, 0x02, 8},
+ {31, 0x02, 8},
+ {41, 0x02, 8},
+ {56, 0x03, 8},
+ {3, 0x02, 11},
+ {6, 0x02, 11},
+ {10, 0x02, 11},
+ {15, 0x02, 11},
+ {24, 0x02, 11},
+ {31, 0x02, 11},
+ {41, 0x02, 11},
+ {56, 0x03, 11},
+ },
+ /* 234 */
+ {
+ {3, 0x02, 12},
+ {6, 0x02, 12},
+ {10, 0x02, 12},
+ {15, 0x02, 12},
+ {24, 0x02, 12},
+ {31, 0x02, 12},
+ {41, 0x02, 12},
+ {56, 0x03, 12},
+ {3, 0x02, 14},
+ {6, 0x02, 14},
+ {10, 0x02, 14},
+ {15, 0x02, 14},
+ {24, 0x02, 14},
+ {31, 0x02, 14},
+ {41, 0x02, 14},
+ {56, 0x03, 14},
+ },
+ /* 235 */
+ {
+ {2, 0x02, 15},
+ {9, 0x02, 15},
+ {23, 0x02, 15},
+ {40, 0x03, 15},
+ {2, 0x02, 16},
+ {9, 0x02, 16},
+ {23, 0x02, 16},
+ {40, 0x03, 16},
+ {2, 0x02, 17},
+ {9, 0x02, 17},
+ {23, 0x02, 17},
+ {40, 0x03, 17},
+ {2, 0x02, 18},
+ {9, 0x02, 18},
+ {23, 0x02, 18},
+ {40, 0x03, 18},
+ },
+ /* 236 */
+ {
+ {3, 0x02, 15},
+ {6, 0x02, 15},
+ {10, 0x02, 15},
+ {15, 0x02, 15},
+ {24, 0x02, 15},
+ {31, 0x02, 15},
+ {41, 0x02, 15},
+ {56, 0x03, 15},
+ {3, 0x02, 16},
+ {6, 0x02, 16},
+ {10, 0x02, 16},
+ {15, 0x02, 16},
+ {24, 0x02, 16},
+ {31, 0x02, 16},
+ {41, 0x02, 16},
+ {56, 0x03, 16},
+ },
+ /* 237 */
+ {
+ {3, 0x02, 17},
+ {6, 0x02, 17},
+ {10, 0x02, 17},
+ {15, 0x02, 17},
+ {24, 0x02, 17},
+ {31, 0x02, 17},
+ {41, 0x02, 17},
+ {56, 0x03, 17},
+ {3, 0x02, 18},
+ {6, 0x02, 18},
+ {10, 0x02, 18},
+ {15, 0x02, 18},
+ {24, 0x02, 18},
+ {31, 0x02, 18},
+ {41, 0x02, 18},
+ {56, 0x03, 18},
+ },
+ /* 238 */
+ {
+ {0, 0x03, 19},
+ {0, 0x03, 20},
+ {0, 0x03, 21},
+ {0, 0x03, 23},
+ {0, 0x03, 24},
+ {0, 0x03, 25},
+ {0, 0x03, 26},
+ {0, 0x03, 27},
+ {0, 0x03, 28},
+ {0, 0x03, 29},
+ {0, 0x03, 30},
+ {0, 0x03, 31},
+ {0, 0x03, 127},
+ {0, 0x03, 220},
+ {0, 0x03, 249},
+ {253, 0x00, 0},
+ },
+ /* 239 */
+ {
+ {1, 0x02, 19},
+ {22, 0x03, 19},
+ {1, 0x02, 20},
+ {22, 0x03, 20},
+ {1, 0x02, 21},
+ {22, 0x03, 21},
+ {1, 0x02, 23},
+ {22, 0x03, 23},
+ {1, 0x02, 24},
+ {22, 0x03, 24},
+ {1, 0x02, 25},
+ {22, 0x03, 25},
+ {1, 0x02, 26},
+ {22, 0x03, 26},
+ {1, 0x02, 27},
+ {22, 0x03, 27},
+ },
+ /* 240 */
+ {
+ {2, 0x02, 19},
+ {9, 0x02, 19},
+ {23, 0x02, 19},
+ {40, 0x03, 19},
+ {2, 0x02, 20},
+ {9, 0x02, 20},
+ {23, 0x02, 20},
+ {40, 0x03, 20},
+ {2, 0x02, 21},
+ {9, 0x02, 21},
+ {23, 0x02, 21},
+ {40, 0x03, 21},
+ {2, 0x02, 23},
+ {9, 0x02, 23},
+ {23, 0x02, 23},
+ {40, 0x03, 23},
+ },
+ /* 241 */
+ {
+ {3, 0x02, 19},
+ {6, 0x02, 19},
+ {10, 0x02, 19},
+ {15, 0x02, 19},
+ {24, 0x02, 19},
+ {31, 0x02, 19},
+ {41, 0x02, 19},
+ {56, 0x03, 19},
+ {3, 0x02, 20},
+ {6, 0x02, 20},
+ {10, 0x02, 20},
+ {15, 0x02, 20},
+ {24, 0x02, 20},
+ {31, 0x02, 20},
+ {41, 0x02, 20},
+ {56, 0x03, 20},
+ },
+ /* 242 */
+ {
+ {3, 0x02, 21},
+ {6, 0x02, 21},
+ {10, 0x02, 21},
+ {15, 0x02, 21},
+ {24, 0x02, 21},
+ {31, 0x02, 21},
+ {41, 0x02, 21},
+ {56, 0x03, 21},
+ {3, 0x02, 23},
+ {6, 0x02, 23},
+ {10, 0x02, 23},
+ {15, 0x02, 23},
+ {24, 0x02, 23},
+ {31, 0x02, 23},
+ {41, 0x02, 23},
+ {56, 0x03, 23},
+ },
+ /* 243 */
+ {
+ {2, 0x02, 24},
+ {9, 0x02, 24},
+ {23, 0x02, 24},
+ {40, 0x03, 24},
+ {2, 0x02, 25},
+ {9, 0x02, 25},
+ {23, 0x02, 25},
+ {40, 0x03, 25},
+ {2, 0x02, 26},
+ {9, 0x02, 26},
+ {23, 0x02, 26},
+ {40, 0x03, 26},
+ {2, 0x02, 27},
+ {9, 0x02, 27},
+ {23, 0x02, 27},
+ {40, 0x03, 27},
+ },
+ /* 244 */
+ {
+ {3, 0x02, 24},
+ {6, 0x02, 24},
+ {10, 0x02, 24},
+ {15, 0x02, 24},
+ {24, 0x02, 24},
+ {31, 0x02, 24},
+ {41, 0x02, 24},
+ {56, 0x03, 24},
+ {3, 0x02, 25},
+ {6, 0x02, 25},
+ {10, 0x02, 25},
+ {15, 0x02, 25},
+ {24, 0x02, 25},
+ {31, 0x02, 25},
+ {41, 0x02, 25},
+ {56, 0x03, 25},
+ },
+ /* 245 */
+ {
+ {3, 0x02, 26},
+ {6, 0x02, 26},
+ {10, 0x02, 26},
+ {15, 0x02, 26},
+ {24, 0x02, 26},
+ {31, 0x02, 26},
+ {41, 0x02, 26},
+ {56, 0x03, 26},
+ {3, 0x02, 27},
+ {6, 0x02, 27},
+ {10, 0x02, 27},
+ {15, 0x02, 27},
+ {24, 0x02, 27},
+ {31, 0x02, 27},
+ {41, 0x02, 27},
+ {56, 0x03, 27},
+ },
+ /* 246 */
+ {
+ {1, 0x02, 28},
+ {22, 0x03, 28},
+ {1, 0x02, 29},
+ {22, 0x03, 29},
+ {1, 0x02, 30},
+ {22, 0x03, 30},
+ {1, 0x02, 31},
+ {22, 0x03, 31},
+ {1, 0x02, 127},
+ {22, 0x03, 127},
+ {1, 0x02, 220},
+ {22, 0x03, 220},
+ {1, 0x02, 249},
+ {22, 0x03, 249},
+ {254, 0x00, 0},
+ {255, 0x00, 0},
+ },
+ /* 247 */
+ {
+ {2, 0x02, 28},
+ {9, 0x02, 28},
+ {23, 0x02, 28},
+ {40, 0x03, 28},
+ {2, 0x02, 29},
+ {9, 0x02, 29},
+ {23, 0x02, 29},
+ {40, 0x03, 29},
+ {2, 0x02, 30},
+ {9, 0x02, 30},
+ {23, 0x02, 30},
+ {40, 0x03, 30},
+ {2, 0x02, 31},
+ {9, 0x02, 31},
+ {23, 0x02, 31},
+ {40, 0x03, 31},
+ },
+ /* 248 */
+ {
+ {3, 0x02, 28},
+ {6, 0x02, 28},
+ {10, 0x02, 28},
+ {15, 0x02, 28},
+ {24, 0x02, 28},
+ {31, 0x02, 28},
+ {41, 0x02, 28},
+ {56, 0x03, 28},
+ {3, 0x02, 29},
+ {6, 0x02, 29},
+ {10, 0x02, 29},
+ {15, 0x02, 29},
+ {24, 0x02, 29},
+ {31, 0x02, 29},
+ {41, 0x02, 29},
+ {56, 0x03, 29},
+ },
+ /* 249 */
+ {
+ {3, 0x02, 30},
+ {6, 0x02, 30},
+ {10, 0x02, 30},
+ {15, 0x02, 30},
+ {24, 0x02, 30},
+ {31, 0x02, 30},
+ {41, 0x02, 30},
+ {56, 0x03, 30},
+ {3, 0x02, 31},
+ {6, 0x02, 31},
+ {10, 0x02, 31},
+ {15, 0x02, 31},
+ {24, 0x02, 31},
+ {31, 0x02, 31},
+ {41, 0x02, 31},
+ {56, 0x03, 31},
+ },
+ /* 250 */
+ {
+ {2, 0x02, 127},
+ {9, 0x02, 127},
+ {23, 0x02, 127},
+ {40, 0x03, 127},
+ {2, 0x02, 220},
+ {9, 0x02, 220},
+ {23, 0x02, 220},
+ {40, 0x03, 220},
+ {2, 0x02, 249},
+ {9, 0x02, 249},
+ {23, 0x02, 249},
+ {40, 0x03, 249},
+ {0, 0x03, 10},
+ {0, 0x03, 13},
+ {0, 0x03, 22},
+ {0, 0x04, 0},
+ },
+ /* 251 */
+ {
+ {3, 0x02, 127},
+ {6, 0x02, 127},
+ {10, 0x02, 127},
+ {15, 0x02, 127},
+ {24, 0x02, 127},
+ {31, 0x02, 127},
+ {41, 0x02, 127},
+ {56, 0x03, 127},
+ {3, 0x02, 220},
+ {6, 0x02, 220},
+ {10, 0x02, 220},
+ {15, 0x02, 220},
+ {24, 0x02, 220},
+ {31, 0x02, 220},
+ {41, 0x02, 220},
+ {56, 0x03, 220},
+ },
+ /* 252 */
+ {
+ {3, 0x02, 249},
+ {6, 0x02, 249},
+ {10, 0x02, 249},
+ {15, 0x02, 249},
+ {24, 0x02, 249},
+ {31, 0x02, 249},
+ {41, 0x02, 249},
+ {56, 0x03, 249},
+ {1, 0x02, 10},
+ {22, 0x03, 10},
+ {1, 0x02, 13},
+ {22, 0x03, 13},
+ {1, 0x02, 22},
+ {22, 0x03, 22},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ },
+ /* 253 */
+ {
+ {2, 0x02, 10},
+ {9, 0x02, 10},
+ {23, 0x02, 10},
+ {40, 0x03, 10},
+ {2, 0x02, 13},
+ {9, 0x02, 13},
+ {23, 0x02, 13},
+ {40, 0x03, 13},
+ {2, 0x02, 22},
+ {9, 0x02, 22},
+ {23, 0x02, 22},
+ {40, 0x03, 22},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ },
+ /* 254 */
+ {
+ {3, 0x02, 10},
+ {6, 0x02, 10},
+ {10, 0x02, 10},
+ {15, 0x02, 10},
+ {24, 0x02, 10},
+ {31, 0x02, 10},
+ {41, 0x02, 10},
+ {56, 0x03, 10},
+ {3, 0x02, 13},
+ {6, 0x02, 13},
+ {10, 0x02, 13},
+ {15, 0x02, 13},
+ {24, 0x02, 13},
+ {31, 0x02, 13},
+ {41, 0x02, 13},
+ {56, 0x03, 13},
+ },
+ /* 255 */
+ {
+ {3, 0x02, 22},
+ {6, 0x02, 22},
+ {10, 0x02, 22},
+ {15, 0x02, 22},
+ {24, 0x02, 22},
+ {31, 0x02, 22},
+ {41, 0x02, 22},
+ {56, 0x03, 22},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ },
+};
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_helper.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_helper.c
new file mode 100644
index 00000000..8d80eb98
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_helper.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_helper.h"
+
+#include
+#include
+
+#include "nghttp2_net.h"
+
+void nghttp2_put_uint16be(uint8_t *buf, uint16_t n) {
+ uint16_t x = nghttp2_htons(n);
+ memcpy(buf, &x, sizeof(uint16_t));
+}
+
+void nghttp2_put_uint32be(uint8_t *buf, uint32_t n) {
+ uint32_t x = nghttp2_htonl(n);
+ memcpy(buf, &x, sizeof(uint32_t));
+}
+
+uint16_t nghttp2_get_uint16(const uint8_t *data) {
+ uint16_t n;
+ memcpy(&n, data, sizeof(uint16_t));
+ return nghttp2_ntohs(n);
+}
+
+uint32_t nghttp2_get_uint32(const uint8_t *data) {
+ uint32_t n;
+ memcpy(&n, data, sizeof(uint32_t));
+ return nghttp2_ntohl(n);
+}
+
+/* Generated by gendowncasetbl.py */
+static const uint8_t DOWNCASE_TBL[] = {
+ 0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
+ 4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
+ 8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
+ 12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
+ 16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
+ 20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
+ 24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
+ 28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
+ 32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
+ 36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
+ 40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
+ 44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
+ 48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
+ 52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
+ 56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
+ 60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
+ 64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
+ 100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
+ 104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
+ 108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
+ 112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
+ 116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
+ 120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
+ 92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
+ 96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
+ 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
+ 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
+ 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
+ 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
+ 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
+ 120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
+ 124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
+ 128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
+ 132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
+ 136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
+ 140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
+ 144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
+ 148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
+ 152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
+ 156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
+ 160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
+ 164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
+ 168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
+ 172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
+ 176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
+ 180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
+ 184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
+ 188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
+ 192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
+ 196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
+ 200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
+ 204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
+ 208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
+ 212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
+ 216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
+ 220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
+ 224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
+ 228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
+ 232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
+ 236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
+ 240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
+ 244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
+ 248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
+ 252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
+};
+
+void nghttp2_downcase(uint8_t *s, size_t len) {
+ size_t i;
+ for (i = 0; i < len; ++i) {
+ s[i] = DOWNCASE_TBL[s[i]];
+ }
+}
+
+/*
+ * local_window_size
+ * ^ *
+ * | * recv_window_size
+ * | * * ^
+ * | * * |
+ * 0+++++++++
+ * | * * \
+ * | * * | This rage is hidden in flow control. But it must be
+ * v * * / kept in order to restore it when window size is enlarged.
+ * recv_reduction
+ * (+ for negative direction)
+ *
+ * recv_window_size could be negative if we decrease
+ * local_window_size more than recv_window_size:
+ *
+ * local_window_size
+ * ^ *
+ * | *
+ * | *
+ * 0++++++++
+ * | * ^ recv_window_size (negative)
+ * | * |
+ * v * *
+ * recv_reduction
+ */
+int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr) {
+ if (*delta_ptr > 0) {
+ int32_t recv_reduction_delta;
+ int32_t delta;
+ int32_t new_recv_window_size =
+ nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr;
+
+ if (new_recv_window_size >= 0) {
+ *recv_window_size_ptr = new_recv_window_size;
+ return 0;
+ }
+
+ delta = -new_recv_window_size;
+
+ /* The delta size is strictly more than received bytes. Increase
+ local_window_size by that difference |delta|. */
+ if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
+ return NGHTTP2_ERR_FLOW_CONTROL;
+ }
+ *local_window_size_ptr += delta;
+ /* If there is recv_reduction due to earlier window_size
+ reduction, we have to adjust it too. */
+ recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
+ *recv_reduction_ptr -= recv_reduction_delta;
+ if (*recv_window_size_ptr < 0) {
+ *recv_window_size_ptr += recv_reduction_delta;
+ } else {
+ /* If *recv_window_size_ptr > 0, then those bytes are going to
+ be returned to the remote peer (by WINDOW_UPDATE with the
+ adjusted *delta_ptr), so it is effectively 0 now. We set to
+ *recv_reduction_delta, because caller does not take into
+ account it in *delta_ptr. */
+ *recv_window_size_ptr = recv_reduction_delta;
+ }
+ /* recv_reduction_delta must be paid from *delta_ptr, since it was
+ added in window size reduction (see below). */
+ *delta_ptr -= recv_reduction_delta;
+
+ return 0;
+ }
+
+ if (*local_window_size_ptr + *delta_ptr < 0 ||
+ *recv_window_size_ptr < INT32_MIN - *delta_ptr ||
+ *recv_reduction_ptr > INT32_MAX + *delta_ptr) {
+ return NGHTTP2_ERR_FLOW_CONTROL;
+ }
+ /* Decreasing local window size. Note that we achieve this without
+ noticing to the remote peer. To do this, we cut
+ recv_window_size by -delta. This means that we don't send
+ WINDOW_UPDATE for -delta bytes. */
+ *local_window_size_ptr += *delta_ptr;
+ *recv_window_size_ptr += *delta_ptr;
+ *recv_reduction_ptr -= *delta_ptr;
+ *delta_ptr = 0;
+
+ return 0;
+}
+
+int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr) {
+ int32_t recv_reduction_delta;
+ int32_t delta;
+
+ delta = *delta_ptr;
+
+ assert(delta >= 0);
+
+ /* The delta size is strictly more than received bytes. Increase
+ local_window_size by that difference |delta|. */
+ if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
+ return NGHTTP2_ERR_FLOW_CONTROL;
+ }
+
+ *local_window_size_ptr += delta;
+ /* If there is recv_reduction due to earlier window_size
+ reduction, we have to adjust it too. */
+ recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
+ *recv_reduction_ptr -= recv_reduction_delta;
+
+ *recv_window_size_ptr += recv_reduction_delta;
+
+ /* recv_reduction_delta must be paid from *delta_ptr, since it was
+ added in window size reduction (see below). */
+ *delta_ptr -= recv_reduction_delta;
+
+ return 0;
+}
+
+int nghttp2_should_send_window_update(int32_t local_window_size,
+ int32_t recv_window_size) {
+ return recv_window_size > 0 && recv_window_size >= local_window_size / 2;
+}
+
+const char *nghttp2_strerror(int error_code) {
+ switch (error_code) {
+ case 0:
+ return "Success";
+ case NGHTTP2_ERR_INVALID_ARGUMENT:
+ return "Invalid argument";
+ case NGHTTP2_ERR_BUFFER_ERROR:
+ return "Out of buffer space";
+ case NGHTTP2_ERR_UNSUPPORTED_VERSION:
+ return "Unsupported SPDY version";
+ case NGHTTP2_ERR_WOULDBLOCK:
+ return "Operation would block";
+ case NGHTTP2_ERR_PROTO:
+ return "Protocol error";
+ case NGHTTP2_ERR_INVALID_FRAME:
+ return "Invalid frame octets";
+ case NGHTTP2_ERR_EOF:
+ return "EOF";
+ case NGHTTP2_ERR_DEFERRED:
+ return "Data transfer deferred";
+ case NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:
+ return "No more Stream ID available";
+ case NGHTTP2_ERR_STREAM_CLOSED:
+ return "Stream was already closed or invalid";
+ case NGHTTP2_ERR_STREAM_CLOSING:
+ return "Stream is closing";
+ case NGHTTP2_ERR_STREAM_SHUT_WR:
+ return "The transmission is not allowed for this stream";
+ case NGHTTP2_ERR_INVALID_STREAM_ID:
+ return "Stream ID is invalid";
+ case NGHTTP2_ERR_INVALID_STREAM_STATE:
+ return "Invalid stream state";
+ case NGHTTP2_ERR_DEFERRED_DATA_EXIST:
+ return "Another DATA frame has already been deferred";
+ case NGHTTP2_ERR_START_STREAM_NOT_ALLOWED:
+ return "request HEADERS is not allowed";
+ case NGHTTP2_ERR_GOAWAY_ALREADY_SENT:
+ return "GOAWAY has already been sent";
+ case NGHTTP2_ERR_INVALID_HEADER_BLOCK:
+ return "Invalid header block";
+ case NGHTTP2_ERR_INVALID_STATE:
+ return "Invalid state";
+ case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
+ return "The user callback function failed due to the temporal error";
+ case NGHTTP2_ERR_FRAME_SIZE_ERROR:
+ return "The length of the frame is invalid";
+ case NGHTTP2_ERR_HEADER_COMP:
+ return "Header compression/decompression error";
+ case NGHTTP2_ERR_FLOW_CONTROL:
+ return "Flow control error";
+ case NGHTTP2_ERR_INSUFF_BUFSIZE:
+ return "Insufficient buffer size given to function";
+ case NGHTTP2_ERR_PAUSE:
+ return "Callback was paused by the application";
+ case NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS:
+ return "Too many inflight SETTINGS";
+ case NGHTTP2_ERR_PUSH_DISABLED:
+ return "Server push is disabled by peer";
+ case NGHTTP2_ERR_DATA_EXIST:
+ return "DATA or HEADERS frame has already been submitted for the stream";
+ case NGHTTP2_ERR_SESSION_CLOSING:
+ return "The current session is closing";
+ case NGHTTP2_ERR_HTTP_HEADER:
+ return "Invalid HTTP header field was received";
+ case NGHTTP2_ERR_HTTP_MESSAGING:
+ return "Violation in HTTP messaging rule";
+ case NGHTTP2_ERR_REFUSED_STREAM:
+ return "Stream was refused";
+ case NGHTTP2_ERR_INTERNAL:
+ return "Internal error";
+ case NGHTTP2_ERR_CANCEL:
+ return "Cancel";
+ case NGHTTP2_ERR_SETTINGS_EXPECTED:
+ return "When a local endpoint expects to receive SETTINGS frame, it "
+ "receives an other type of frame";
+ case NGHTTP2_ERR_NOMEM:
+ return "Out of memory";
+ case NGHTTP2_ERR_CALLBACK_FAILURE:
+ return "The user callback function failed";
+ case NGHTTP2_ERR_BAD_CLIENT_MAGIC:
+ return "Received bad client magic byte string";
+ case NGHTTP2_ERR_FLOODED:
+ return "Flooding was detected in this HTTP/2 session, and it must be "
+ "closed";
+ default:
+ return "Unknown error code";
+ }
+}
+
+/* Generated by gennmchartbl.py */
+static int VALID_HD_NAME_CHARS[] = {
+ 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
+ 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
+ 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
+ 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
+ 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
+ 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
+ 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
+ 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
+ 0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
+ 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
+ 0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
+ 0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
+ 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
+ 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
+ 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
+ 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
+ 0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
+ 0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
+ 0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
+ 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
+ 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
+ 0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
+ 0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
+ 0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
+ 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
+ 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
+ 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
+ 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
+ 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
+ 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
+ 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
+ 1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
+ 0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
+ 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
+ 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
+ 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
+ 0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
+ 0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
+ 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
+ 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
+ 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
+ 0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
+ 0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
+ 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
+ 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
+ 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
+ 0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
+ 0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
+ 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
+ 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
+ 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
+ 0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
+ 0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
+ 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
+ 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
+ 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
+ 0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
+ 0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
+ 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
+ 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
+ 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
+ 0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
+ 0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
+ 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
+};
+
+int nghttp2_check_header_name(const uint8_t *name, size_t len) {
+ const uint8_t *last;
+ if (len == 0) {
+ return 0;
+ }
+ if (*name == ':') {
+ if (len == 1) {
+ return 0;
+ }
+ ++name;
+ --len;
+ }
+ for (last = name + len; name != last; ++name) {
+ if (!VALID_HD_NAME_CHARS[*name]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Generated by genvchartbl.py */
+static int VALID_HD_VALUE_CHARS[] = {
+ 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
+ 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
+ 0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
+ 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
+ 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
+ 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
+ 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
+ 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
+ 1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
+ 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
+ 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
+ 1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
+ 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
+ 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
+ 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
+ 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
+ 1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
+ 1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
+ 1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
+ 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
+ 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
+ 1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
+ 1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
+ 1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
+ 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
+ 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
+ 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
+ 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
+ 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
+ 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
+ 1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
+ 1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
+ 1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
+ 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
+ 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
+ 1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
+ 1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
+ 1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
+ 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
+ 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
+ 1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
+ 1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
+ 1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
+ 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
+ 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
+ 1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
+ 1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
+ 1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
+ 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
+ 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
+ 1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
+ 1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
+ 1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
+ 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
+ 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
+ 1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
+ 1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
+ 1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
+ 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
+ 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
+ 1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
+ 1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
+ 1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
+ 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
+};
+
+int nghttp2_check_header_value(const uint8_t *value, size_t len) {
+ const uint8_t *last;
+ for (last = value + len; value != last; ++value) {
+ if (!VALID_HD_VALUE_CHARS[*value]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
+ if (len == 0) {
+ return dest;
+ }
+
+ memcpy(dest, src, len);
+
+ return dest + len;
+}
+
+const char *nghttp2_http2_strerror(uint32_t error_code) {
+ switch (error_code) {
+ case NGHTTP2_NO_ERROR:
+ return "NO_ERROR";
+ case NGHTTP2_PROTOCOL_ERROR:
+ return "PROTOCOL_ERROR";
+ case NGHTTP2_INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ case NGHTTP2_FLOW_CONTROL_ERROR:
+ return "FLOW_CONTROL_ERROR";
+ case NGHTTP2_SETTINGS_TIMEOUT:
+ return "SETTINGS_TIMEOUT";
+ case NGHTTP2_STREAM_CLOSED:
+ return "STREAM_CLOSED";
+ case NGHTTP2_FRAME_SIZE_ERROR:
+ return "FRAME_SIZE_ERROR";
+ case NGHTTP2_REFUSED_STREAM:
+ return "REFUSED_STREAM";
+ case NGHTTP2_CANCEL:
+ return "CANCEL";
+ case NGHTTP2_COMPRESSION_ERROR:
+ return "COMPRESSION_ERROR";
+ case NGHTTP2_CONNECT_ERROR:
+ return "CONNECT_ERROR";
+ case NGHTTP2_ENHANCE_YOUR_CALM:
+ return "ENHANCE_YOUR_CALM";
+ case NGHTTP2_INADEQUATE_SECURITY:
+ return "INADEQUATE_SECURITY";
+ case NGHTTP2_HTTP_1_1_REQUIRED:
+ return "HTTP_1_1_REQUIRED";
+ default:
+ return "unknown";
+ }
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_helper.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_helper.h
new file mode 100644
index 00000000..be85fd2f
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_helper.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HELPER_H
+#define NGHTTP2_HELPER_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include
+#include
+
+#include "nghttp2.h"
+#include "nghttp2_mem.h"
+
+#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
+#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
+
+#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
+
+#define nghttp2_struct_of(ptr, type, member) \
+ ((type *)(void *)((char *)(ptr)-offsetof(type, member)))
+
+/*
+ * Copies 2 byte unsigned integer |n| in host byte order to |buf| in
+ * network byte order.
+ */
+void nghttp2_put_uint16be(uint8_t *buf, uint16_t n);
+
+/*
+ * Copies 4 byte unsigned integer |n| in host byte order to |buf| in
+ * network byte order.
+ */
+void nghttp2_put_uint32be(uint8_t *buf, uint32_t n);
+
+/*
+ * Retrieves 2 byte unsigned integer stored in |data| in network byte
+ * order and returns it in host byte order.
+ */
+uint16_t nghttp2_get_uint16(const uint8_t *data);
+
+/*
+ * Retrieves 4 byte unsigned integer stored in |data| in network byte
+ * order and returns it in host byte order.
+ */
+uint32_t nghttp2_get_uint32(const uint8_t *data);
+
+void nghttp2_downcase(uint8_t *s, size_t len);
+
+/*
+ * Adjusts |*local_window_size_ptr|, |*recv_window_size_ptr|,
+ * |*recv_reduction_ptr| with |*delta_ptr| which is the
+ * WINDOW_UPDATE's window_size_increment sent from local side. If
+ * |delta| is strictly larger than |*recv_window_size_ptr|,
+ * |*local_window_size_ptr| is increased by delta -
+ * *recv_window_size_ptr. If |delta| is negative,
+ * |*local_window_size_ptr| is decreased by delta.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_FLOW_CONTROL
+ * local_window_size overflow or gets negative.
+ */
+int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr);
+
+/*
+ * This function works like nghttp2_adjust_local_window_size(). The
+ * difference is that this function assumes *delta_ptr >= 0, and
+ * *recv_window_size_ptr is not decreased by *delta_ptr.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_FLOW_CONTROL
+ * local_window_size overflow or gets negative.
+ */
+int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr);
+
+/*
+ * Returns non-zero if the function decided that WINDOW_UPDATE should
+ * be sent.
+ */
+int nghttp2_should_send_window_update(int32_t local_window_size,
+ int32_t recv_window_size);
+
+/*
+ * Copies the buffer |src| of length |len| to the destination pointed
+ * by the |dest|, assuming that the |dest| is at lest |len| bytes long
+ * . Returns dest + len.
+ */
+uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
+
+#endif /* NGHTTP2_HELPER_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_http.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_http.c
new file mode 100644
index 00000000..49caa100
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_http.c
@@ -0,0 +1,577 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_http.h"
+
+#include
+#include
+#include
+
+#include "nghttp2_hd.h"
+#include "nghttp2_helper.h"
+
+static uint8_t downcase(uint8_t c) {
+ return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c;
+}
+
+static int memieq(const void *a, const void *b, size_t n) {
+ size_t i;
+ const uint8_t *aa = a, *bb = b;
+
+ for (i = 0; i < n; ++i) {
+ if (downcase(aa[i]) != downcase(bb[i])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
+
+static int64_t parse_uint(const uint8_t *s, size_t len) {
+ int64_t n = 0;
+ size_t i;
+ if (len == 0) {
+ return -1;
+ }
+ for (i = 0; i < len; ++i) {
+ if ('0' <= s[i] && s[i] <= '9') {
+ if (n > INT64_MAX / 10) {
+ return -1;
+ }
+ n *= 10;
+ if (n > INT64_MAX - (s[i] - '0')) {
+ return -1;
+ }
+ n += s[i] - '0';
+ continue;
+ }
+ return -1;
+ }
+ return n;
+}
+
+static int lws(const uint8_t *s, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ if (s[i] != ' ' && s[i] != '\t') {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int check_pseudo_header(nghttp2_stream *stream, const nghttp2_hd_nv *nv,
+ int flag) {
+ if (stream->http_flags & flag) {
+ return 0;
+ }
+ if (lws(nv->value->base, nv->value->len)) {
+ return 0;
+ }
+ stream->http_flags = (uint16_t)(stream->http_flags | flag);
+ return 1;
+}
+
+static int expect_response_body(nghttp2_stream *stream) {
+ return (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_HEAD) == 0 &&
+ stream->status_code / 100 != 1 && stream->status_code != 304 &&
+ stream->status_code != 204;
+}
+
+/* For "http" or "https" URIs, OPTIONS request may have "*" in :path
+ header field to represent system-wide OPTIONS request. Otherwise,
+ :path header field value must start with "/". This function must
+ be called after ":method" header field was received. This function
+ returns nonzero if path is valid.*/
+static int check_path(nghttp2_stream *stream) {
+ return (stream->http_flags & NGHTTP2_HTTP_FLAG_SCHEME_HTTP) == 0 ||
+ ((stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_REGULAR) ||
+ ((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_OPTIONS) &&
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_ASTERISK)));
+}
+
+static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
+ int trailer) {
+ if (nv->name->base[0] == ':') {
+ if (trailer ||
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ switch (nv->token) {
+ case NGHTTP2_TOKEN__AUTHORITY:
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ case NGHTTP2_TOKEN__METHOD:
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ switch (nv->value->len) {
+ case 4:
+ if (lstreq("HEAD", nv->value->base, nv->value->len)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
+ }
+ break;
+ case 7:
+ switch (nv->value->base[6]) {
+ case 'T':
+ if (lstreq("CONNECT", nv->value->base, nv->value->len)) {
+ if (stream->stream_id % 2 == 0) {
+ /* we won't allow CONNECT for push */
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
+ if (stream->http_flags &
+ (NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+ break;
+ case 'S':
+ if (lstreq("OPTIONS", nv->value->base, nv->value->len)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case NGHTTP2_TOKEN__PATH:
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (nv->value->base[0] == '/') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_REGULAR;
+ } else if (nv->value->len == 1 && nv->value->base[0] == '*') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_ASTERISK;
+ }
+ break;
+ case NGHTTP2_TOKEN__SCHEME:
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) ||
+ (nv->value->len == 5 && memieq("https", nv->value->base, 5))) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
+ }
+ break;
+ case NGHTTP2_TOKEN_HOST:
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ case NGHTTP2_TOKEN_CONTENT_LENGTH: {
+ if (stream->content_length != -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->content_length = parse_uint(nv->value->base, nv->value->len);
+ if (stream->content_length == -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ }
+ /* disallowed header fields */
+ case NGHTTP2_TOKEN_CONNECTION:
+ case NGHTTP2_TOKEN_KEEP_ALIVE:
+ case NGHTTP2_TOKEN_PROXY_CONNECTION:
+ case NGHTTP2_TOKEN_TRANSFER_ENCODING:
+ case NGHTTP2_TOKEN_UPGRADE:
+ return NGHTTP2_ERR_HTTP_HEADER;
+ case NGHTTP2_TOKEN_TE:
+ if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ default:
+ if (nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ if (nv->name->base[0] != ':') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ }
+
+ return 0;
+}
+
+static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
+ int trailer) {
+ if (nv->name->base[0] == ':') {
+ if (trailer ||
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ switch (nv->token) {
+ case NGHTTP2_TOKEN__STATUS: {
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (nv->value->len != 3) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
+ if (stream->status_code == -1 || stream->status_code == 101) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ }
+ case NGHTTP2_TOKEN_CONTENT_LENGTH: {
+ if (stream->status_code == 204) {
+ /* content-length header field in 204 response is prohibited by
+ RFC 7230. But some widely used servers send content-length:
+ 0. Until they get fixed, we ignore it. */
+ if (stream->content_length != -1) {
+ /* Found multiple content-length field */
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (!lstrieq("0", nv->value->base, nv->value->len)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->content_length = 0;
+ return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
+ }
+ if (stream->status_code / 100 == 1 ||
+ (stream->status_code == 200 &&
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (stream->content_length != -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->content_length = parse_uint(nv->value->base, nv->value->len);
+ if (stream->content_length == -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ }
+ /* disallowed header fields */
+ case NGHTTP2_TOKEN_CONNECTION:
+ case NGHTTP2_TOKEN_KEEP_ALIVE:
+ case NGHTTP2_TOKEN_PROXY_CONNECTION:
+ case NGHTTP2_TOKEN_TRANSFER_ENCODING:
+ case NGHTTP2_TOKEN_UPGRADE:
+ return NGHTTP2_ERR_HTTP_HEADER;
+ case NGHTTP2_TOKEN_TE:
+ if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ default:
+ if (nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ if (nv->name->base[0] != ':') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ }
+
+ return 0;
+}
+
+/* Generated by genauthroitychartbl.py */
+static char VALID_AUTHORITY_CHARS[] = {
+ 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
+ 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
+ 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
+ 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
+ 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
+ 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
+ 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
+ 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
+ 0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
+ 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
+ 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
+ 1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
+ 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
+ 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
+ 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
+ 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
+ 1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
+ 1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
+ 1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
+ 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
+ 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
+ 1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
+ 1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
+ 0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
+ 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
+ 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
+ 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
+ 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
+ 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
+ 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
+ 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
+ 0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
+ 0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
+ 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
+ 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
+ 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
+ 0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
+ 0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
+ 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
+ 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
+ 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
+ 0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
+ 0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
+ 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
+ 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
+ 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
+ 0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
+ 0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
+ 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
+ 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
+ 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
+ 0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
+ 0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
+ 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
+ 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
+ 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
+ 0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
+ 0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
+ 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
+ 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
+ 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
+ 0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
+ 0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
+ 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
+};
+
+static int check_authority(const uint8_t *value, size_t len) {
+ const uint8_t *last;
+ for (last = value + len; value != last; ++value) {
+ if (!VALID_AUTHORITY_CHARS[*value]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int check_scheme(const uint8_t *value, size_t len) {
+ const uint8_t *last;
+ if (len == 0) {
+ return 0;
+ }
+
+ if (!(('A' <= *value && *value <= 'Z') || ('a' <= *value && *value <= 'z'))) {
+ return 0;
+ }
+
+ last = value + len;
+ ++value;
+
+ for (; value != last; ++value) {
+ if (!(('A' <= *value && *value <= 'Z') ||
+ ('a' <= *value && *value <= 'z') ||
+ ('0' <= *value && *value <= '9') || *value == '+' || *value == '-' ||
+ *value == '.')) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
+ nghttp2_frame *frame, nghttp2_hd_nv *nv,
+ int trailer) {
+ int rv;
+
+ /* We are strict for pseudo header field. One bad character should
+ lead to fail. OTOH, we should be a bit forgiving for regular
+ headers, since existing public internet has so much illegal
+ headers floating around and if we kill the stream because of
+ this, we may disrupt many web sites and/or libraries. So we
+ become conservative here, and just ignore those illegal regular
+ headers. */
+ if (!nghttp2_check_header_name(nv->name->base, nv->name->len)) {
+ size_t i;
+ if (nv->name->len > 0 && nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ /* header field name must be lower-cased without exception */
+ for (i = 0; i < nv->name->len; ++i) {
+ uint8_t c = nv->name->base[i];
+ if ('A' <= c && c <= 'Z') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+ /* When ignoring regular headers, we set this flag so that we
+ still enforce header field ordering rule for pseudo header
+ fields. */
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ return NGHTTP2_ERR_IGN_HTTP_HEADER;
+ }
+
+ if (nv->token == NGHTTP2_TOKEN__AUTHORITY ||
+ nv->token == NGHTTP2_TOKEN_HOST) {
+ rv = check_authority(nv->value->base, nv->value->len);
+ } else if (nv->token == NGHTTP2_TOKEN__SCHEME) {
+ rv = check_scheme(nv->value->base, nv->value->len);
+ } else {
+ rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
+ }
+
+ if (rv == 0) {
+ assert(nv->name->len > 0);
+ if (nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ /* When ignoring regular headers, we set this flag so that we
+ still enforce header field ordering rule for pseudo header
+ fields. */
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ return NGHTTP2_ERR_IGN_HTTP_HEADER;
+ }
+
+ if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ return http_request_on_header(stream, nv, trailer);
+ }
+
+ return http_response_on_header(stream, nv, trailer);
+}
+
+int nghttp2_http_on_request_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) {
+ return -1;
+ }
+ stream->content_length = -1;
+ } else {
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) !=
+ NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
+ (stream->http_flags &
+ (NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
+ return -1;
+ }
+ if (!check_path(stream)) {
+ return -1;
+ }
+ }
+
+ if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ /* we are going to reuse data fields for upcoming response. Clear
+ them now, except for method flags. */
+ stream->http_flags &= NGHTTP2_HTTP_FLAG_METH_ALL;
+ stream->content_length = -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_response_headers(nghttp2_stream *stream) {
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG__STATUS) == 0) {
+ return -1;
+ }
+
+ if (stream->status_code / 100 == 1) {
+ /* non-final response */
+ stream->http_flags =
+ (uint16_t)((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_ALL) |
+ NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
+ stream->content_length = -1;
+ stream->status_code = -1;
+ return 0;
+ }
+
+ stream->http_flags =
+ (uint16_t)(stream->http_flags & ~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
+
+ if (!expect_response_body(stream)) {
+ stream->content_length = 0;
+ } else if (stream->http_flags & (NGHTTP2_HTTP_FLAG_METH_CONNECT |
+ NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND)) {
+ stream->content_length = -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_trailer_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ (void)stream;
+
+ if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_remote_end_stream(nghttp2_stream *stream) {
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) {
+ return -1;
+ }
+
+ if (stream->content_length != -1 &&
+ stream->content_length != stream->recv_content_length) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n) {
+ stream->recv_content_length += (int64_t)n;
+
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
+ (stream->content_length != -1 &&
+ stream->recv_content_length > stream->content_length)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void nghttp2_http_record_request_method(nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ const nghttp2_nv *nva;
+ size_t nvlen;
+ size_t i;
+
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS:
+ nva = frame->headers.nva;
+ nvlen = frame->headers.nvlen;
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ nva = frame->push_promise.nva;
+ nvlen = frame->push_promise.nvlen;
+ break;
+ default:
+ return;
+ }
+
+ /* TODO we should do this strictly. */
+ for (i = 0; i < nvlen; ++i) {
+ const nghttp2_nv *nv = &nva[i];
+ if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
+ memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
+ continue;
+ }
+ if (lstreq("CONNECT", nv->value, nv->valuelen)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
+ return;
+ }
+ if (lstreq("HEAD", nv->value, nv->valuelen)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
+ return;
+ }
+ return;
+ }
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_http.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_http.h
new file mode 100644
index 00000000..bde7023d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_http.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HTTP_H
+#define NGHTTP2_HTTP_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_session.h"
+#include "nghttp2_stream.h"
+
+/*
+ * This function is called when HTTP header field |nv| in |frame| is
+ * received for |stream|. This function will validate |nv| against
+ * the current state of stream.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_HTTP_HEADER
+ * Invalid HTTP header field was received.
+ * NGHTTP2_ERR_IGN_HTTP_HEADER
+ * Invalid HTTP header field was received but it can be treated as
+ * if it was not received because of compatibility reasons.
+ */
+int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
+ nghttp2_frame *frame, nghttp2_hd_nv *nv,
+ int trailer);
+
+/*
+ * This function is called when request header is received. This
+ * function performs validation and returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_request_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame);
+
+/*
+ * This function is called when response header is received. This
+ * function performs validation and returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_response_headers(nghttp2_stream *stream);
+
+/*
+ * This function is called trailer header (for both request and
+ * response) is received. This function performs validation and
+ * returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_trailer_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame);
+
+/*
+ * This function is called when END_STREAM flag is seen in incoming
+ * frame. This function performs validation and returns 0 if it
+ * succeeds, or -1.
+ */
+int nghttp2_http_on_remote_end_stream(nghttp2_stream *stream);
+
+/*
+ * This function is called when chunk of data is received. This
+ * function performs validation and returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n);
+
+/*
+ * This function inspects header field in |frame| and records its
+ * method in stream->http_flags. If frame->hd.type is neither
+ * NGHTTP2_HEADERS nor NGHTTP2_PUSH_PROMISE, this function does
+ * nothing.
+ */
+void nghttp2_http_record_request_method(nghttp2_stream *stream,
+ nghttp2_frame *frame);
+
+#endif /* NGHTTP2_HTTP_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_int.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_int.h
new file mode 100644
index 00000000..56c071a4
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_int.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_INT_H
+#define NGHTTP2_INT_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/* Macros, types and constants for internal use */
+
+/* "less" function, return nonzero if |lhs| is less than |rhs|. */
+typedef int (*nghttp2_less)(const void *lhs, const void *rhs);
+
+/* Internal error code. They must be in the range [-499, -100],
+ inclusive. */
+typedef enum {
+ NGHTTP2_ERR_CREDENTIAL_PENDING = -101,
+ NGHTTP2_ERR_IGN_HEADER_BLOCK = -103,
+ NGHTTP2_ERR_IGN_PAYLOAD = -104,
+ /*
+ * Invalid HTTP header field was received but it can be treated as
+ * if it was not received because of compatibility reasons.
+ */
+ NGHTTP2_ERR_IGN_HTTP_HEADER = -105,
+ /*
+ * Invalid HTTP header field was received, and it is ignored.
+ * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
+ * nghttp2_on_invalid_header_callback.
+ */
+ NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106
+} nghttp2_internal_error;
+
+#endif /* NGHTTP2_INT_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_map.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_map.c
new file mode 100644
index 00000000..9de8299a
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_map.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_map.h"
+
+#include
+
+#define INITIAL_TABLE_LENGTH 256
+
+int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
+ map->mem = mem;
+ map->tablelen = INITIAL_TABLE_LENGTH;
+ map->table =
+ nghttp2_mem_calloc(mem, map->tablelen, sizeof(nghttp2_map_entry *));
+ if (map->table == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ map->size = 0;
+
+ return 0;
+}
+
+void nghttp2_map_free(nghttp2_map *map) {
+ nghttp2_mem_free(map->mem, map->table);
+}
+
+void nghttp2_map_each_free(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr) {
+ uint32_t i;
+ for (i = 0; i < map->tablelen; ++i) {
+ nghttp2_map_entry *entry;
+ for (entry = map->table[i]; entry;) {
+ nghttp2_map_entry *next = entry->next;
+ func(entry, ptr);
+ entry = next;
+ }
+ map->table[i] = NULL;
+ }
+}
+
+int nghttp2_map_each(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr) {
+ int rv;
+ uint32_t i;
+ for (i = 0; i < map->tablelen; ++i) {
+ nghttp2_map_entry *entry;
+ for (entry = map->table[i]; entry; entry = entry->next) {
+ rv = func(entry, ptr);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key) {
+ entry->key = key;
+ entry->next = NULL;
+}
+
+/* Same hash function in android HashMap source code. */
+/* The |mod| must be power of 2 */
+static uint32_t hash(int32_t key, uint32_t mod) {
+ uint32_t h = (uint32_t)key;
+ h ^= (h >> 20) ^ (h >> 12);
+ h ^= (h >> 7) ^ (h >> 4);
+ return h & (mod - 1);
+}
+
+static int insert(nghttp2_map_entry **table, uint32_t tablelen,
+ nghttp2_map_entry *entry) {
+ uint32_t h = hash(entry->key, tablelen);
+ if (table[h] == NULL) {
+ table[h] = entry;
+ } else {
+ nghttp2_map_entry *p;
+ /* We won't allow duplicated key, so check it out. */
+ for (p = table[h]; p; p = p->next) {
+ if (p->key == entry->key) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ }
+ entry->next = table[h];
+ table[h] = entry;
+ }
+ return 0;
+}
+
+/* new_tablelen must be power of 2 */
+static int resize(nghttp2_map *map, uint32_t new_tablelen) {
+ uint32_t i;
+ nghttp2_map_entry **new_table;
+
+ new_table =
+ nghttp2_mem_calloc(map->mem, new_tablelen, sizeof(nghttp2_map_entry *));
+ if (new_table == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ for (i = 0; i < map->tablelen; ++i) {
+ nghttp2_map_entry *entry;
+ for (entry = map->table[i]; entry;) {
+ nghttp2_map_entry *next = entry->next;
+ entry->next = NULL;
+ /* This function must succeed */
+ insert(new_table, new_tablelen, entry);
+ entry = next;
+ }
+ }
+ nghttp2_mem_free(map->mem, map->table);
+ map->tablelen = new_tablelen;
+ map->table = new_table;
+
+ return 0;
+}
+
+int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry) {
+ int rv;
+ /* Load factor is 0.75 */
+ if ((map->size + 1) * 4 > map->tablelen * 3) {
+ rv = resize(map, map->tablelen * 2);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ rv = insert(map->table, map->tablelen, new_entry);
+ if (rv != 0) {
+ return rv;
+ }
+ ++map->size;
+ return 0;
+}
+
+nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key) {
+ uint32_t h;
+ nghttp2_map_entry *entry;
+ h = hash(key, map->tablelen);
+ for (entry = map->table[h]; entry; entry = entry->next) {
+ if (entry->key == key) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+int nghttp2_map_remove(nghttp2_map *map, key_type key) {
+ uint32_t h;
+ nghttp2_map_entry **dst;
+
+ h = hash(key, map->tablelen);
+
+ for (dst = &map->table[h]; *dst; dst = &(*dst)->next) {
+ if ((*dst)->key != key) {
+ continue;
+ }
+
+ *dst = (*dst)->next;
+ --map->size;
+ return 0;
+ }
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+}
+
+size_t nghttp2_map_size(nghttp2_map *map) { return map->size; }
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_map.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_map.h
new file mode 100644
index 00000000..48096a2d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_map.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_MAP_H
+#define NGHTTP2_MAP_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_int.h"
+#include "nghttp2_mem.h"
+
+/* Implementation of unordered map */
+
+typedef int32_t key_type;
+
+typedef struct nghttp2_map_entry {
+ struct nghttp2_map_entry *next;
+ key_type key;
+#if SIZEOF_INT_P == 4
+ /* we requires 8 bytes aligment */
+ int64_t pad;
+#endif
+} nghttp2_map_entry;
+
+typedef struct {
+ nghttp2_map_entry **table;
+ nghttp2_mem *mem;
+ size_t size;
+ uint32_t tablelen;
+} nghttp2_map;
+
+/*
+ * Initializes the map |map|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |map|. The stored entries
+ * are not freed by this function. Use nghttp2_map_each_free() to free
+ * each entries.
+ */
+void nghttp2_map_free(nghttp2_map *map);
+
+/*
+ * Deallocates each entries using |func| function and any resources
+ * allocated for |map|. The |func| function is responsible for freeing
+ * given the |entry| object. The |ptr| will be passed to the |func| as
+ * send argument. The return value of the |func| will be ignored.
+ */
+void nghttp2_map_each_free(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr);
+
+/*
+ * Initializes the |entry| with the |key|. All entries to be inserted
+ * to the map must be initialized with this function.
+ */
+void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key);
+
+/*
+ * Inserts the new |entry| with the key |entry->key| to the map |map|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The item associated by |key| already exists.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *entry);
+
+/*
+ * Returns the entry associated by the key |key|. If there is no such
+ * entry, this function returns NULL.
+ */
+nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key);
+
+/*
+ * Removes the entry associated by the key |key| from the |map|. The
+ * removed entry is not freed by this function.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The entry associated by |key| does not exist.
+ */
+int nghttp2_map_remove(nghttp2_map *map, key_type key);
+
+/*
+ * Returns the number of items stored in the map |map|.
+ */
+size_t nghttp2_map_size(nghttp2_map *map);
+
+/*
+ * Applies the function |func| to each entry in the |map| with the
+ * optional user supplied pointer |ptr|.
+ *
+ * If the |func| returns 0, this function calls the |func| with the
+ * next entry. If the |func| returns nonzero, it will not call the
+ * |func| for further entries and return the return value of the
+ * |func| immediately. Thus, this function returns 0 if all the
+ * invocations of the |func| return 0, or nonzero value which the last
+ * invocation of |func| returns.
+ *
+ * Don't use this function to free each entry. Use
+ * nghttp2_map_each_free() instead.
+ */
+int nghttp2_map_each(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr);
+
+#endif /* NGHTTP2_MAP_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_mem.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_mem.c
new file mode 100644
index 00000000..5a669731
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_mem.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include "nghttp2_mem.h"
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+
+static void *default_malloc(size_t size, void *mem_user_data)
+{
+ (void)mem_user_data;
+
+#ifdef INFRA_MEM_STATS
+ return LITE_malloc(size, MEM_MAGIC, "nghttp2");
+#else
+ return HAL_Malloc(size);
+#endif
+}
+
+static void default_free(void *ptr, void *mem_user_data)
+{
+ (void)mem_user_data;
+ if (ptr != NULL) {
+#ifdef INFRA_MEM_STATS
+ LITE_free(ptr);
+#else
+ HAL_Free((void *)ptr);
+ ptr = NULL;
+#endif
+ }
+}
+
+static void *default_calloc(size_t nmemb, size_t size, void *mem_user_data)
+{
+ /* (void)mem_user_data; */
+
+#ifdef INFRA_MEM_STATS
+ return LITE_calloc(nmemb, size, MEM_MAGIC, "nghttp2");
+#else
+ void *ptr = HAL_Malloc(nmemb * size);
+ if (ptr != NULL) {
+ memset(ptr, 0, nmemb * size);
+ }
+ return ptr;
+#endif
+}
+
+static void *default_realloc(void *ptr, size_t size, void *mem_user_data)
+{
+ (void)mem_user_data;
+
+#ifdef INFRA_MEM_STATS
+ return LITE_realloc(ptr, size, MEM_MAGIC, "nghttp2");
+#else
+ return HAL_Realloc(ptr, size);
+#endif
+}
+
+static nghttp2_mem mem_default = {NULL, default_malloc, default_free,
+ default_calloc, default_realloc
+ };
+
+nghttp2_mem *nghttp2_mem_default(void)
+{
+ return &mem_default;
+}
+
+void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size)
+{
+ return mem->malloc(size, mem->mem_user_data);
+}
+
+void nghttp2_mem_free(nghttp2_mem *mem, void *ptr)
+{
+ mem->free(ptr, mem->mem_user_data);
+}
+
+void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data)
+{
+ free_func(ptr, mem_user_data);
+}
+
+void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size)
+{
+ return mem->calloc(nmemb, size, mem->mem_user_data);
+}
+
+void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size)
+{
+ return mem->realloc(ptr, size, mem->mem_user_data);
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_mem.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_mem.h
new file mode 100644
index 00000000..be33ac5d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_mem.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_MEM_H
+#define NGHTTP2_MEM_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+/* The default, system standard memory allocator */
+nghttp2_mem *nghttp2_mem_default(void);
+
+/* Convenient wrapper functions to call allocator function in
+ |mem|. */
+void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size);
+void nghttp2_mem_free(nghttp2_mem *mem, void *ptr);
+void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data);
+void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size);
+void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size);
+
+#endif /* NGHTTP2_MEM_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_net.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_net.c
new file mode 100644
index 00000000..c71af3e1
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_net.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include
+#include
+#include "nghttp2_net.h"
+
+#if IOT_BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t nghttp2_htonl(uint32_t hostlong) {
+ uint32_t res;
+ unsigned char *p = (unsigned char *)&res;
+ *p++ = hostlong >> 24;
+ *p++ = (hostlong >> 16) & 0xffu;
+ *p++ = (hostlong >> 8) & 0xffu;
+ *p = hostlong & 0xffu;
+ return res;
+}
+
+uint16_t nghttp2_htons(uint16_t hostshort) {
+ uint16_t res;
+ unsigned char *p = (unsigned char *)&res;
+ *p++ = hostshort >> 8;
+ *p = hostshort & 0xffu;
+ return res;
+}
+
+uint32_t nghttp2_ntohl(uint32_t netlong) {
+ uint32_t res;
+ unsigned char *p = (unsigned char *)&netlong;
+ res = *p++ << 24;
+ res += *p++ << 16;
+ res += *p++ << 8;
+ res += *p;
+ return res;
+}
+
+uint16_t nghttp2_ntohs(uint16_t netshort) {
+ uint16_t res;
+ unsigned char *p = (unsigned char *)&netshort;
+ res = *p++ << 8;
+ res += *p;
+ return res;
+}
+#endif
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_net.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_net.h
new file mode 100644
index 00000000..b1adc401
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_net.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_NET_H
+#define NGHTTP2_NET_H
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+#define IOT_BYTE_ORDER LITTLE_ENDIAN
+
+#if IOT_BYTE_ORDER == BIG_ENDIAN
+#define nghttp2_htonl(x) (x)
+#define nghttp2_htons(x) (x)
+#define nghttp2_ntohl(x) (x)
+#define nghttp2_ntohs(x) (x)
+#else
+/* Windows requires ws2_32 library for ntonl family functions. We
+ define inline functions for those function so that we don't have
+ dependeny on that lib. */
+
+#ifdef _MSC_VER
+#define STIN
+#else
+#define STIN
+#endif
+
+STIN uint32_t nghttp2_htonl(uint32_t hostlong);
+
+STIN uint16_t nghttp2_htons(uint16_t hostshort);
+
+STIN uint32_t nghttp2_ntohl(uint32_t netlong);
+
+STIN uint16_t nghttp2_ntohs(uint16_t netshort);
+
+#endif
+#endif /* NGHTTP2_NET_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_npn.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_npn.c
new file mode 100644
index 00000000..0527ec94
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_npn.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_npn.h"
+
+#include
+
+static int select_next_protocol(unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ const char *key, unsigned int keylen) {
+ unsigned int i;
+ for (i = 0; i + keylen <= inlen; i += (unsigned int)(in[i] + 1)) {
+ if (memcmp(&in[i], key, keylen) == 0) {
+ *out = (unsigned char *)&in[i + 1];
+ *outlen = in[i];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+#define NGHTTP2_HTTP_1_1_ALPN "\x8http/1.1"
+#define NGHTTP2_HTTP_1_1_ALPN_LEN (sizeof(NGHTTP2_HTTP_1_1_ALPN) - 1)
+
+int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen) {
+ if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN,
+ NGHTTP2_PROTO_ALPN_LEN) == 0) {
+ return 1;
+ }
+ if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN,
+ NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
+ return 0;
+ }
+ return -1;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_npn.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_npn.h
new file mode 100644
index 00000000..c9fe50c9
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_npn.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_NPN_H
+#define NGHTTP2_NPN_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#endif /* NGHTTP2_NPN_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_option.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_option.c
new file mode 100644
index 00000000..1d62f5b6
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_option.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include "nghttp2_option.h"
+#include "nghttp2_session.h"
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+#if INFRA_MEM_STATS
+#define NGHTTP2_OPTION_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "nghttp2.option")
+#define NGHTTP2_OPTION_FREE(ptr) LITE_free(ptr)
+#else
+#define NGHTTP2_OPTION_MALLOC(size) HAL_Malloc(size)
+#define NGHTTP2_OPTION_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+int nghttp2_option_new(nghttp2_option **option_ptr) {
+ *option_ptr = NGHTTP2_OPTION_MALLOC(sizeof(nghttp2_option));
+
+ if (*option_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ memset(*option_ptr, 0, sizeof(nghttp2_option));
+ return 0;
+}
+
+void nghttp2_option_del(nghttp2_option *option) { NGHTTP2_OPTION_FREE(option); }
+
+void nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE;
+ option->no_auto_window_update = val;
+}
+
+void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
+ uint32_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS;
+ option->peer_max_concurrent_streams = val;
+}
+
+void nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC;
+ option->no_recv_client_magic = val;
+}
+
+void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_HTTP_MESSAGING;
+ option->no_http_messaging = val;
+}
+
+void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
+ uint32_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS;
+ option->max_reserved_remote_streams = val;
+}
+
+static void set_ext_type(uint8_t *ext_types, uint8_t type) {
+ ext_types[type / 8] = (uint8_t)(ext_types[type / 8] | (1 << (type & 0x7)));
+}
+
+void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
+ uint8_t type) {
+ if (type < 10) {
+ return;
+ }
+
+ option->opt_set_mask |= NGHTTP2_OPT_USER_RECV_EXT_TYPES;
+ set_ext_type(option->user_recv_ext_types, type);
+}
+
+void nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
+ uint8_t type) {
+ switch (type) {
+ case NGHTTP2_ALTSVC:
+ option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
+ option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC;
+ return;
+ default:
+ return;
+ }
+}
+
+void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_PING_ACK;
+ option->no_auto_ping_ack = val;
+}
+
+void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option,
+ size_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH;
+ option->max_send_header_block_length = val;
+}
+
+void nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
+ size_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE;
+ option->max_deflate_dynamic_table_size = val;
+}
+
+void nghttp2_option_set_no_closed_streams(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_CLOSED_STREAMS;
+ option->no_closed_streams = val;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_option.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_option.h
new file mode 100644
index 00000000..16b64e09
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_option.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_OPTION_H
+#define NGHTTP2_OPTION_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/**
+ * Configuration options
+ */
+typedef enum {
+ /**
+ * This option prevents the library from sending WINDOW_UPDATE for a
+ * connection automatically. If this option is set to nonzero, the
+ * library won't send WINDOW_UPDATE for DATA until application calls
+ * nghttp2_session_consume() to indicate the amount of consumed
+ * DATA. By default, this option is set to zero.
+ */
+ NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE = 1,
+ /**
+ * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
+ * remote endpoint as if it is received in SETTINGS frame. Without
+ * specifying this option, before the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
+ * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
+ * cause problem if local endpoint submits lots of requests
+ * initially and sending them at once to the remote peer may lead to
+ * the rejection of some requests. Specifying this option to the
+ * sensible value, say 100, may avoid this kind of issue. This value
+ * will be overwritten if the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
+ */
+ NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1,
+ NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2,
+ NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3,
+ NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4,
+ NGHTTP2_OPT_USER_RECV_EXT_TYPES = 1 << 5,
+ NGHTTP2_OPT_NO_AUTO_PING_ACK = 1 << 6,
+ NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES = 1 << 7,
+ NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8,
+ NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
+ NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
+} nghttp2_option_flag;
+
+/**
+ * Struct to store option values for nghttp2_session.
+ */
+struct nghttp2_option {
+ /**
+ * NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
+ */
+ size_t max_send_header_block_length;
+ /**
+ * NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE
+ */
+ size_t max_deflate_dynamic_table_size;
+ /**
+ * Bitwise OR of nghttp2_option_flag to determine that which fields
+ * are specified.
+ */
+ uint32_t opt_set_mask;
+ /**
+ * NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS
+ */
+ uint32_t peer_max_concurrent_streams;
+ /**
+ * NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS
+ */
+ uint32_t max_reserved_remote_streams;
+ /**
+ * NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES
+ */
+ uint32_t builtin_recv_ext_types;
+ /**
+ * NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE
+ */
+ int no_auto_window_update;
+ /**
+ * NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC
+ */
+ int no_recv_client_magic;
+ /**
+ * NGHTTP2_OPT_NO_HTTP_MESSAGING
+ */
+ int no_http_messaging;
+ /**
+ * NGHTTP2_OPT_NO_AUTO_PING_ACK
+ */
+ int no_auto_ping_ack;
+ /**
+ * NGHTTP2_OPT_NO_CLOSED_STREAMS
+ */
+ int no_closed_streams;
+ /**
+ * NGHTTP2_OPT_USER_RECV_EXT_TYPES
+ */
+ uint8_t user_recv_ext_types[32];
+};
+
+#endif /* NGHTTP2_OPTION_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_outbound_item.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_outbound_item.c
new file mode 100644
index 00000000..3d35983d
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_outbound_item.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_outbound_item.h"
+
+#include
+#include
+
+void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
+ item->cycle = 0;
+ item->qnext = NULL;
+ item->queued = 0;
+
+ memset(&item->aux_data, 0, sizeof(nghttp2_aux_data));
+}
+
+void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
+ nghttp2_frame *frame;
+
+ if (item == NULL) {
+ return;
+ }
+
+ frame = &item->frame;
+
+ switch (frame->hd.type) {
+ case NGHTTP2_DATA:
+ nghttp2_frame_data_free(&frame->data);
+ break;
+ case NGHTTP2_HEADERS:
+ nghttp2_frame_headers_free(&frame->headers, mem);
+ break;
+ case NGHTTP2_PRIORITY:
+ nghttp2_frame_priority_free(&frame->priority);
+ break;
+ case NGHTTP2_RST_STREAM:
+ nghttp2_frame_rst_stream_free(&frame->rst_stream);
+ break;
+ case NGHTTP2_SETTINGS:
+ nghttp2_frame_settings_free(&frame->settings, mem);
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ nghttp2_frame_push_promise_free(&frame->push_promise, mem);
+ break;
+ case NGHTTP2_PING:
+ nghttp2_frame_ping_free(&frame->ping);
+ break;
+ case NGHTTP2_GOAWAY:
+ nghttp2_frame_goaway_free(&frame->goaway, mem);
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ nghttp2_frame_window_update_free(&frame->window_update);
+ break;
+ default: {
+ nghttp2_ext_aux_data *aux_data;
+
+ aux_data = &item->aux_data.ext;
+
+ if (aux_data->builtin == 0) {
+ nghttp2_frame_extension_free(&frame->ext);
+ break;
+ }
+
+ switch (frame->hd.type) {
+ case NGHTTP2_ALTSVC:
+ nghttp2_frame_altsvc_free(&frame->ext, mem);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ }
+}
+
+void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q) {
+ q->head = q->tail = NULL;
+ q->n = 0;
+}
+
+void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
+ nghttp2_outbound_item *item) {
+ if (q->tail) {
+ q->tail = q->tail->qnext = item;
+ } else {
+ q->head = q->tail = item;
+ }
+ ++q->n;
+}
+
+void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q) {
+ nghttp2_outbound_item *item;
+ if (!q->head) {
+ return;
+ }
+ item = q->head;
+ q->head = q->head->qnext;
+ item->qnext = NULL;
+ if (!q->head) {
+ q->tail = NULL;
+ }
+ --q->n;
+}
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_outbound_item.h b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_outbound_item.h
new file mode 100644
index 00000000..33918356
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_outbound_item.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_OUTBOUND_ITEM_H
+#define NGHTTP2_OUTBOUND_ITEM_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_frame.h"
+#include "nghttp2_mem.h"
+
+/* struct used for HEADERS and PUSH_PROMISE frame */
+typedef struct {
+ nghttp2_data_provider data_prd;
+ void *stream_user_data;
+ /* error code when request HEADERS is canceled by RST_STREAM while
+ it is in queue. */
+ uint32_t error_code;
+ /* nonzero if request HEADERS is canceled. The error code is stored
+ in |error_code|. */
+ uint8_t canceled;
+} nghttp2_headers_aux_data;
+
+/* struct used for DATA frame */
+typedef struct {
+ /**
+ * The data to be sent for this DATA frame.
+ */
+ nghttp2_data_provider data_prd;
+ /**
+ * The flags of DATA frame. We use separate flags here and
+ * nghttp2_data frame. The latter contains flags actually sent to
+ * peer. This |flags| may contain NGHTTP2_FLAG_END_STREAM and only
+ * when |eof| becomes nonzero, flags in nghttp2_data has
+ * NGHTTP2_FLAG_END_STREAM set.
+ */
+ uint8_t flags;
+ /**
+ * The flag to indicate whether EOF was reached or not. Initially
+ * |eof| is 0. It becomes 1 after all data were read.
+ */
+ uint8_t eof;
+ /**
+ * The flag to indicate that NGHTTP2_DATA_FLAG_NO_COPY is used.
+ */
+ uint8_t no_copy;
+} nghttp2_data_aux_data;
+
+typedef enum {
+ NGHTTP2_GOAWAY_AUX_NONE = 0x0,
+ /* indicates that session should be terminated after the
+ transmission of this frame. */
+ NGHTTP2_GOAWAY_AUX_TERM_ON_SEND = 0x1,
+ /* indicates that this GOAWAY is just a notification for graceful
+ shutdown. No nghttp2_session.goaway_flags should be updated on
+ the reaction to this frame. */
+ NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE = 0x2
+} nghttp2_goaway_aux_flag;
+
+/* struct used for GOAWAY frame */
+typedef struct {
+ /* bitwise-OR of one or more of nghttp2_goaway_aux_flag. */
+ uint8_t flags;
+} nghttp2_goaway_aux_data;
+
+/* struct used for extension frame */
+typedef struct {
+ /* nonzero if this extension frame is serialized by library
+ function, instead of user-defined callbacks. */
+ uint8_t builtin;
+} nghttp2_ext_aux_data;
+
+/* Additional data which cannot be stored in nghttp2_frame struct */
+typedef union {
+ nghttp2_data_aux_data data;
+ nghttp2_headers_aux_data headers;
+ nghttp2_goaway_aux_data goaway;
+ nghttp2_ext_aux_data ext;
+} nghttp2_aux_data;
+
+struct nghttp2_outbound_item;
+typedef struct nghttp2_outbound_item nghttp2_outbound_item;
+
+struct nghttp2_outbound_item {
+ nghttp2_frame frame;
+ /* Storage for extension frame payload. frame->ext.payload points
+ to this structure to avoid frequent memory allocation. */
+ nghttp2_ext_frame_payload ext_frame_payload;
+ nghttp2_aux_data aux_data;
+ /* The priority used in priority comparion. Smaller is served
+ earlier. For PING, SETTINGS and non-DATA frames (excluding
+ response HEADERS frame) have dedicated cycle value defined above.
+ For DATA frame, cycle is computed by taking into account of
+ effective weight and frame payload length previously sent, so
+ that the amount of transmission is distributed across streams
+ proportional to effective weight (inside a tree). */
+ uint64_t cycle;
+ nghttp2_outbound_item *qnext;
+ /* nonzero if this object is queued, except for DATA or HEADERS
+ which are attached to stream as item. */
+ uint8_t queued;
+};
+
+/*
+ * Initializes |item|. No memory allocation is done in this function.
+ * Don't call nghttp2_outbound_item_free() until frame member is
+ * initialized.
+ */
+void nghttp2_outbound_item_init(nghttp2_outbound_item *item);
+
+/*
+ * Deallocates resource for |item|. If |item| is NULL, this function
+ * does nothing.
+ */
+void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem);
+
+/*
+ * queue for nghttp2_outbound_item.
+ */
+typedef struct {
+ nghttp2_outbound_item *head, *tail;
+ /* number of items in this queue. */
+ size_t n;
+} nghttp2_outbound_queue;
+
+void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q);
+
+/* Pushes |item| into |q| */
+void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
+ nghttp2_outbound_item *item);
+
+/* Pops |item| at the top from |q|. If |q| is empty, nothing
+ happens. */
+void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q);
+
+/* Returns the top item. */
+#define nghttp2_outbound_queue_top(Q) ((Q)->head)
+
+/* Returns the size of the queue */
+#define nghttp2_outbound_queue_size(Q) ((Q)->n)
+
+#endif /* NGHTTP2_OUTBOUND_ITEM_H */
diff --git a/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_pq.c b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_pq.c
new file mode 100644
index 00000000..79aa1562
--- /dev/null
+++ b/sdk/ESP-IDF/esp_fastbee_aliyun/esp-aliyun/wrappers/external_libs/nghttp2/nghttp2_pq.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_pq.h"
+
+#include
+#include