diff --git a/README.md b/README.md index 4aa78ad..df5f6c2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Ali IoTKit +> 说明: +Ali IoTKit 软件包已经同步更新到 c-sdk-v3.0.1-269691d1b45b15fb9045a8eb178efa54b262aca1c-sdk.git 版本。本软件包中的文档教程未能及时更新,深表歉意,最新文档请移步阿里 [官方 Wikis](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/Linkkit_User_Manual) 和阿里 [官方文档](https://help.aliyun.com/product/93051.html?spm=a2c4g.11186623.6.540.393e492bC6TzC4)。 + ## 1. 介绍 **ali-iotkit** 是 RT-Thread 移植的用于连接阿里云 IoT 平台的软件包。基础 SDK 是阿里提供的 [**iotkit-embedded C-SDK**](https://github.com/aliyun/iotkit-embedded)。 diff --git a/SConscript b/SConscript index dadc354..dad050d 100644 --- a/SConscript +++ b/SConscript @@ -2,129 +2,297 @@ import os from building import * import rtconfig -cwd = GetCurrentDir() +cwd = GetCurrentDir() -src = [] +src = [] CPPPATH = [] -CPPDEFINES = [] -LOCAL_CCFLAGS = '' -#sample -if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT_SAMPLE']): - src += Glob('samples/mqtt/mqtt-example.c') +# +# atm +# +if GetDepend(['ATM_ENABLED']): + src += Glob("iotkit-embedded/src/atm/at_api.c") + if GetDepend(['AT_TCP_ENABLED']): + src += Split(""" + iotkit-embedded/src/atm/at_conn_mbox.c + iotkit-embedded/src/atm/at_conn_mgmt.c + iotkit-embedded/src/atm/at_tcp.c + """) + if GetDepend(['AT_MQTT_ENABLED']): + src += Glob("iotkit-embedded/src/atm/at_mqtt.c") + if GetDepend(['AT_PARSER_ENABLED']): + src += Glob("iotkit-embedded/src/atm/at_parser.c") + + CPPPATH += [cwd + '/iotkit-embedded/src/atm'] +#### atm end #### + +# +# infra +# +src += Glob('iotkit-embedded/src/infra/infra_defs.c') + +if GetDepend(['INFRA_AES']): + src += Glob('iotkit-embedded/src/infra/infra_aes.c') +if GetDepend(['INFRA_CJSON']): + src += Glob('iotkit-embedded/src/infra/infra_cjson.c') +if GetDepend(['INFRA_COMPAT']): + src += Glob('iotkit-embedded/src/infra/infra_compat.c') +if GetDepend(['INFRA_HTTPC']): + src += Glob('iotkit-embedded/src/infra/infra_httpc.c') +if GetDepend(['INFRA_JSON_PARSER']): + src += Glob('iotkit-embedded/src/infra/infra_json_parser.c') +if GetDepend(['INFRA_LOG']): + src += Glob('iotkit-embedded/src/infra/infra_log.c') +if GetDepend(['INFRA_MD5']): + src += Glob('iotkit-embedded/src/infra/infra_md5.c') +if GetDepend(['INFRA_MEM_STATS']): + src += Glob('iotkit-embedded/src/infra/infra_mem_stats.c') +if GetDepend(['INFRA_NET']): + src += Glob('iotkit-embedded/src/infra/infra_net.c') +if GetDepend(['INFRA_PREAUTH']): + src += Glob('iotkit-embedded/src/infra/infra_preauth.c') +if GetDepend(['INFRA_LOG_NETWORK_PAYLOAD']): + src += Glob('iotkit-embedded/src/infra/infra_prt_nwk_payload.c') +if GetDepend(['INFRA_REPORT']): + src += Glob('iotkit-embedded/src/infra/infra_report.c') +if GetDepend(['INFRA_SHA1']): + src += Glob('iotkit-embedded/src/infra/infra_sha1.c') +if GetDepend(['INFRA_SHA256']): + src += Glob('iotkit-embedded/src/infra/infra_sha256.c') +if GetDepend(['INFRA_STRING']): + src += Glob('iotkit-embedded/src/infra/infra_string.c') +if GetDepend(['INFRA_TIMER']): + src += Glob('iotkit-embedded/src/infra/infra_timer.c') + +CPPPATH += [cwd + '/iotkit-embedded/src/infra'] +#### infra end #### + +# +# mqtt +# +if GetDepend(['MQTT_COMM_ENABLED']): + src += Glob('iotkit-embedded/src/mqtt/*.c') + if GetDepend(['MQTT_DEFAULT_IMPL']): + src += Glob('iotkit-embedded/src/mqtt/impl/*.c') + CPPPATH += [cwd + '/iotkit-embedded/src/mqtt/impl'] + + CPPPATH += [cwd + '/iotkit-embedded/src/mqtt'] +#### mqtt end #### + +# +# coap +# +if GetDepend(['COAP_COMM_ENABLED']): + if GetDepend(['COAP_CLIENT']): + src += Glob('iotkit-embedded/src/coap/client/*.c') + CPPPATH += [cwd + '/iotkit-embedded/src/coap/client'] + if GetDepend(['COAP_PACKET']): + src += Glob('iotkit-embedded/src/coap/CoAPPacket/*.c') + CPPPATH += [cwd + '/iotkit-embedded/src/coap/CoAPPacket'] + if GetDepend(['COAP_SERVER']): + src += Glob('iotkit-embedded/src/coap/server/*.c') + CPPPATH += [cwd + '/iotkit-embedded/src/coap/server'] + CPPPATH += [cwd + '/iotkit-embedded/src/coap'] +#### coap end #### + + +# +# device bind +# +if GetDepend(['DEV_BIND_ENABLED']): + src += Glob("iotkit-embedded/src/dev_bind/impl/*.c") + src += Glob("iotkit-embedded/src/dev_bind/impl/awss_reset/*.c") + src += Glob("iotkit-embedded/src/dev_bind/impl/os/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/dev_bind'] + CPPPATH += [cwd + '/iotkit-embedded/src/dev_bind/awss_reset'] + CPPPATH += [cwd + '/iotkit-embedded/src/dev_bind/os'] +#### device bind #### + + +# +# device model +# +if GetDepend(['DEVICE_MODEL_ENABLED']): + src += Split(""" + iotkit-embedded/src/dev_model/client/dm_client.c + iotkit-embedded/src/dev_model/client/dm_client_adapter.c + iotkit-embedded/src/dev_model/dm_api.c + iotkit-embedded/src/dev_model/dm_cota.c + iotkit-embedded/src/dev_model/dm_fota.c + iotkit-embedded/src/dev_model/dm_ipc.c + iotkit-embedded/src/dev_model/dm_manager.c + iotkit-embedded/src/dev_model/dm_message_cache.c + iotkit-embedded/src/dev_model/dm_message.c + iotkit-embedded/src/dev_model/dm_opt.c + iotkit-embedded/src/dev_model/dm_ota.c + iotkit-embedded/src/dev_model/dm_msg_process.c + iotkit-embedded/src/dev_model/dm_utils.c + iotkit-embedded/src/dev_model/iotx_cm_mqtt.c + iotkit-embedded/src/dev_model/impl_linkkit.c + iotkit-embedded/src/dev_model/iotx_cm.c + """) + + if GetDepend(['LOG_REPORT_TO_CLOUD']): + src += Split(""" + iotkit-embedded/src/dev_model/dm_log_report.c + """) + + # ALCS(alink local communication service) is a communication between phone and device + if GetDepend(['ALCS_ENABLED']): + src += Glob("iotkit-embedded/src/dev_model/alcs/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/dev_model/alcs'] + + if GetDepend(['COAP_COMM_ENABLED']): + src += Glob("iotkit-embedded/src/dev_model/iotx_cm_coap.c") + + CPPPATH += [cwd + '/iotkit-embedded/src/dev_model'] + CPPPATH += [cwd + '/iotkit-embedded/src/dev_model/client'] + CPPPATH += [cwd + '/iotkit-embedded/src/dev_model/server'] +#### device model end #### + +# +# device sign +# +if GetDepend(['DEV_SIGN']): + src += Glob('iotkit-embedded/src/dev_sign/dev_sign_mqtt.c') + CPPPATH += [cwd + '/iotkit-embedded/src/dev_sign'] +#### device sign end #### + +# +# device reset +# +if GetDepend(['DEV_RESET']): + src += Glob('iotkit-embedded/src/dev_reset/dev_reset.c') + CPPPATH += [cwd + '/iotkit-embedded/src/dev_reset'] +#### device reset end #### + +# +# dynamic register +# +if GetDepend(['DYNAMIC_REGISTER']): + src += Glob("iotkit-embedded/src/dynamic_register/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/dynamic_register'] +#### dynamic register end #### + +# +# http +# +if GetDepend(['HTTP_COMM_ENABLED']): + src += Glob("iotkit-embedded/src/http/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/http'] +#### http end #### + +# +# http2 +# +if GetDepend(['HTTP2_COMM_ENABLED']): + src += Glob("iotkit-embedded/src/http2/http2_api.c") + src += Glob("iotkit-embedded/src/http2/iotx_http2.c") + + if GetDepend(['FS_ENABLED']): + src += Glob("iotkit-embedded/src/http2/http2_upload_api.c") + CPPPATH += [cwd + '/iotkit-embedded/src/http2'] +#### http end #### + +# +# ota +# +if GetDepend(['OTA_ENABLED']): + src += Split(""" + iotkit-embedded/src/ota/iotx_ota.c + iotkit-embedded/src/ota/ota_fetch.c + iotkit-embedded/src/ota/ota_lib.c + """) + CPPPATH += [cwd + '/iotkit-embedded/src/ota'] +#### ota end #### + +# +# wifi provision +# +if GetDepend(['WIFI_PROVISION_ENABLED']): + if GetDepend(['AWSS_SUPPORT_SMARTCONFIG']): + src += Glob("iotkit-embedded/src/wifi_provision/smartconfig/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/smartconfig'] + if GetDepend(['AWSS_SUPPORT_SMARTCONFIG_WPS']): + src += Glob("iotkit-embedded/src/wifi_provision/p2p/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/p2p'] + + if GetDepend(['AWSS_SUPPORT_ZEROCONFIG']): + src += Glob("iotkit-embedded/src/wifi_provision/zero_config/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/zero_config'] + + if GetDepend(['AWSS_SUPPORT_AHA']): + src += Glob("iotkit-embedded/src/wifi_provision/phone_ap/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/phone_ap'] + if GetDepend(['AWSS_SUPPORT_ADHA']): + src += Glob("iotkit-embedded/src/wifi_provision/router_ap/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/router_ap'] + + if GetDepend(['AWSS_SUPPORT_DEV_AP']): + src += Glob("iotkit-embedded/src/wifi_provision/dev_ap/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/dev_ap'] + + if GetDepend(['AWSS_FRAMEWORKS']): + src += Glob("iotkit-embedded/src/wifi_provision/frameworks/*.c") + src += Glob("iotkit-embedded/src/wifi_provision/frameworks/*/*.c") + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/frameworks'] + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/frameworks/aplist'] + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/frameworks/ieee80211'] + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/frameworks/statics'] + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision/frameworks/utils'] + + CPPPATH += [cwd + '/iotkit-embedded/src/wifi_provision'] +#### wifi provision end #### + +# +# wrappers | port +# +src += Split(""" +ports/rtthread/HAL_OS_rtthread.c +ports/rtthread/HAL_TCP_rtthread.c +ports/rtthread/HAL_UDP_rtthread.c +ports/wrapper.c +""") + +if GetDepend(['SUPPORT_TLS']) or GetDepend(['COAP_DTLS_SUPPORT']): + src += Glob('iotkit-embedded/certs/root_ca.c') +if GetDepend(['SUPPORT_TLS']): + src += Glob('ports/tls/mbedtls/HAL_TLS_mbedtls.c') +if GetDepend(['COAP_DTLS_SUPPORT']): + src += Glob('ports/tls/mbedtls/HAL_DTLS_mbedtls.c') + +if GetDepend(['HAL_CRYPTO']): + src += Glob('ports/rtthread/HAL_Crypt_rtthread.c') + +CPPPATH += [cwd + '/iotkit-embedded/wrappers'] +#### wrappers | port end #### + +# +# samples +# +if GetDepend(['PKG_USING_ALI_IOTKIT_DEV_MODEL_SAMPLE']): + src += Split(""" + samples/dev_model/cJSON.c + samples/dev_model/linkkit_example_solo.c + """) + CPPPATH += [cwd + '/iotkit-embedded/samples/dev_model'] -if GetDepend(['PKG_USING_ALI_IOTKIT_OTA']): - src += Glob('samples/ota/ota_mqtt-example.c') +if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT_SAMPLE']): + src += Split(""" + samples/mqtt/mqtt-example.c + """) if GetDepend(['PKG_USING_ALI_IOTKIT_COAP_SAMPLE']): - src += Glob('samples/coap/coap-example.c') - -#src/cmp, need to enable CMP_ENABLED -#src += Glob('iotkit-embedded/src/cmp/Link-CMP/src/*.c') -#CPPPATH += [cwd + '/iotkit-embedded/src/cmp/Link-CMP'] -#CPPPATH += [cwd + '/iotkit-embedded/src/cmp/Link-CMP/inc'] - -#src/coap -src += Glob('iotkit-embedded/src/coap/*.c') - -#packages/iot-coap-c -src += Glob('iotkit-embedded/src/packages/iot-coap-c/*.c') -CPPPATH += [cwd + '/iotkit-embedded/src/packages/iot-coap-c'] - -#src/dm - -#src/http, need to enable HTTP_COMM_ENABLED -#src += Glob('iotkit-embedded/src/http/*.c') - -#src/import - -#src/log -src += Glob('iotkit-embedded/src/log/LITE-log/*.c') -CPPPATH += [cwd + '/iotkit-embedded/src/log/LITE-log'] - -#src/mqtt -if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT']): - src += Glob('iotkit-embedded/src/mqtt/Link-MQTT/*.c') - src += Glob('iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/*.c') - CPPPATH += [cwd + '/iotkit-embedded/src/mqtt/Link-MQTT'] - CPPPATH += [cwd + '/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket'] - -#src/ota -if GetDepend(['PKG_USING_ALI_IOTKIT_OTA']): - src += Glob('iotkit-embedded/src/ota/Link-OTA/src/*.c') - CPPPATH += [cwd + '/iotkit-embedded/src/ota/Link-OTA'] - -SrcRemove(src, 'iotkit-embedded/src/ota/Link-OTA/src/ota_lib.c') # have been include by ota.c -SrcRemove(src, 'iotkit-embedded/src/ota/Link-OTA/src/ota_mqtt.c') # have been include by ota.c -SrcRemove(src, 'iotkit-embedded/src/ota/Link-OTA/src/ota_coap.c') # have been include by ota.c -SrcRemove(src, 'iotkit-embedded/src/ota/Link-OTA/src/ota_fetch.c') # have been include by ota.c - -#src/cota -#src += Glob('iotkit-embedded/src/cota/*.c') - -#src/fota -#src += Glob('iotkit-embedded/src/fota/*.c') - -#src/packages -src += Glob('iotkit-embedded/src/packages/LITE-utils/*.c') -CPPPATH += [cwd + '/iotkit-embedded/src/packages/LITE-utils'] - -SrcRemove(src, 'iotkit-embedded/src/packages/LITE-utils/lite-utils_prog.c') - -#src/platform -#src/scripts - -#src/sdk-tests -#src/shadow -#src/subdev - -#src/system -src += Glob('iotkit-embedded/src/system/iotkit-system/src/*.c') -CPPPATH += [cwd + '/iotkit-embedded/src/system/iotkit-system'] - -#src/tfs -#src/tls - -#src/utils -src += Glob('iotkit-embedded/src/utils/misc/*.c') -src += Glob('iotkit-embedded/src/utils/digest/*.c') -CPPPATH += [cwd + '/iotkit-embedded/src/utils/misc'] -CPPPATH += [cwd + '/iotkit-embedded/src/utils/digest'] - -#ports -src += Glob('ports/rtthread/*.c') - -if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT_TLS']): - src += Glob('ports/ssl/mbedtls/*.c') - -#src/sdk-impl -CPPPATH += [cwd + '/iotkit-embedded/src/sdk-impl'] -CPPPATH += [cwd + '/iotkit-embedded/src/sdk-impl/exports'] -CPPPATH += [cwd + '/iotkit-embedded/src/sdk-impl/imports'] - -if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT']): - CPPDEFINES += ['MQTT_COMM_ENABLED'] - if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT_DIRECT']): - CPPDEFINES += ['MQTT_DIRECT'] - if not GetDepend(['PKG_USING_ALI_IOTKIT_MQTT_TLS']): - CPPDEFINES += ['IOTX_WITHOUT_TLS'] - -if GetDepend(['PKG_USING_ALI_IOTKIT_COAP']): - CPPDEFINES += ['COAP_COMM_ENABLED'] - if GetDepend(['PKG_USING_ALI_IOTKIT_COAP_DTLS']): - CPPDEFINES += ['COAP_DTLS_SUPPORT'] - -# OTA_SIGNAL_CHANNEL: 1-mqtt; 2:coap; 4:http -if GetDepend(['PKG_USING_ALI_IOTKIT_MQTT_OTA']): - CPPDEFINES += ['SERVICE_OTA_ENABLED', 'OTA_SIGNAL_CHANNEL=1'] - -if GetDepend(['PKG_USING_ALI_IOTKIT_COAP_OTA']): - CPPDEFINES += ['SERVICE_OTA_ENABLED', 'OTA_SIGNAL_CHANNEL=2'] + src += Split(""" + samples/coap/coap_example.c + """) -CPPDEFINES += ['IOTX_NET_INIT_WITH_PK_EXT', '_PLATFORM_IS_RTTHREAD_', 'IOTX_WITHOUT_ITLS'] +if GetDepend(['PKG_USING_ALI_IOTKIT_OTA_SAMPLE']): + src += Split(""" + samples/ota/ota_mqtt-example.c + """) +#### samples end #### -if rtconfig.CROSS_TOOL == 'gcc' : - CPPDEFINES += ['IOTX_PRJ_VERSION=\\"V2.10\\"'] +group = DefineGroup('ali-iotkit', src, depend = ['PKG_USING_ALI_IOTKIT'], CPPPATH = CPPPATH) -group = DefineGroup('ali-iotkit', src, depend = ['PKG_USING_ALI_IOTKIT'], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS, CPPDEFINES = CPPDEFINES) Return('group') diff --git a/iotkit-embedded/.gitignore b/iotkit-embedded/.gitignore index ce6fff3..32f060b 100644 --- a/iotkit-embedded/.gitignore +++ b/iotkit-embedded/.gitignore @@ -1,5 +1,3 @@ -*.so -*.exe .settings/ *.cproject *.project @@ -20,9 +18,15 @@ ltmain.sh .config output/ ota.bin +src/packages/*.git/hooks/*.sample vs_build/ .vs/ -html/ +doc/html/ compile.log CMakeLists.txt.user qt_build/ +.vscode/ +GPATH +GRTAGS +GTAGS +iotx-sdk-c-test/ diff --git a/iotkit-embedded/CMakeLists.txt b/iotkit-embedded/CMakeLists.txt deleted file mode 100644 index d03f356..0000000 --- a/iotkit-embedded/CMakeLists.txt +++ /dev/null @@ -1,158 +0,0 @@ -######################################################################## -# prevent in-tree builds -######################################################################## -if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) - message(FATAL_ERROR "not allowded in-tree build") -endif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) - -######################################################################## -# project setup -######################################################################## -cmake_minimum_required(VERSION 2.8) -project(iotx-sdk-c) - -list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") -include(iotx-sdk-version) - -######################################################################## -# options -######################################################################## -option(FEATURE_GIT_CLONE_BEFORE_BUILD "git clone repos in packages folder when cmake configs" OFF) -option(FEATURE_MQTT_COMM_ENABLED "MQTT communication enabled or not" ON) -option(FEATURE_MQTT_DIRECT "MQTT direct connection enabled or not" ON) -option(FEATURE_MQTT_DIRECT_NOTLS "MQTT direct connection w/o tls enabled or not" OFF) -option(FEATURE_COAP_COMM_ENABLED "coap communication enabled or not" ON) -option(FEATURE_HTTP_COMM_ENABLED "HTTP communication enabled or not" ON) -option(FEATURE_MQTT_SHADOW "MQTT shadow enabled or not" ${FEATURE_MQTT_COMM_ENABLED}) -option(FEATURE_COAP_DTLS_SUPPORT "coap w/ dtls support or not" ${FEATURE_COAP_COMM_ENABLED}) -option(FEATURE_SUBDEVICE_ENABLED "subdev enabled or not" OFF) -option(FEATURE_CLOUD_CONN_ENABLED "cloud connection enabled or not" OFF) -option(FEATURE_CMP_ENABLED "cmp enabled or not" ON) -option(FEATURE_DM_ENABLED "dm & linkkit enabled or not" ON) -option(FEATURE_SERVICE_OTA_ENABLED "ota enabled or not" ON) -option(FEATURE_SERVICE_COTA_ENABLED "config ota enabled or not" OFF) -option(FEATURE_SUPPORT_PRODUCT_SECRET "support via product_secret get device_secret" OFF) -#option(FEATURE_OTA_FETCH_CHANNEL "specify ota fetch channel" ON)HTTP -#option(FEATURE_OTA_SIGNAL_CHANNEL "specify ota signal channel" ON)MQTT -set(GCC_ARCH native CACHE STRING "GCC compile for specific architecture.") - -######################################################################## -# Compiler specific setup -######################################################################## -add_definitions(-DOTA_SIGNAL_CHANNEL=1) -add_definitions(-DFORCE_SSL_VERIFY) -add_definitions(-DUSING_UTILS_JSON) -add_definitions(-DLITE_THING_MODEL) - -if(FEATURE_MQTT_DIRECT) - add_definitions(-DMQTT_DIRECT) -endif(FEATURE_MQTT_DIRECT) - -add_definitions(-DUSING_SHA1_IN_HMAC) - -if(FEATURE_MQTT_COMM_ENABLED) - add_definitions(-DMQTT_COMM_ENABLED) -endif(FEATURE_MQTT_COMM_ENABLED) - -if(FEATURE_SUBDEVICE_ENABLED) - add_definitions(-DSUBDEVICE_ENABLED) -endif(FEATURE_SUBDEVICE_ENABLED) - -if(FEATURE_CMP_ENABLED) - add_definitions(-DCMP_ENABLED) -endif(FEATURE_CMP_ENABLED) -add_definitions(-DCMP_SUPPORT_TOPIC_DISPATCH) - -if(FEATURE_DM_ENABLED) - add_definitions(-DDM_ENABLED) - add_definitions(-DDEVICEINFO_ENABLED) -endif(FEATURE_DM_ENABLED) - -if(FEATURE_SERVICE_OTA_ENABLED) - add_definitions(-DSERVICE_OTA_ENABLED) - if(FEATURE_SERVICE_COTA_ENABLED) - add_definitions(-DSERVICE_COTA_ENABLED) - endif(FEATURE_SERVICE_COTA_ENABLED) -endif(FEATURE_SERVICE_OTA_ENABLED) - -if(FEATURE_SUPPORT_PRODUCT_SECRET) - add_definitions(-DSUPPORT_PRODUCT_SECRET) -endif(FEATURE_SUPPORT_PRODUCT_SECRET) - -add_definitions(-DIOTX_WITHOUT_ITLS) -add_definitions(-DIOTX_NET_INIT_WITH_PK_EXT) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${GCC_ARCH} -Wall -Wno-comment -Wno-write-strings -Wno-format-extra-args -Winline -Wno-unused-result -Wno-format") -######################################################################## -# add -fPIC property to all targets -######################################################################## -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -######################################################################## -# print project summary -######################################################################## -message(STATUS "---------------------------------------------") -message(STATUS "project name:\t" ${PROJECT_NAME}) -message(STATUS "source dir:\t" ${PROJECT_SOURCE_DIR}) -message(STATUS "binary dir:\t" ${PROJECT_BINARY_DIR}) -message(STATUS "system processor:\t" ${CMAKE_SYSTEM_PROCESSOR}) -message(STATUS "c compiler:\t" ${CMAKE_C_COMPILER}) -message(STATUS "system platform:\t" ${CMAKE_SYSTEM}) -message(STATUS "c compiler options:\t" ${CMAKE_C_FLAGS}) - -if(WIN32) - message(STATUS "windows compiling...") - add_definitions(-D_PLATFORM_IS_WINDOWS_) -else(WIN32) - message(STATUS "linux compiling...") - add_definitions( -D_PLATFORM_IS_LINUX_) -endif(WIN32) -message(STATUS "iotx sdk version:\t" ${iotx_sdk_version}) -message(STATUS "---------------------------------------------") - -######################################################################## -# git clone integrated repos -######################################################################## -if(FEATURE_GIT_CLONE_BEFORE_BUILD) -file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/src/packages/LITE-log) -file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/src/packages/mbedtls-in-iotkit) -file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/src/packages/iotkit-system) -file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/src/packages/Link-MQTT) -file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/src/packages/Link-OTA) -file(REMOVE_RECURSE ${PROJECT_SOURCE_DIR}/src/packages/Link-CMP) -execute_process(COMMAND git clone ${PROJECT_SOURCE_DIR}/src/packages/LITE-log.git ${PROJECT_SOURCE_DIR}/src/packages/LITE-log) -execute_process(COMMAND git clone ${PROJECT_SOURCE_DIR}/src/packages/mbedtls-in-iotkit.git ${PROJECT_SOURCE_DIR}/src/packages/mbedtls-in-iotkit) -execute_process(COMMAND git clone ${PROJECT_SOURCE_DIR}/src/packages/iotkit-system.git ${PROJECT_SOURCE_DIR}/src/packages/iotkit-system) -execute_process(COMMAND git clone ${PROJECT_SOURCE_DIR}/src/packages/Link-MQTT.git ${PROJECT_SOURCE_DIR}/src/packages/Link-MQTT) -execute_process(COMMAND git clone ${PROJECT_SOURCE_DIR}/src/packages/Link-OTA.git ${PROJECT_SOURCE_DIR}/src/packages/Link-OTA) -execute_process(COMMAND git clone ${PROJECT_SOURCE_DIR}/src/packages/Link-CMP.git ${PROJECT_SOURCE_DIR}/src/packages/Link-CMP) -endif(FEATURE_GIT_CLONE_BEFORE_BUILD) - -include_directories(${PROJECT_SOURCE_DIR}/src/sdk-impl) -include_directories(${PROJECT_SOURCE_DIR}/src/sdk-impl/imports) -include_directories(${PROJECT_SOURCE_DIR}/src/sdk-impl/exports) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/mbedtls-in-iotkit/include) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/LITE-log) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/LITE-utils) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/Link-MQTT) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/Link-OTA) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/Link-CMP/inc) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/iot-coap-c) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/iotkit-system) -include_directories(${PROJECT_SOURCE_DIR}/src/packages/iot-coap-c) -include_directories(${PROJECT_SOURCE_DIR}/src/utils/digest) -include_directories(${PROJECT_SOURCE_DIR}/src/utils/misc) -include_directories(${PROJECT_SOURCE_DIR}/src/tfs) -if(FEATURE_SUBDEVICE_ENABLED) -include_directories(${PROJECT_SOURCE_DIR}/src/subdev) -endif(FEATURE_SUBDEVICE_ENABLED) -if(FEATURE_DM_ENABLED) -include_directories(${PROJECT_SOURCE_DIR}/src/dm/include) -endif(FEATURE_DM_ENABLED) -include_directories(${PROJECT_SOURCE_DIR}/src/import/linux/include) - -######################################################################## -# Add the subdirectories -######################################################################## -add_subdirectory(src) -add_subdirectory(sample) diff --git a/iotkit-embedded/LICENSE b/iotkit-embedded/LICENSE index 261eeb9..57bc88a 100644 --- a/iotkit-embedded/LICENSE +++ b/iotkit-embedded/LICENSE @@ -199,3 +199,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + diff --git a/iotkit-embedded/README.md b/iotkit-embedded/README.md index 607df02..b733de3 100644 --- a/iotkit-embedded/README.md +++ b/iotkit-embedded/README.md @@ -1,172 +1,22 @@ -# 阿里云物联网套件 +# C-SDK 简介 -物联网套件是阿里云专门为物联网领域的开发人员推出的, 其目的是帮助开发者搭建安全且性能强大的数据通道, 方便终端(如传感器, 执行器, 嵌入式设备或智能家电等等)和云端的双向通信. +设备厂商在设备上集成 `C-SDK` 后, 可以将设备安全的接入到阿里云IoT物联网平台, 从而使设备可以被阿里云IoT物联网平台进行管理 -- **[官方代码首页](https://github.com/aliyun/iotkit-embedded)** -- **[官方维基首页](https://github.com/aliyun/iotkit-embedded/wiki)** +设备需要支持TCP/IP协议栈或串口通信, 以及C99标准的C库才能集成SDK, zigbee/433/KNX这样的非IP设备需要通过网关设备接入到阿里云IoT物联网平台, 网关设备需要集成C-SDK -# 快速开始 - -本节描述如何申请自己的设备, 并结合本SDK快速体验该设备通过`MQTT`+`TLS/SSL`协议连接到阿里云, 上报和接收业务报文. 关于SDK的更多使用方式, 请访问[官方WiKi](https://github.com/aliyun/iotkit-embedded/wiki) - -> 实现原理: -> -> `MQTT协议`(`Message Queuing Telemetry Transport`, 消息队列遥测传输)是IBM开发的一个即时通讯协议, 是为大量计算能力有限, 且工作在低带宽, 不可靠的网络的远程传感器和控制设备通讯而设计的协议 -> -> 利用MQTT协议是一种基于二进制消息的发布/订阅编程模式的消息协议, 下面的应用程序先在阿里云IoT平台订阅(`Subscribe`)一个`Topic`成功, 然后自己向该`Topic`做发布(`Publish`)动作 -> 阿里云IoT平台收到之后, 就会原样推送回这个应用程序, 因为该程序之前已经通过订阅(`Subscribe`)动作成为该`Topic`的一个接收者, 发布到这个`Topic`上的任何消息, 都会被推送到已订阅该`Topic`的所有终端上 - -## 一. 开发环境准备 - -#### **1. 安装Ubuntu16.04** - -本SDK的编译环境是`64位`的`Ubuntu16.04`, 在其它Linux上尚未测试过, 所以推荐安装与阿里开发者一致的发行版 - -如果您使用`Windows`操作系统, 建议安装虚拟机软件`Virtualbox`, 下载地址: [https://www.virtualbox.org/wiki/Downloads](https://www.virtualbox.org/wiki/Downloads) - -然后安装64位的desktop版本`Ubuntu 16.04.x LTS`, 下载地址: [https://www.ubuntu.com/download/desktop](https://www.ubuntu.com/download/desktop) - -#### **2. 安装必备软件** - -本SDK的开发编译环境使用如下软件: `make-4.1`, `git-2.7.4`, `gcc-5.4.0`, `gcov-5.4.0`, `lcov-1.12`, `bash-4.3.48`, `tar-1.28`, `mingw-5.3.1` - -可使用如下命令行安装必要的软件: - - apt-get install -y build-essential make git gcc - -## 二. 在控制台创建设备 - -#### **1. 注册/登录阿里云账号** - -访问阿里云[登录页面](https://account.aliyun.com/login/login.htm), 点击[免费注册](https://account.aliyun.com/register/register.htm), 免费获得一个阿里云账号. 若您已有账号, 可直接登录 - -#### **2. 访问物联网套件控制台** - -登入之后, 鼠标悬停在**产品**上, 弹出层叠菜单 - -![image](https://raw.githubusercontent.com/wiki/aliyun/iotkit-embedded/pics/iotconsole-product.png) - -然后向下滚动页面, 点击**物联网套件** - -![image](https://raw.githubusercontent.com/wiki/aliyun/iotkit-embedded/pics/iotconsole-iotkit.png) - -或直接访问[https://www.aliyun.com/product/iot](https://www.aliyun.com/product/iot), 之后点击**立即开通**, 或者**管理控制台**, 登入[控制台主界面](https://iot.console.aliyun.com/) - -#### **3. 创建产品和设备** - -点击页面右上角的**创建产品**按钮, 创建一个品类, 然后在左侧导航栏点击**设备管理**, 再到页面右侧点**添加设备**, 创建该品类下的一个设备, 如下图则得到创建成功后的**设备标识三元组** -- `productKey`: 标识产品的品类 -- `deviceName`: 标识品类下的具体设备 -- `deviceSecret`: 该设备的密钥, 需填写到SDK中, 用于连接阿里云服务器时完成认证 - -![image](https://raw.githubusercontent.com/wiki/aliyun/iotkit-embedded/pics/iotconsole-devinfo.png) - -#### **4. 创建可订阅可发布的Topic** - -点击左侧导航栏的**消息通信**, 再到页面右侧点**定义Topic类**, 创建一个新的`/${productKey}/${deviceName}/data`, 并设置为**可订阅可发布**权限 - -![image](https://raw.githubusercontent.com/wiki/aliyun/iotkit-embedded/pics/iotconsole-subpub.png) - -## 三. 编译样例程序 - -#### **1. 下载SDK** - -登录Linux, 运行如下命令从github克隆代码, 或者访问最新地址[下载页面](https://github.com/aliyun/iotkit-embedded/releases/latest), **将下载到的压缩包在Linux上解压缩** - - $ git clone https://github.com/aliyun/iotkit-embedded - -#### **2. 填入设备信息** - -编辑文件`sample/mqtt/mqtt-example.c`, 编辑如下代码段, 填入之前**创建产品和设备**步骤中得到的**设备标识三元组**: - -![image](https://raw.githubusercontent.com/wiki/aliyun/iotkit-embedded/pics/sdk-devinfo.png) - -#### **3. 编译SDK产生样例程序** - -运行如下命令: - - $ make distclean - $ make - -编译成功完成后, 生成的样例程序在当前目录的`output/release/bin`目录下: - - $ tree output/release - output/release - ├── bin - │   ├── coap-example - │   ├── http-example - │   ├── mqtt-example - │   ├── mqtt_rrpc-example - │   ├── ota_mqtt-example - │   ├── sdk-testsuites - │   ├── shadow-testsuites - │   └── subdev-example - ... - ... - -## 四. 运行样例程序 - -#### **1. 执行样例程序** - - $ ./output/release/bin/mqtt-example - [inf] iotx_device_info_init(40): device_info created successfully! - [dbg] iotx_device_info_set(50): start to set device info! - [dbg] iotx_device_info_set(64): device_info set successfully! - [dbg] _calc_hmac_signature(57): | source: clientId2UCRZpAbCGC.ExampleDevdeviceNameExampleDevproductKey2UCRZpAbCGCtimestamp2524608000000 (93) - [dbg] _calc_hmac_signature(58): | secret: fbh47lGBSayncmTHEjF1E5x4CZdeJTO9 (32) - [dbg] _calc_hmac_signature(61): | method: hmacsha1 - [dbg] _calc_hmac_signature(74): | signature: 326a4a6ed38b1bd5ddb6a5d11d27928bfb5a62d0 (40) - [dbg] guider_print_dev_guider_info(236): .................................................... - [dbg] guider_print_dev_guider_info(237): ProductKey : 2UCRZpAbCGC - [dbg] guider_print_dev_guider_info(238): DeviceName : ExampleDev - [dbg] guider_print_dev_guider_info(239): DeviceID : 2UCRZpAbCGC.ExampleDev - [dbg] guider_print_dev_guider_info(240): DeviceSecret : fbh47lGBSayncmTHEjF1E5x4CZdeJTO9 - [dbg] guider_print_dev_guider_info(241): .................................................... - ... - ... - _demo_message_arrive|136 :: ---- - _demo_message_arrive|140 :: Topic: '/2UCRZpAbCGC/ExampleDev/data' (Length: 28) - _demo_message_arrive|144 :: Payload: '{"attr_name":"temperature", "attr_value":"1"}' (Length: 45) - _demo_message_arrive|145 :: ---- - [inf] iotx_mc_unsubscribe(1416): mqtt unsubscribe success,topic = /2UCRZpAbCGC/ExampleDev/data! - [dbg] iotx_mc_disconnect(2106): rc = MQTTDisconnect() = 0 - [inf] _network_ssl_disconnect(413): ssl_disconnect - [inf] iotx_mc_disconnect(2114): mqtt disconnect! - [inf] iotx_mc_release(2160): mqtt release! - - --------------------------------------------------- - . bytes_total_allocated: 1292 - . bytes_total_freed: 1292 - . bytes_total_in_use: 0 - . bytes_max_allocated: 560 - . bytes_max_in_use: 1066 - . iterations_allocated: 20 - . iterations_freed: 20 - . iterations_in_use: 0 - . iterations_max_in_use: 11 - --------------------------------------------------- - main|441 :: out of sample! - -#### **2. 观察消息上报** - -如下日志信息显示样例程序正在通过`MQTT`的`Publish`类型消息, 上报业务数据到`/${prodcutKey}/${deviceName}/data` +# 快速开始 - mqtt_client|256 :: packet-id=3, publish topic msg={"attr_name":"temperature", "attr_value":"1"} +用户可以通过[快速的体验C-SDK](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Quick_Start)感受如何将设备连接到阿里云物联网平台, 并如何将设备的数据发送到平台/以及如何从物联网平台接收数据 -#### **3. 观察消息下推** -如下日志信息显示该消息因为是到达已被订阅的`Topic`, 所以又被服务器原样推送到样例程序, 并进入相应的回调函数 +# 移植说明 +C-SDK与OS/硬件平台无关, 全部部分用C编写, 它定义了HAL层来对接与硬件相关的功能, 因此在使用C-SDK时用户需要去实现相关的HAL函数 - _demo_message_arrive|136 :: ---- - _demo_message_arrive|140 :: Topic: '/2UCRZpAbCGC/ExampleDev/data' (Length: 28) - _demo_message_arrive|144 :: Payload: '{"attr_name":"temperature", "attr_value":"1"}' (Length: 45) - _demo_message_arrive|145 :: ---- +目前C-SDK已实现了在Linux/Windows/AliOS上HAL的实现, 同时对于一些常见的OS或者模组也进行了适配, 可以[访问此处](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Port_Guide/Porting_Overview)查看如何在相应平台上进行SDK的编译与集成 -#### **4. 观察控制台日志** -可以登录物联网套件控制台, 到[设备页面](https://iot.console.aliyun.com/#/product/detail), 找到刚才填写在SDK中的设备并点击进入, 点左边导航栏的**日志服务**, 可以看到刚才被上报的消息 +# 编程文档 -![image](https://raw.githubusercontent.com/wiki/aliyun/iotkit-embedded/pics/iotconsole-publog.png) +SDK提供了一系列的编程文档来描述如何使用SDK提供的软件功能, 请[访问此处](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/Linkkit_User_Manual)进行了解 -# 关于SDK的更多使用方式, 请访问[官方WiKi](https://github.com/aliyun/iotkit-embedded/wiki) diff --git a/iotkit-embedded/certs/iot.mk b/iotkit-embedded/certs/iot.mk new file mode 100644 index 0000000..48d6a9c --- /dev/null +++ b/iotkit-embedded/certs/iot.mk @@ -0,0 +1 @@ +LIBA_TARGET := libiot_cert.a diff --git a/iotkit-embedded/src/system/iotkit-system/src/ca.c b/iotkit-embedded/certs/root_ca.c similarity index 63% rename from iotkit-embedded/src/system/iotkit-system/src/ca.c rename to iotkit-embedded/certs/root_ca.c index f28bb4c..4881a94 100644 --- a/iotkit-embedded/src/system/iotkit-system/src/ca.c +++ b/iotkit-embedded/certs/root_ca.c @@ -1,26 +1,10 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ - #include -#ifndef IOTX_WITHOUT_TLS -static const char *iotx_ca_crt = \ +const char *iotx_ca_crt = \ { \ "-----BEGIN CERTIFICATE-----\r\n" @@ -45,13 +29,3 @@ static const char *iotx_ca_crt = \ "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \ "-----END CERTIFICATE-----" }; -#endif /* #ifndef IOTX_WITHOUT_TLS */ - -const char *iotx_ca_get(void) -{ -#ifdef IOTX_WITHOUT_TLS - return NULL; -#else - return iotx_ca_crt; -#endif -} diff --git a/iotkit-embedded/config.bat b/iotkit-embedded/config.bat new file mode 100644 index 0000000..944b58e --- /dev/null +++ b/iotkit-embedded/config.bat @@ -0,0 +1,11 @@ +@echo off +chcp 437 + +set CONFIG_=FEATURE_ + +.\tools\prebuilt\windows\kconfig-frontends-3.12.0-windows\kconfig-mconf.exe .\tools\Config.in + +if exist .config ( + copy /y .config make.settings + del /F .config +) diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/.gitignore b/iotkit-embedded/external_libs/mbedtls/include/.gitignore similarity index 100% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/.gitignore rename to iotkit-embedded/external_libs/mbedtls/include/.gitignore diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/aes.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/aes.h similarity index 71% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/aes.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/aes.h index b5560cc..115db98 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/aes.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/aes.h @@ -1,32 +1,16 @@ -/** - * \file aes.h - * - * \brief AES block cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_AES_H #define MBEDTLS_AES_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include @@ -41,7 +25,7 @@ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) -#define inline __inline + #define inline __inline #endif #if !defined(MBEDTLS_AES_ALT) @@ -60,8 +44,7 @@ extern "C" { * - to simplify key expansion in the 256-bit case by * generating an extra round key */ -typedef struct -{ +typedef struct { int nr; /*!< number of rounds */ uint32_t *rk; /*!< AES round keys */ uint32_t buf[68]; /*!< unaligned data */ @@ -73,14 +56,14 @@ mbedtls_aes_context; * * \param ctx AES context to be initialized */ -void mbedtls_aes_init( mbedtls_aes_context *ctx ); +void mbedtls_aes_init(mbedtls_aes_context *ctx); /** * \brief Clear AES context * * \param ctx AES context to be cleared */ -void mbedtls_aes_free( mbedtls_aes_context *ctx ); +void mbedtls_aes_free(mbedtls_aes_context *ctx); /** * \brief AES key schedule (encryption) @@ -91,8 +74,8 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ); * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ -int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); /** * \brief AES key schedule (decryption) @@ -103,8 +86,8 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ -int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); /** * \brief AES-ECB block encryption/decryption @@ -116,10 +99,10 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, * * \return 0 if successful */ -int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** @@ -144,12 +127,12 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH */ -int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); +int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) @@ -178,13 +161,13 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, * * \return 0 if successful */ -int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); +int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); /** * \brief AES-CFB8 buffer encryption/decryption. @@ -210,12 +193,12 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, * * \return 0 if successful */ -int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); +int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); #endif /*MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) @@ -241,13 +224,13 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, * * \return 0 if successful */ -int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); +int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ /** @@ -261,9 +244,9 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, * * \return 0 if successful */ -int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); /** * \brief Internal AES block decryption function @@ -276,9 +259,9 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, * * \return 0 if successful */ -int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); #if !defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) @@ -298,11 +281,11 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, * \param output Output (ciphertext) block */ MBEDTLS_DEPRECATED static inline void mbedtls_aes_encrypt( - mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) + mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) { - mbedtls_internal_aes_encrypt( ctx, input, output ); + mbedtls_internal_aes_encrypt(ctx, input, output); } /** @@ -317,11 +300,11 @@ MBEDTLS_DEPRECATED static inline void mbedtls_aes_encrypt( * \param output Output (plaintext) block */ MBEDTLS_DEPRECATED static inline void mbedtls_aes_decrypt( - mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) + mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) { - mbedtls_internal_aes_decrypt( ctx, input, output ); + mbedtls_internal_aes_decrypt(ctx, input, output); } #undef MBEDTLS_DEPRECATED @@ -344,7 +327,7 @@ extern "C" { * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_aes_self_test( int verbose ); +int mbedtls_aes_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/asn1.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/asn1.h similarity index 75% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/asn1.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/asn1.h index 082832c..b561b49 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/asn1.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/asn1.h @@ -1,38 +1,22 @@ -/** - * \file asn1.h - * - * \brief Generic ASN.1 parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_ASN1_H #define MBEDTLS_ASN1_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include #if defined(MBEDTLS_BIGNUM_C) -#include "bignum.h" + #include "bignum.h" #endif /** @@ -100,8 +84,8 @@ * 'unsigned char *oid' here! */ #define MBEDTLS_OID_CMP(oid_str, oid_buf) \ - ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ - memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) #ifdef __cplusplus extern "C" { @@ -115,8 +99,7 @@ extern "C" { /** * Type-length-value structure that allows for ASN1 using DER. */ -typedef struct mbedtls_asn1_buf -{ +typedef struct mbedtls_asn1_buf { int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ size_t len; /**< ASN1 length, in octets. */ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ @@ -126,8 +109,7 @@ mbedtls_asn1_buf; /** * Container for ASN1 bit strings. */ -typedef struct mbedtls_asn1_bitstring -{ +typedef struct mbedtls_asn1_bitstring { size_t len; /**< ASN1 length, in octets. */ unsigned char unused_bits; /**< Number of unused bits at the end of the string */ unsigned char *p; /**< Raw ASN1 data for the bit string */ @@ -137,8 +119,7 @@ mbedtls_asn1_bitstring; /** * Container for a sequence of ASN.1 items */ -typedef struct mbedtls_asn1_sequence -{ +typedef struct mbedtls_asn1_sequence { mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ } @@ -147,8 +128,7 @@ mbedtls_asn1_sequence; /** * Container for a sequence or list of 'named' ASN.1 data items */ -typedef struct mbedtls_asn1_named_data -{ +typedef struct mbedtls_asn1_named_data { mbedtls_asn1_buf oid; /**< The object identifier. */ mbedtls_asn1_buf val; /**< The named value. */ struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ @@ -168,9 +148,9 @@ mbedtls_asn1_named_data; * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is * unparseable. */ -int mbedtls_asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ); +int mbedtls_asn1_get_len(unsigned char **p, + const unsigned char *end, + size_t *len); /** * \brief Get the tag and length of the tag. Check for the requested tag. @@ -184,9 +164,9 @@ int mbedtls_asn1_get_len( unsigned char **p, * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did * not match requested tag, or another specific ASN.1 error code. */ -int mbedtls_asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ); +int mbedtls_asn1_get_tag(unsigned char **p, + const unsigned char *end, + size_t *len, int tag); /** * \brief Retrieve a boolean ASN.1 tag and its value. @@ -198,9 +178,9 @@ int mbedtls_asn1_get_tag( unsigned char **p, * * \return 0 if successful or a specific ASN.1 error code. */ -int mbedtls_asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ); +int mbedtls_asn1_get_bool(unsigned char **p, + const unsigned char *end, + int *val); /** * \brief Retrieve an integer ASN.1 tag and its value. @@ -212,9 +192,9 @@ int mbedtls_asn1_get_bool( unsigned char **p, * * \return 0 if successful or a specific ASN.1 error code. */ -int mbedtls_asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ); +int mbedtls_asn1_get_int(unsigned char **p, + const unsigned char *end, + int *val); /** * \brief Retrieve a bitstring ASN.1 tag and its value. @@ -226,8 +206,8 @@ int mbedtls_asn1_get_int( unsigned char **p, * * \return 0 if successful or a specific ASN.1 error code. */ -int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, - mbedtls_asn1_bitstring *bs); +int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs); /** * \brief Retrieve a bitstring ASN.1 tag without unused bits and its @@ -240,8 +220,8 @@ int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, * * \return 0 if successful or a specific ASN.1 error code. */ -int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, - size_t *len ); +int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, + size_t *len); /** * \brief Parses and splits an ASN.1 "SEQUENCE OF " @@ -254,10 +234,10 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end * * \return 0 if successful or a specific ASN.1 error code. */ -int mbedtls_asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_sequence *cur, - int tag); +int mbedtls_asn1_get_sequence_of(unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag); #if defined(MBEDTLS_BIGNUM_C) /** @@ -270,9 +250,9 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p, * * \return 0 if successful or a specific ASN.1 or MPI error code. */ -int mbedtls_asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X ); +int mbedtls_asn1_get_mpi(unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X); #endif /* MBEDTLS_BIGNUM_C */ /** @@ -287,9 +267,9 @@ int mbedtls_asn1_get_mpi( unsigned char **p, * * \return 0 if successful or a specific ASN.1 or MPI error code. */ -int mbedtls_asn1_get_alg( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); +int mbedtls_asn1_get_alg(unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params); /** * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no @@ -303,9 +283,9 @@ int mbedtls_asn1_get_alg( unsigned char **p, * * \return 0 if successful or a specific ASN.1 or MPI error code. */ -int mbedtls_asn1_get_alg_null( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg ); +int mbedtls_asn1_get_alg_null(unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg); /** * \brief Find a specific named_data entry in a sequence or list based on @@ -317,15 +297,15 @@ int mbedtls_asn1_get_alg_null( unsigned char **p, * * \return NULL if not found, or a pointer to the existing entry. */ -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, - const char *oid, size_t len ); +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list, + const char *oid, size_t len); /** * \brief Free a mbedtls_asn1_named_data entry * * \param entry The named data entry to free */ -void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); +void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); /** * \brief Free all entries in a mbedtls_asn1_named_data list @@ -333,7 +313,7 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); * * \param head Pointer to the head of the list of named data entries to free */ -void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); +void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/base64.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/base64.h similarity index 64% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/base64.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/base64.h index 352c652..ef2cd0b 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/base64.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/base64.h @@ -1,25 +1,9 @@ -/** - * \file base64.h - * - * \brief RFC 1521 base64 encoding/decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H @@ -51,8 +35,8 @@ extern "C" { * \note Call this function with dlen = 0 to obtain the * required buffer size in *olen */ -int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); +int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen); /** * \brief Decode a base64-formatted buffer @@ -71,15 +55,15 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, * \note Call this function with *dst = NULL or dlen = 0 to obtain * the required buffer size in *olen */ -int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); +int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_base64_self_test( int verbose ); +int mbedtls_base64_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/bignum.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/bignum.h similarity index 75% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/bignum.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/bignum.h index aa51556..4781c6b 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/bignum.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/bignum.h @@ -1,39 +1,23 @@ -/** - * \file bignum.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_BIGNUM_H #define MBEDTLS_BIGNUM_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include #include #if defined(MBEDTLS_FS_IO) -#include + #include #endif #define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ @@ -53,27 +37,27 @@ #define MBEDTLS_MPI_MAX_LIMBS 10000 #if !defined(MBEDTLS_MPI_WINDOW_SIZE) -/* - * Maximum window size used for modular exponentiation. Default: 6 - * Minimum value: 1. Maximum value: 6. - * - * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) - * - * Reduction in size, reduces speed. - */ -#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ + /* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ + #define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ #endif /* !MBEDTLS_MPI_WINDOW_SIZE */ #if !defined(MBEDTLS_MPI_MAX_SIZE) -/* - * Maximum size of MPIs allowed in bits and bytes for user-MPIs. - * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) - * - * Note: Calculations can results temporarily in larger MPIs. So the number - * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. - */ -#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + /* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ + #define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ #endif /* !MBEDTLS_MPI_MAX_SIZE */ #define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ @@ -108,30 +92,30 @@ */ #if ( ! defined(MBEDTLS_HAVE_INT32) && \ defined(_MSC_VER) && defined(_M_AMD64) ) - #define MBEDTLS_HAVE_INT64 - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; +#define MBEDTLS_HAVE_INT64 +typedef int64_t mbedtls_mpi_sint; +typedef uint64_t mbedtls_mpi_uint; #else - #if ( ! defined(MBEDTLS_HAVE_INT32) && \ +#if ( ! defined(MBEDTLS_HAVE_INT32) && \ defined(__GNUC__) && ( \ defined(__amd64__) || defined(__x86_64__) || \ defined(__ppc64__) || defined(__powerpc64__) || \ defined(__ia64__) || defined(__alpha__) || \ (defined(__sparc__) && defined(__arch64__)) || \ defined(__s390x__) || defined(__mips64) ) ) - #define MBEDTLS_HAVE_INT64 - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); - #define MBEDTLS_HAVE_UDBL - #else - #define MBEDTLS_HAVE_INT32 - typedef int32_t mbedtls_mpi_sint; - typedef uint32_t mbedtls_mpi_uint; - typedef uint64_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_HAVE_INT32 && __GNUC__ && 64-bit platform */ +#define MBEDTLS_HAVE_INT64 +typedef int64_t mbedtls_mpi_sint; +typedef uint64_t mbedtls_mpi_uint; +/* mbedtls_t_udbl defined as 128-bit unsigned int */ +typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); +#define MBEDTLS_HAVE_UDBL +#else +#define MBEDTLS_HAVE_INT32 +typedef int32_t mbedtls_mpi_sint; +typedef uint32_t mbedtls_mpi_uint; +typedef uint64_t mbedtls_t_udbl; +#define MBEDTLS_HAVE_UDBL +#endif /* !MBEDTLS_HAVE_INT32 && __GNUC__ && 64-bit platform */ #endif /* !MBEDTLS_HAVE_INT32 && _MSC_VER && _M_AMD64 */ #ifdef __cplusplus @@ -141,8 +125,7 @@ extern "C" { /** * \brief MPI structure */ -typedef struct -{ +typedef struct { int s; /*!< integer sign */ size_t n; /*!< total # of limbs */ mbedtls_mpi_uint *p; /*!< pointer to limbs */ @@ -156,14 +139,14 @@ mbedtls_mpi; * * \param X One MPI to initialize. */ -void mbedtls_mpi_init( mbedtls_mpi *X ); +void mbedtls_mpi_init(mbedtls_mpi *X); /** * \brief Unallocate one MPI * * \param X One MPI to unallocate. */ -void mbedtls_mpi_free( mbedtls_mpi *X ); +void mbedtls_mpi_free(mbedtls_mpi *X); /** * \brief Enlarge to the specified number of limbs @@ -174,7 +157,7 @@ void mbedtls_mpi_free( mbedtls_mpi *X ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); +int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs); /** * \brief Resize down, keeping at least the specified number of limbs @@ -185,7 +168,7 @@ int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); +int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs); /** * \brief Copy the contents of Y into X @@ -196,7 +179,7 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); +int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Swap the contents of X and Y @@ -204,7 +187,7 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); * \param X First MPI value * \param Y Second MPI value */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); +void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y); /** * \brief Safe conditional assignement X = Y if assign is 1 @@ -223,7 +206,7 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); * information through branch prediction and/or memory access * patterns analysis). */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); +int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign); /** * \brief Safe conditional swap X <-> Y if swap is 1 @@ -242,7 +225,7 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned * information through branch prediction and/or memory access * patterns analysis). */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); +int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign); /** * \brief Set value from integer @@ -253,7 +236,7 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char as * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); +int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z); /** * \brief Get a specific bit from X @@ -263,7 +246,7 @@ int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); * * \return Either a 0 or a 1 */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); +int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos); /** * \brief Set a bit of X to a specific value of 0 or 1 @@ -279,7 +262,7 @@ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); +int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val); /** * \brief Return the number of zero-bits before the least significant @@ -289,7 +272,7 @@ int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); * * \param X MPI to use */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); +size_t mbedtls_mpi_lsb(const mbedtls_mpi *X); /** * \brief Return the number of bits up to and including the most @@ -299,14 +282,14 @@ size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); * * \param X MPI to use */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); +size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X); /** * \brief Return the total size in bytes * * \param X MPI to use */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ); +size_t mbedtls_mpi_size(const mbedtls_mpi *X); /** * \brief Import from an ASCII string @@ -317,7 +300,7 @@ size_t mbedtls_mpi_size( const mbedtls_mpi *X ); * * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); +int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s); /** * \brief Export into an ASCII string @@ -335,8 +318,8 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); * \note Call this function with buflen = 0 to obtain the * minimum required buffer size in *olen. */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ); +int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen); #if defined(MBEDTLS_FS_IO) /** @@ -350,7 +333,7 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, * the file read buffer is too small or a * MBEDTLS_ERR_MPI_XXX error code */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); +int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin); /** * \brief Write X into an opened file, or stdout if fout is NULL @@ -364,7 +347,7 @@ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); * * \note Set fout == NULL to print X on the console. */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout); #endif /* MBEDTLS_FS_IO */ /** @@ -377,7 +360,7 @@ int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); +int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); /** * \brief Export X into unsigned binary data, big endian. @@ -391,7 +374,7 @@ int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t bu * \return 0 if successful, * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); +int mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); /** * \brief Left-shift: X <<= count @@ -402,7 +385,7 @@ int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t b * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); +int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count); /** * \brief Right-shift: X >>= count @@ -413,7 +396,7 @@ int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); +int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count); /** * \brief Compare unsigned values @@ -425,7 +408,7 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); * -1 if |X| is lesser than |Y| or * 0 if |X| is equal to |Y| */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); +int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Compare signed values @@ -437,7 +420,7 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); * -1 if X is lesser than Y or * 0 if X is equal to Y */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); +int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Compare signed values @@ -449,7 +432,7 @@ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); * -1 if X is lesser than z or * 0 if X is equal to z */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); +int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z); /** * \brief Unsigned addition: X = |A| + |B| @@ -461,7 +444,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Unsigned subtraction: X = |A| - |B| @@ -473,7 +456,7 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * \return 0 if successful, * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Signed addition: X = A + B @@ -485,7 +468,7 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Signed subtraction: X = A - B @@ -497,7 +480,7 @@ int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Signed addition: X = A + b @@ -509,7 +492,7 @@ int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Signed subtraction: X = A - b @@ -521,7 +504,7 @@ int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Baseline multiplication: X = A * B @@ -533,7 +516,7 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Baseline multiplication: X = A * b @@ -547,7 +530,7 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); +int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b); /** * \brief Division by mbedtls_mpi: A = Q * B + R @@ -563,7 +546,7 @@ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint * * \note Either Q or R can be NULL. */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Division by int: A = Q * b + R @@ -579,7 +562,7 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, c * * \note Either Q or R can be NULL. */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Modulo: R = A mod B @@ -593,7 +576,7 @@ int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, m * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Modulo: r = A mod b @@ -607,7 +590,7 @@ int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Sliding-window exponentiation: X = A^E mod N @@ -627,7 +610,8 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_ * multiple calls, which speeds up things a bit. It can * be set to NULL if the extra performance is unneeded. */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); +int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR); /** * \brief Fill an MPI X with size bytes of random @@ -640,9 +624,9 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Greatest common divisor: G = gcd(A, B) @@ -654,7 +638,7 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Modular inverse: X = A^-1 mod N @@ -668,7 +652,7 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or nil MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); +int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N); /** * \brief Miller-Rabin primality test @@ -681,9 +665,9 @@ int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_mpi_is_prime(const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Prime number generation @@ -699,16 +683,16 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_mpi_self_test( int verbose ); +int mbedtls_mpi_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/bn_mul.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/bn_mul.h similarity index 97% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/bn_mul.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/bn_mul.h index cac3f14..30b487a 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/bn_mul.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/bn_mul.h @@ -1,25 +1,9 @@ -/** - * \file bn_mul.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * Multiply source vector [s] with b, add result * to destination vector [d] and set carry c. diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/check_config.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/check_config.h similarity index 96% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/check_config.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/check_config.h index dab1113..6d600fe 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/check_config.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/check_config.h @@ -1,26 +1,10 @@ -/** - * \file check_config.h - * - * \brief Consistency checks for configuration options - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * It is recommended to include this file from your config.h * in order to catch dependency issues early. diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/cipher.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/cipher.h similarity index 81% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/cipher.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/cipher.h index b12e388..763ed43 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/cipher.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/cipher.h @@ -1,54 +1,36 @@ -/** - * \file cipher.h - * - * \brief Generic cipher wrapper. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_CIPHER_H #define MBEDTLS_CIPHER_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) -#define MBEDTLS_CIPHER_MODE_AEAD + #define MBEDTLS_CIPHER_MODE_AEAD #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_CIPHER_MODE_WITH_PADDING + #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif #if defined(MBEDTLS_ARC4_C) -#define MBEDTLS_CIPHER_MODE_STREAM + #define MBEDTLS_CIPHER_MODE_STREAM #endif #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) -#define inline __inline + #define inline __inline #endif #define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ @@ -196,7 +178,7 @@ typedef struct { unsigned int key_bitlen; /** Name of the cipher */ - const char * name; + const char *name; /** IV/NONCE size, in bytes. * For cipher that accept many sizes: recommended size */ @@ -228,8 +210,8 @@ typedef struct { #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** Padding functions to use, if relevant for cipher mode */ - void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); - int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); + void (*add_padding)(unsigned char *output, size_t olen, size_t data_len); + int (*get_padding)(unsigned char *input, size_t ilen, size_t *data_len); #endif /** Buffer for data that hasn't been encrypted yet */ @@ -259,7 +241,7 @@ typedef struct { * \return a statically allocated array of ciphers, the last entry * is 0. */ -const int *mbedtls_cipher_list( void ); +const int *mbedtls_cipher_list(void); /** * \brief Returns the cipher information structure associated @@ -270,7 +252,7 @@ const int *mbedtls_cipher_list( void ); * \return the cipher information structure associated with the * given cipher_name, or NULL if not found. */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_name); /** * \brief Returns the cipher information structure associated @@ -281,7 +263,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher * \return the cipher information structure associated with the * given cipher_type, or NULL if not found. */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type); /** * \brief Returns the cipher information structure associated @@ -295,21 +277,21 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher * \return the cipher information structure associated with the * given cipher_type, or NULL if not found. */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, - int key_bitlen, - const mbedtls_cipher_mode_t mode ); +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode); /** * \brief Initialize a cipher_context (as NONE) */ -void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); +void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx); /** * \brief Free and clear the cipher-specific context of ctx. * Freeing ctx itself remains the responsibility of the * caller. */ -void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); +void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx); /** * \brief Initialises and fills the cipher context structure with @@ -327,7 +309,7 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); * MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context failed. */ -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); +int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); /** * \brief Returns the block size of the given cipher. @@ -337,10 +319,11 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in * \return size of the cipher's blocks, or 0 if ctx has not been * initialised. */ -static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +static inline unsigned int mbedtls_cipher_get_block_size(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return 0; + } return ctx->cipher_info->block_size; } @@ -354,10 +337,11 @@ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_c * \return mode of operation, or MBEDTLS_MODE_NONE if ctx * has not been initialised. */ -static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return MBEDTLS_MODE_NONE; + } return ctx->cipher_info->mode; } @@ -371,13 +355,15 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtl * (0 for ciphers not using IV/NONCE). * If IV has already been set: actual size. */ -static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +static inline int mbedtls_cipher_get_iv_size(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return 0; + } - if( ctx->iv_size != 0 ) + if (ctx->iv_size != 0) { return (int) ctx->iv_size; + } return (int) ctx->cipher_info->iv_size; } @@ -390,10 +376,11 @@ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ct * \return type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has * not been initialised. */ -static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return MBEDTLS_CIPHER_NONE; + } return ctx->cipher_info->type; } @@ -405,10 +392,11 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_ciphe * * \return name of the cipher, or NULL if ctx was not initialised. */ -static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +static inline const char *mbedtls_cipher_get_name(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return 0; + } return ctx->cipher_info->name; } @@ -422,10 +410,11 @@ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_ * MBEDTLS_KEY_LENGTH_NONE if ctx has not been * initialised. */ -static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +static inline int mbedtls_cipher_get_key_bitlen(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return MBEDTLS_KEY_LENGTH_NONE; + } return (int) ctx->cipher_info->key_bitlen; } @@ -439,10 +428,11 @@ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t * or MBEDTLS_OPERATION_NONE if ctx has not been * initialised. */ -static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_operation_t mbedtls_cipher_get_operation(const mbedtls_cipher_context_t *ctx) { - if( NULL == ctx || NULL == ctx->cipher_info ) + if (NULL == ctx || NULL == ctx->cipher_info) { return MBEDTLS_OPERATION_NONE; + } return ctx->operation; } @@ -462,8 +452,8 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci * parameter verification fails or a cipher specific * error code. */ -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ); +int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** @@ -478,7 +468,7 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * does not support padding. */ -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode); #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ /** @@ -494,8 +484,8 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph * \note Some ciphers don't use IVs nor NONCE. For these * ciphers, this function has no effect. */ -int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ); +int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len); /** * \brief Finish preparation of the given context @@ -505,7 +495,7 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA * if parameter verification fails. */ -int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); +int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx); #if defined(MBEDTLS_GCM_C) /** @@ -519,8 +509,8 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); * * \return 0 on success, or a specific error code. */ -int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ); +int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len); #endif /* MBEDTLS_GCM_C */ /** @@ -552,8 +542,8 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, * function, except the last one before mbedtls_cipher_finish(), * must have ilen a multiple of the block size. */ -int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen ); +int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen); /** * \brief Generic cipher finalisation function. If data still @@ -572,8 +562,8 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding * while decrypting or a cipher specific error code. */ -int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output, size_t *olen ); +int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen); #if defined(MBEDTLS_GCM_C) /** @@ -587,8 +577,8 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, * * \return 0 on success, or a specific error code. */ -int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, - unsigned char *tag, size_t tag_len ); +int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len); /** * \brief Check tag for AEAD ciphers. @@ -601,8 +591,8 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, * * \return 0 on success, or a specific error code. */ -int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, - const unsigned char *tag, size_t tag_len ); +int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len); #endif /* MBEDTLS_GCM_C */ /** @@ -632,10 +622,10 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, * while decrypting, or * a cipher specific error code. */ -int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ); +int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen); #if defined(MBEDTLS_CIPHER_MODE_AEAD) /** @@ -660,12 +650,12 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or * a cipher specific error code. */ -int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ); +int mbedtls_cipher_auth_encrypt(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len); /** * \brief Generic autenticated decryption (AEAD ciphers). @@ -694,12 +684,12 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, * is zeroed out to prevent the unauthentic plaintext to * be used by mistake, making this interface safer. */ -int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len ); +int mbedtls_cipher_auth_decrypt(mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len); #endif /* MBEDTLS_CIPHER_MODE_AEAD */ #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/cipher_internal.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/cipher_internal.h similarity index 74% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/cipher_internal.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/cipher_internal.h index 6c58bcc..db57b2e 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/cipher_internal.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/cipher_internal.h @@ -1,27 +1,9 @@ -/** - * \file cipher_internal.h - * - * \brief Cipher wrappers. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_CIPHER_WRAP_H #define MBEDTLS_CIPHER_WRAP_H diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/config.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/config.h similarity index 98% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/config.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/config.h index a55d787..cc1763c 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/config.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/config.h @@ -1,35 +1,12 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ #ifndef MBEDTLS_CONFIG_H #define MBEDTLS_CONFIG_H #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 + #define _CRT_SECURE_NO_DEPRECATE 1 #endif /** @@ -408,7 +385,7 @@ * * Enable Cipher Feedback mode (CFB) for symmetric ciphers. */ -//#define MBEDTLS_CIPHER_MODE_CFB +#define MBEDTLS_CIPHER_MODE_CFB /** * \def MBEDTLS_CIPHER_MODE_CTR @@ -1150,7 +1127,7 @@ * * Comment this macro to disable support for the max_fragment_length extension */ -//#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH /** * \def MBEDTLS_SSL_PROTO_SSL3 @@ -1993,7 +1970,7 @@ * This module is required for SSL/TLS and X.509. * PEM_PARSE uses MD5 for decrypting encrypted keys. */ -//#define MBEDTLS_MD5_C +// #define MBEDTLS_MD5_C /** * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C @@ -2642,7 +2619,7 @@ //#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h" #if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE + #include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE #endif /* @@ -2653,9 +2630,9 @@ * - without yotta is looks weird to have a YOTTA prefix. */ #if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE + #include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE #elif defined(MBEDTLS_USER_CONFIG_FILE) -#include MBEDTLS_USER_CONFIG_FILE + #include MBEDTLS_USER_CONFIG_FILE #endif #include "check_config.h" diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ctr_drbg.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ctr_drbg.h similarity index 67% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ctr_drbg.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/ctr_drbg.h index 059d3c5..7b78285 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ctr_drbg.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ctr_drbg.h @@ -1,32 +1,16 @@ -/** - * \file ctr_drbg.h - * - * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H #include "aes.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" + #include "mbedtls/threading.h" #endif #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ @@ -38,7 +22,7 @@ #define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ #define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) #define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) - /**< The seed length (counter + AES key) */ +/**< The seed length (counter + AES key) */ /** * \name SECTION: Module settings @@ -49,27 +33,27 @@ */ #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -#else -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -#endif + #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) + #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ + #else + #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ + #endif #endif #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) -#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ + #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ + #define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) -#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ + #define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ #endif /* \} name SECTION: Module settings */ @@ -84,8 +68,7 @@ extern "C" { /** * \brief CTR_DRBG context structure */ -typedef struct -{ +typedef struct { unsigned char counter[16]; /*!< counter (V) */ int reseed_counter; /*!< reseed counter */ int prediction_resistance; /*!< enable prediction resistance (Automatic @@ -116,7 +99,7 @@ mbedtls_ctr_drbg_context; * * \param ctx CTR_DRBG context to be initialized */ -void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); +void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx); /** * \brief CTR_DRBG initial seeding @@ -136,18 +119,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * \return 0 if successful, or * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED */ -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ); +int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len); /** * \brief Clear CTR_CRBG context data * * \param ctx CTR_DRBG context to clear */ -void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); +void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx); /** * \brief Enable / disable prediction resistance (Default: Off) @@ -158,8 +141,8 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); * \param ctx CTR_DRBG context * \param resistance MBEDTLS_CTR_DRBG_PR_ON or MBEDTLS_CTR_DRBG_PR_OFF */ -void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, - int resistance ); +void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, + int resistance); /** * \brief Set the amount of entropy grabbed on each (re)seed @@ -168,8 +151,8 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, * \param ctx CTR_DRBG context * \param len Amount of entropy to grab */ -void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, - size_t len ); +void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, + size_t len); /** * \brief Set the reseed interval @@ -178,8 +161,8 @@ void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, * \param ctx CTR_DRBG context * \param interval Reseed interval */ -void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, - int interval ); +void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, + int interval); /** * \brief CTR_DRBG reseeding (extracts data from entropy source) @@ -191,8 +174,8 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, * \return 0 if successful, or * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED */ -int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ); +int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len); /** * \brief CTR_DRBG update state @@ -205,8 +188,8 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, * only the first MBEDTLS_CTR_DRBG_MAX_SEED_INPUT bytes are used, * the remaining ones are silently discarded. */ -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); +void mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len); /** * \brief CTR_DRBG generate random with additional update input @@ -223,9 +206,9 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG */ -int mbedtls_ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ); +int mbedtls_ctr_drbg_random_with_add(void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len); /** * \brief CTR_DRBG generate random @@ -240,8 +223,8 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG */ -int mbedtls_ctr_drbg_random( void *p_rng, - unsigned char *output, size_t output_len ); +int mbedtls_ctr_drbg_random(void *p_rng, + unsigned char *output, size_t output_len); #if defined(MBEDTLS_FS_IO) /** @@ -254,7 +237,7 @@ int mbedtls_ctr_drbg_random( void *p_rng, * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED */ -int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); /** * \brief Read and update a seed file. Seed is added to this @@ -268,7 +251,7 @@ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG */ -int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ /** @@ -276,12 +259,12 @@ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_ctr_drbg_self_test( int verbose ); +int mbedtls_ctr_drbg_self_test(int verbose); /* Internal functions (do not call directly) */ -int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, - int (*)(void *, unsigned char *, size_t), void *, - const unsigned char *, size_t, size_t ); +int mbedtls_ctr_drbg_seed_entropy_len(mbedtls_ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/debug.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/debug.h similarity index 76% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/debug.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/debug.h index 2957996..e62f676 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/debug.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/debug.h @@ -1,38 +1,24 @@ -/** - * \file debug.h - * - * \brief Functions for controlling and providing debug output from the library. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_DEBUG_H #define MBEDTLS_DEBUG_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "ssl.h" +#define tls_info(...) log_info("tls", __VA_ARGS__) + #if defined(MBEDTLS_ECP_C) -#include "ecp.h" + #include "ecp.h" #endif #if defined(MBEDTLS_DEBUG_C) @@ -94,7 +80,7 @@ extern "C" { * - 3 Informational * - 4 Verbose */ -void mbedtls_debug_set_threshold( int threshold ); +void mbedtls_debug_set_threshold(int threshold); /** * \brief Print a message to the debug output. This function is always used @@ -111,9 +97,9 @@ void mbedtls_debug_set_threshold( int threshold ); * \attention This function is intended for INTERNAL usage within the * library only. */ -void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ... ); +void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ...); /** * \brief Print the return value of a function to the debug output. This @@ -130,9 +116,9 @@ void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, * \attention This function is intended for INTERNAL usage within the * library only. */ -void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ); +void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret); /** * \brief Output a buffer of size len bytes to the debug output. This function @@ -151,9 +137,9 @@ void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, * \attention This function is intended for INTERNAL usage within the * library only. */ -void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len ); +void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len); #if defined(MBEDTLS_BIGNUM_C) /** @@ -172,9 +158,9 @@ void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, * \attention This function is intended for INTERNAL usage within the * library only. */ -void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X ); +void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X); #endif #if defined(MBEDTLS_ECP_C) @@ -194,9 +180,9 @@ void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, * \attention This function is intended for INTERNAL usage within the * library only. */ -void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X ); +void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -215,9 +201,9 @@ void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, * \attention This function is intended for INTERNAL usage within the * library only. */ -void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt ); +void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt); #endif #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/des.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/des.h similarity index 66% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/des.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/des.h index 5ca2ecf..a2ce882 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/des.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/des.h @@ -1,32 +1,16 @@ -/** - * \file des.h - * - * \brief DES block cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_DES_H #define MBEDTLS_DES_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include @@ -50,8 +34,7 @@ extern "C" { /** * \brief DES context structure */ -typedef struct -{ +typedef struct { uint32_t sk[32]; /*!< DES subkeys */ } mbedtls_des_context; @@ -59,8 +42,7 @@ mbedtls_des_context; /** * \brief Triple-DES context structure */ -typedef struct -{ +typedef struct { uint32_t sk[96]; /*!< 3DES subkeys */ } mbedtls_des3_context; @@ -70,28 +52,28 @@ mbedtls_des3_context; * * \param ctx DES context to be initialized */ -void mbedtls_des_init( mbedtls_des_context *ctx ); +void mbedtls_des_init(mbedtls_des_context *ctx); /** * \brief Clear DES context * * \param ctx DES context to be cleared */ -void mbedtls_des_free( mbedtls_des_context *ctx ); +void mbedtls_des_free(mbedtls_des_context *ctx); /** * \brief Initialize Triple-DES context * * \param ctx DES3 context to be initialized */ -void mbedtls_des3_init( mbedtls_des3_context *ctx ); +void mbedtls_des3_init(mbedtls_des3_context *ctx); /** * \brief Clear Triple-DES context * * \param ctx DES3 context to be cleared */ -void mbedtls_des3_free( mbedtls_des3_context *ctx ); +void mbedtls_des3_free(mbedtls_des3_context *ctx); /** * \brief Set key parity on the given key to odd. @@ -101,7 +83,7 @@ void mbedtls_des3_free( mbedtls_des3_context *ctx ); * * \param key 8-byte secret key */ -void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Check that key parity on the given key is odd. @@ -113,7 +95,7 @@ void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); * * \return 0 is parity was ok, 1 if parity was not correct. */ -int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Check that key is not a weak or semi-weak DES key @@ -122,7 +104,7 @@ int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SI * * \return 0 if no weak key was found, 1 if a weak key was identified. */ -int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief DES key schedule (56-bit, encryption) @@ -132,7 +114,7 @@ int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); * * \return 0 */ -int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief DES key schedule (56-bit, decryption) @@ -142,7 +124,7 @@ int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MB * * \return 0 */ -int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Triple-DES key schedule (112-bit, encryption) @@ -152,8 +134,8 @@ int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MB * * \return 0 */ -int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); +int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (112-bit, decryption) @@ -163,8 +145,8 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, * * \return 0 */ -int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); +int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (168-bit, encryption) @@ -174,8 +156,8 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, * * \return 0 */ -int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); +int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief Triple-DES key schedule (168-bit, decryption) @@ -185,8 +167,8 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, * * \return 0 */ -int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); +int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief DES-ECB block encryption/decryption @@ -197,9 +179,9 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, * * \return 0 if successful */ -int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); +int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** @@ -220,12 +202,12 @@ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, * \param input buffer holding the input data * \param output buffer holding the output data */ -int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); +int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ /** @@ -237,9 +219,9 @@ int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, * * \return 0 if successful */ -int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); +int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** @@ -262,12 +244,12 @@ int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, * * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH */ -int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); +int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ /** @@ -278,8 +260,8 @@ int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, * \param SK Round keys * \param key Base key */ -void mbedtls_des_setkey( uint32_t SK[32], - const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); +void mbedtls_des_setkey(uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE]); #ifdef __cplusplus } #endif @@ -297,7 +279,7 @@ extern "C" { * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_des_self_test( int verbose ); +int mbedtls_des_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ecp.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ecp.h similarity index 83% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ecp.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/ecp.h index bf9abef..da8699c 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ecp.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ecp.h @@ -1,25 +1,9 @@ -/** - * \file ecp.h - * - * \brief Elliptic curves over GF(p) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H @@ -59,8 +43,7 @@ extern "C" { * parameters. Therefore, only well-known domain parameters from trusted * sources should be used. See mbedtls_ecp_group_load(). */ -typedef enum -{ +typedef enum { MBEDTLS_ECP_DP_NONE = 0, MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ @@ -86,8 +69,7 @@ typedef enum /** * Curve information for use by other modules */ -typedef struct -{ +typedef struct { mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ uint16_t tls_id; /*!< TLS NamedCurve identifier */ uint16_t bit_size; /*!< Curve size in bits */ @@ -103,8 +85,7 @@ typedef struct * The point is zero, or "at infinity", if Z == 0. * Otherwise, X and Y are its standard (affine) coordinates. */ -typedef struct -{ +typedef struct { mbedtls_mpi X; /*!< the point's X coordinate */ mbedtls_mpi Y; /*!< the point's Y coordinate */ mbedtls_mpi Z; /*!< the point's Z coordinate */ @@ -135,8 +116,7 @@ mbedtls_ecp_point; * range by a few additions or substractions. It must return 0 on success and * non-zero on failure. */ -typedef struct -{ +typedef struct { mbedtls_ecp_group_id id; /*!< internal group identifier */ mbedtls_mpi P; /*!< prime modulus of the base field */ mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ @@ -162,8 +142,7 @@ mbedtls_ecp_group; * * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. */ -typedef struct -{ +typedef struct { mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ mbedtls_mpi d; /*!< our secret value */ mbedtls_ecp_point Q; /*!< our public value */ @@ -246,7 +225,7 @@ mbedtls_ecp_keypair; * * \return A statically allocated array, the last entry is 0. */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void); /** * \brief Get the list of supported curves in order of preferrence @@ -255,7 +234,7 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); * \return A statically allocated array, * terminated with MBEDTLS_ECP_DP_NONE. */ -const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void); /** * \brief Get curve information from an internal group identifier @@ -264,7 +243,7 @@ const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); * * \return The associated curve information or NULL */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id); /** * \brief Get curve information from a TLS NamedCurve value @@ -273,7 +252,7 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_gr * * \return The associated curve information or NULL */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id); /** * \brief Get curve information from a human-readable name @@ -282,37 +261,37 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_i * * \return The associated curve information or NULL */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name); /** * \brief Initialize a point (as zero) */ -void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); +void mbedtls_ecp_point_init(mbedtls_ecp_point *pt); /** * \brief Initialize a group (to something meaningless) */ -void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); +void mbedtls_ecp_group_init(mbedtls_ecp_group *grp); /** * \brief Initialize a key pair (as an invalid one) */ -void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); +void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key); /** * \brief Free the components of a point */ -void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); +void mbedtls_ecp_point_free(mbedtls_ecp_point *pt); /** * \brief Free the components of an ECP group */ -void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); +void mbedtls_ecp_group_free(mbedtls_ecp_group *grp); /** * \brief Free the components of a key pair */ -void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); +void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key); /** * \brief Copy the contents of point Q into P @@ -323,7 +302,7 @@ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); +int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); /** * \brief Copy the contents of a group object @@ -334,7 +313,7 @@ int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); +int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src); /** * \brief Set a point to zero @@ -344,7 +323,7 @@ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); +int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt); /** * \brief Tell if a point is zero @@ -353,7 +332,7 @@ int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); * * \return 1 if point is zero, 0 otherwise */ -int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); +int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt); /** * \brief Compare two points @@ -367,8 +346,8 @@ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); * \return 0 if the points are equal, * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise */ -int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ); +int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q); /** * \brief Import a non-zero point from two ASCII strings @@ -380,8 +359,8 @@ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, * * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code */ -int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, - const char *x, const char *y ); +int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, + const char *x, const char *y); /** * \brief Export a point into unsigned binary data @@ -397,9 +376,9 @@ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ); +int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen); /** * \brief Import a point from unsigned binary data @@ -419,8 +398,8 @@ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ * belongs to the given group, see mbedtls_ecp_check_pubkey() for * that. */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - const unsigned char *buf, size_t ilen ); +int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen); /** * \brief Import a point from a TLS ECPoint record @@ -436,8 +415,8 @@ int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_poi * MBEDTLS_ERR_MPI_XXX if initialization failed * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t len ); +int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len); /** * \brief Export a point as a TLS ECPoint record @@ -453,9 +432,9 @@ int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ); +int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen); /** * \brief Set a group using well-known domain parameters @@ -470,7 +449,7 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp * \note Index should be a value of RFC 4492's enum NamedCurve, * usually in the form of a MBEDTLS_ECP_DP_XXX macro. */ -int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id index ); +int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id index); /** * \brief Set a group from a TLS ECParameters record @@ -485,7 +464,7 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id index ) * MBEDTLS_ERR_MPI_XXX if initialization failed * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); +int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len); /** * \brief Write the TLS ECParameters record for a group @@ -498,8 +477,8 @@ int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **bu * \return 0 if successful, * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ); +int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen); /** * \brief Multiplication by an integer: R = m * P @@ -527,9 +506,9 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, * or P is not a valid pubkey, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Multiplication and addition of two points by integers: @@ -551,9 +530,9 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * or P or Q is not a valid pubkey, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); +int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q); /** * \brief Check that a point is a valid public key on this curve @@ -576,7 +555,7 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * in order to ease use with other structures such as * mbedtls_ecdh_context of mbedtls_ecdsa_context. */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); +int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt); /** * \brief Check that an mbedtls_mpi is a valid private key for this curve @@ -591,7 +570,7 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po * in order to ease use with other structures such as * mbedtls_ecdh_context of mbedtls_ecdsa_context. */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); +int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d); /** * \brief Generate a keypair with configurable base point @@ -610,11 +589,11 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * * in order to ease use with other structures such as * mbedtls_ecdh_context of mbedtls_ecdsa_context. */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Generate a keypair @@ -632,9 +611,9 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, * in order to ease use with other structures such as * mbedtls_ecdh_context of mbedtls_ecdsa_context. */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Generate a keypair @@ -647,8 +626,8 @@ int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp * \return 0 if successful, * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code */ -int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Check a public-private key pair @@ -660,7 +639,7 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); +int mbedtls_ecp_check_pub_priv(const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv); #if defined(MBEDTLS_SELF_TEST) @@ -669,7 +648,7 @@ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ec * * \return 0 if successful, or 1 if a test failed */ -int mbedtls_ecp_self_test( int verbose ); +int mbedtls_ecp_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/entropy.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/entropy.h similarity index 73% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/entropy.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/entropy.h index 747aca4..1aa97f2 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/entropy.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/entropy.h @@ -1,52 +1,36 @@ -/** - * \file entropy.h - * - * \brief Entropy accumulator implementation - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_ENTROPY_H #define MBEDTLS_ENTROPY_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#include "sha512.h" -#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR + #include "sha512.h" + #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR #else -#if defined(MBEDTLS_SHA256_C) -#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR -#include "sha256.h" -#endif + #if defined(MBEDTLS_SHA256_C) + #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR + #include "sha256.h" + #endif #endif #if defined(MBEDTLS_THREADING_C) -#include "threading.h" + #include "threading.h" #endif #if defined(MBEDTLS_HAVEGE_C) -#include "havege.h" + #include "havege.h" #endif #define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ @@ -64,19 +48,19 @@ */ #if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) -#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ + #define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ #endif #if !defined(MBEDTLS_ENTROPY_MAX_GATHER) -#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ + #define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ #endif /* \} name SECTION: Module settings */ #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) -#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ + #define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ #else -#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ + #define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ #endif #define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ @@ -101,15 +85,14 @@ extern "C" { * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise */ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, - size_t *olen); + size_t *olen); /** * \brief Entropy source state */ -typedef struct -{ +typedef struct { mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ - void * p_source; /**< The callback data pointer */ + void *p_source; /**< The callback data pointer */ size_t size; /**< Amount received in bytes */ size_t threshold; /**< Minimum bytes required before release */ int strong; /**< Is the source strong? */ @@ -119,8 +102,7 @@ mbedtls_entropy_source_state; /** * \brief Entropy context structure */ -typedef struct -{ +typedef struct { #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_context accumulator; #else @@ -145,14 +127,14 @@ mbedtls_entropy_context; * * \param ctx Entropy context to initialize */ -void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); +void mbedtls_entropy_init(mbedtls_entropy_context *ctx); /** * \brief Free the data in the context * * \param ctx Entropy context to free */ -void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); +void mbedtls_entropy_free(mbedtls_entropy_context *ctx); /** * \brief Adds an entropy source to poll @@ -171,9 +153,9 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); * * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES */ -int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, - mbedtls_entropy_f_source_ptr f_source, void *p_source, - size_t threshold, int strong ); +int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong); /** * \brief Trigger an extra gather poll for the accumulator @@ -183,7 +165,7 @@ int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, * * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ -int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); +int mbedtls_entropy_gather(mbedtls_entropy_context *ctx); /** * \brief Retrieve entropy from the accumulator @@ -196,7 +178,7 @@ int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); * * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ -int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); +int mbedtls_entropy_func(void *data, unsigned char *output, size_t len); /** * \brief Add data to the accumulator manually @@ -208,8 +190,8 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); * * \return 0 if successful */ -int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, - const unsigned char *data, size_t len ); +int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len); #if defined(MBEDTLS_ENTROPY_NV_SEED) /** @@ -220,7 +202,7 @@ int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, * * \return 0 if successful */ -int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx); #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_FS_IO) @@ -234,7 +216,7 @@ int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ -int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); +int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path); /** * \brief Read and update a seed file. Seed is added to this @@ -248,7 +230,7 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ -int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) @@ -260,7 +242,7 @@ int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char * * * \return 0 if successful, or 1 if a test failed */ -int mbedtls_entropy_self_test( int verbose ); +int mbedtls_entropy_self_test(int verbose); #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) /** @@ -276,7 +258,7 @@ int mbedtls_entropy_self_test( int verbose ); * * \return 0 if successful, or 1 if a test failed */ -int mbedtls_entropy_source_self_test( int verbose ); +int mbedtls_entropy_source_self_test(int verbose); #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/entropy_poll.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/entropy_poll.h similarity index 52% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/entropy_poll.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/entropy_poll.h index 81258d5..85cdfee 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/entropy_poll.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/entropy_poll.h @@ -1,32 +1,16 @@ -/** - * \file entropy_poll.h - * - * \brief Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_ENTROPY_POLL_H #define MBEDTLS_ENTROPY_POLL_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include @@ -49,16 +33,16 @@ extern "C" { * \brief Entropy poll callback that provides 0 entropy. */ #if defined(MBEDTLS_TEST_NULL_ENTROPY) - int mbedtls_null_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); +int mbedtls_null_entropy_poll(void *data, + unsigned char *output, size_t len, size_t *olen); #endif #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback */ -int mbedtls_platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); +int mbedtls_platform_entropy_poll(void *data, + unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_HAVEGE_C) @@ -67,16 +51,16 @@ int mbedtls_platform_entropy_poll( void *data, * * Requires an HAVEGE state as its data pointer. */ -int mbedtls_havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); +int mbedtls_havege_poll(void *data, + unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_TIMING_C) /** * \brief mbedtls_timing_hardclock-based entropy poll callback */ -int mbedtls_hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); +int mbedtls_hardclock_poll(void *data, + unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) @@ -88,8 +72,8 @@ int mbedtls_hardclock_poll( void *data, * * \note This must accept NULL as its first argument. */ -int mbedtls_hardware_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); +int mbedtls_hardware_poll(void *data, + unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) @@ -98,8 +82,8 @@ int mbedtls_hardware_poll( void *data, * * \note This must accept NULL as its first argument. */ -int mbedtls_nv_seed_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); +int mbedtls_nv_seed_poll(void *data, + unsigned char *output, size_t len, size_t *olen); #endif #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/error.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/error.h similarity index 73% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/error.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/error.h index 5e549f6..09e0de7 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/error.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/error.h @@ -1,29 +1,14 @@ -/** - * \file error.h - * - * \brief Error to string translation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H #include +#include "config.h" /** * Error code layout. @@ -98,7 +83,7 @@ extern "C" { * \param buffer buffer to place representation in * \param buflen length of the buffer */ -void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); +void mbedtls_strerror(int errnum, char *buffer, size_t buflen); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/md.h similarity index 77% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/md.h index 9b996a9..c7c3b56 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/md.h @@ -1,27 +1,9 @@ -/** - * \file md.h - * - * \brief Generic message digest wrapper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_MD_H #define MBEDTLS_MD_H @@ -37,7 +19,7 @@ extern "C" { #endif typedef enum { - MBEDTLS_MD_NONE=0, + MBEDTLS_MD_NONE = 0, MBEDTLS_MD_MD2, MBEDTLS_MD_MD4, MBEDTLS_MD_MD5, @@ -80,7 +62,7 @@ typedef struct { * \return a statically allocated array of digests, the last entry * is 0. */ -const int *mbedtls_md_list( void ); +const int *mbedtls_md_list(void); /** * \brief Returns the message digest information associated with the @@ -91,7 +73,7 @@ const int *mbedtls_md_list( void ); * \return The message digest information associated with md_name or * NULL if not found. */ -const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); +const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name); /** * \brief Returns the message digest information associated with the @@ -102,21 +84,21 @@ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); * \return The message digest information associated with md_type or * NULL if not found. */ -const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); +const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type); /** * \brief Initialize a md_context (as NONE) * This should always be called first. * Prepares the context for mbedtls_md_setup() or mbedtls_md_free(). */ -void mbedtls_md_init( mbedtls_md_context_t *ctx ); +void mbedtls_md_init(mbedtls_md_context_t *ctx); /** * \brief Free and clear the internal structures of ctx. * Can be called at any time after mbedtls_md_init(). * Mandatory once mbedtls_md_setup() has been called. */ -void mbedtls_md_free( mbedtls_md_context_t *ctx ); +void mbedtls_md_free(mbedtls_md_context_t *ctx); #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) @@ -138,7 +120,7 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx ); * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. */ -int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +int mbedtls_md_init_ctx(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info) MBEDTLS_DEPRECATED; #undef MBEDTLS_DEPRECATED #endif /* MBEDTLS_DEPRECATED_REMOVED */ @@ -156,7 +138,7 @@ int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_ * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. */ -int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); +int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac); /** * \brief Clone the state of an MD context @@ -172,8 +154,8 @@ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_inf * \return \c 0 on success, * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. */ -int mbedtls_md_clone( mbedtls_md_context_t *dst, - const mbedtls_md_context_t *src ); +int mbedtls_md_clone(mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src); /** * \brief Returns the size of the message digest output. @@ -182,7 +164,7 @@ int mbedtls_md_clone( mbedtls_md_context_t *dst, * * \return size of the message digest output in bytes. */ -unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); +unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info); /** * \brief Returns the type of the message digest output. @@ -191,7 +173,7 @@ unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); * * \return type of the message digest output. */ -mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); +mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); /** * \brief Returns the name of the message digest output. @@ -200,7 +182,7 @@ mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); * * \return name of the message digest output. */ -const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); +const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); /** * \brief Prepare the context to digest a new message. @@ -212,7 +194,7 @@ const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_starts( mbedtls_md_context_t *ctx ); +int mbedtls_md_starts(mbedtls_md_context_t *ctx); /** * \brief Generic message digest process buffer @@ -226,7 +208,7 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx ); * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); +int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief Generic message digest final digest @@ -239,7 +221,7 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); +int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief Output = message_digest( input buffer ) @@ -252,8 +234,8 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ); +int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output); #if defined(MBEDTLS_FS_IO) /** @@ -267,8 +249,8 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si * MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, * MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL. */ -int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, - unsigned char *output ); +int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output); #endif /* MBEDTLS_FS_IO */ /** @@ -282,8 +264,8 @@ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, - size_t keylen ); +int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen); /** * \brief Generic HMAC process buffer. @@ -298,8 +280,8 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, - size_t ilen ); +int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen); /** * \brief Output HMAC. @@ -313,7 +295,7 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); +int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief Prepare to authenticate a new message with the same key. @@ -325,7 +307,7 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); +int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx); /** * \brief Output = Generic_HMAC( hmac key, input buffer ) @@ -340,12 +322,12 @@ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter * verification fails. */ -int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); +int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output); /* Internal use */ -int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); +int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md5.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/md5.h similarity index 53% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md5.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/md5.h index 5a64061..1ef52a0 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md5.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/md5.h @@ -1,32 +1,16 @@ -/** - * \file md5.h - * - * \brief MD5 message digest algorithm (hash function) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_MD5_H #define MBEDTLS_MD5_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include @@ -43,8 +27,7 @@ extern "C" { /** * \brief MD5 context structure */ -typedef struct -{ +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 */ @@ -56,14 +39,14 @@ mbedtls_md5_context; * * \param ctx MD5 context to be initialized */ -void mbedtls_md5_init( mbedtls_md5_context *ctx ); +void mbedtls_md5_init(mbedtls_md5_context *ctx); /** * \brief Clear MD5 context * * \param ctx MD5 context to be cleared */ -void mbedtls_md5_free( mbedtls_md5_context *ctx ); +void mbedtls_md5_free(mbedtls_md5_context *ctx); /** * \brief Clone (the state of) an MD5 context @@ -71,15 +54,15 @@ void mbedtls_md5_free( mbedtls_md5_context *ctx ); * \param dst The destination context * \param src The context to be cloned */ -void mbedtls_md5_clone( mbedtls_md5_context *dst, - const mbedtls_md5_context *src ); +void mbedtls_md5_clone(mbedtls_md5_context *dst, + const mbedtls_md5_context *src); /** * \brief MD5 context setup * * \param ctx context to be initialized */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ); +void mbedtls_md5_starts(mbedtls_md5_context *ctx); /** * \brief MD5 process buffer @@ -88,7 +71,7 @@ void mbedtls_md5_starts( mbedtls_md5_context *ctx ); * \param input buffer holding the data * \param ilen length of the input data */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); +void mbedtls_md5_update(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); /** * \brief MD5 final digest @@ -96,10 +79,10 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s * \param ctx MD5 context * \param output MD5 checksum result */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); +void mbedtls_md5_finish(mbedtls_md5_context *ctx, unsigned char output[16]); /* Internal use */ -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); +void mbedtls_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]); #ifdef __cplusplus } @@ -120,14 +103,14 @@ extern "C" { * \param ilen length of the input data * \param output MD5 checksum result */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); +void mbedtls_md5(const unsigned char *input, size_t ilen, unsigned char output[16]); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_md5_self_test( int verbose ); +int mbedtls_md5_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md_internal.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/md_internal.h similarity index 70% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md_internal.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/md_internal.h index e2441bb..5f5ca6c 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/md_internal.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/md_internal.h @@ -1,29 +1,9 @@ -/** - * \file md_internal.h - * - * \brief Message digest wrappers. - * - * \warning This in an internal header. Do not include directly. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_MD_WRAP_H #define MBEDTLS_MD_WRAP_H diff --git a/iotkit-embedded/external_libs/mbedtls/include/mbedtls/net.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/net.h new file mode 100644 index 0000000..4ad8223 --- /dev/null +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/net.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "mbedtls/net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/net_sockets.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/net_sockets.h similarity index 79% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/net_sockets.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/net_sockets.h index de33552..cf3eb9c 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/net_sockets.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/net_sockets.h @@ -1,32 +1,16 @@ -/** - * \file net_sockets.h - * - * \brief Network communication functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_NET_SOCKETS_H #define MBEDTLS_NET_SOCKETS_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "ssl.h" @@ -62,8 +46,7 @@ extern "C" { * (eg two file descriptors for combined IPv4 + IPv6 support, or additional * structures for hand-made UDP demultiplexing). */ -typedef struct -{ +typedef struct { int fd; /**< The underlying file descriptor */ } mbedtls_net_context; @@ -74,7 +57,7 @@ mbedtls_net_context; * * \param ctx Context to initialize */ -void mbedtls_net_init( mbedtls_net_context *ctx ); +void mbedtls_net_init(mbedtls_net_context *ctx); /** * \brief Initiate a connection with host:port in the given protocol @@ -91,7 +74,7 @@ void mbedtls_net_init( mbedtls_net_context *ctx ); * * \note Sets the socket in connected mode even with UDP. */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); +int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto); /** * \brief Create a receiving socket on bind_ip:port in the chosen @@ -110,7 +93,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char * \note Regardless of the protocol, opens the sockets and binds it. * In addition, make the socket listening if protocol is TCP. */ -int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); +int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto); /** * \brief Accept a connection from a remote client @@ -127,9 +110,9 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to * non-blocking and accept() would block. */ -int mbedtls_net_accept( mbedtls_net_context *bind_ctx, - mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len ); +int mbedtls_net_accept(mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len); /** * \brief Set the socket blocking @@ -138,7 +121,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, * * \return 0 if successful, or a non-zero error code */ -int mbedtls_net_set_block( mbedtls_net_context *ctx ); +int mbedtls_net_set_block(mbedtls_net_context *ctx); /** * \brief Set the socket non-blocking @@ -147,7 +130,7 @@ int mbedtls_net_set_block( mbedtls_net_context *ctx ); * * \return 0 if successful, or a non-zero error code */ -int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); +int mbedtls_net_set_nonblock(mbedtls_net_context *ctx); /** * \brief Portable usleep helper @@ -157,7 +140,7 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); * \note Real amount of time slept will not be less than * select()'s timeout granularity (typically, 10ms). */ -void mbedtls_net_usleep( unsigned long usec ); +void mbedtls_net_usleep(unsigned long usec); /** * \brief Read at most 'len' characters. If no error occurs, @@ -171,7 +154,7 @@ void mbedtls_net_usleep( unsigned long usec ); * or a non-zero error code; with a non-blocking socket, * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. */ -int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); +int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); /** * \brief Write at most 'len' characters. If no error occurs, @@ -185,7 +168,7 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); * or a non-zero error code; with a non-blocking socket, * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. */ -int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); +int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len); /** * \brief Read at most 'len' characters, blocking for at most @@ -208,15 +191,15 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); * non-blocking. Handling timeouts with non-blocking reads * requires a different strategy. */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ); +int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, + uint32_t timeout); /** * \brief Gracefully shutdown the connection and free associated data * * \param ctx The context to free */ -void mbedtls_net_free( mbedtls_net_context *ctx ); +void mbedtls_net_free(mbedtls_net_context *ctx); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/oid.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/oid.h similarity index 91% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/oid.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/oid.h index fcecdaf..e1f58de 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/oid.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/oid.h @@ -1,32 +1,16 @@ -/** - * \file oid.h - * - * \brief Object Identifier (OID) database - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_OID_H #define MBEDTLS_OID_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "asn1.h" @@ -35,15 +19,15 @@ #include #if defined(MBEDTLS_CIPHER_C) -#include "cipher.h" + #include "cipher.h" #endif #if defined(MBEDTLS_MD_C) -#include "md.h" + #include "md.h" #endif #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "x509.h" + #include "x509.h" #endif #define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ @@ -63,10 +47,10 @@ #define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ #define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ #define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ #define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ #define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_ANSI_X9_62 + MBEDTLS_OID_ORG_ANSI_X9_62 /* * ISO Identified organization OID parts @@ -397,7 +381,7 @@ typedef struct { * \return Length of the string written (excluding final NULL) or * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error */ -int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); +int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) /** @@ -408,7 +392,7 @@ int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_b * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); +int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); #endif /** @@ -420,7 +404,7 @@ int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); +int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name); /** * \brief Translate PublicKeyAlgorithm OID into pk_type @@ -430,7 +414,7 @@ int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **s * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); +int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg); /** * \brief Translate pk_type into PublicKeyAlgorithm OID @@ -441,8 +425,8 @@ int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_a * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, - const char **oid, size_t *olen ); +int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen); #if defined(MBEDTLS_ECP_C) /** @@ -453,7 +437,7 @@ int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); +int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); /** * \brief Translate EC group identifier into NamedCurve OID @@ -464,8 +448,8 @@ int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *g * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, - const char **oid, size_t *olen ); +int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) @@ -478,8 +462,8 @@ int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); +int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg); /** * \brief Translate SignatureAlgorithm OID into description @@ -489,7 +473,7 @@ int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); +int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc); /** * \brief Translate md_type and pk_type into SignatureAlgorithm OID @@ -501,8 +485,8 @@ int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const char **oid, size_t *olen ); +int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen); /** * \brief Translate hash algorithm OID into md_type @@ -512,7 +496,7 @@ int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); +int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); #endif /* MBEDTLS_MD_C */ /** @@ -523,7 +507,7 @@ int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_a * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); +int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); /** * \brief Translate md_type into hash algorithm OID @@ -534,7 +518,7 @@ int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); +int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen); #if defined(MBEDTLS_CIPHER_C) /** @@ -545,7 +529,7 @@ int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_ * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PKCS12_C) @@ -559,8 +543,8 @@ int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ -int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, - mbedtls_cipher_type_t *cipher_alg ); +int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg); #endif /* MBEDTLS_PKCS12_C */ #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pem.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/pem.h similarity index 72% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pem.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/pem.h index 54dc02d..589fbf8 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pem.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/pem.h @@ -1,25 +1,9 @@ -/** - * \file pem.h - * - * \brief Privacy Enhanced Mail (PEM) decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H @@ -50,8 +34,7 @@ extern "C" { /** * \brief PEM context structure */ -typedef struct -{ +typedef struct { unsigned char *buf; /*!< buffer for decoded data */ size_t buflen; /*!< length of the buffer */ unsigned char *info; /*!< buffer for extra header information */ @@ -63,7 +46,7 @@ mbedtls_pem_context; * * \param ctx context to be initialized */ -void mbedtls_pem_init( mbedtls_pem_context *ctx ); +void mbedtls_pem_init(mbedtls_pem_context *ctx); /** * \brief Read a buffer for PEM information and store the resulting @@ -87,17 +70,17 @@ void mbedtls_pem_init( mbedtls_pem_context *ctx ); * * \return 0 on success, or a specific PEM error code */ -int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, - const unsigned char *data, - const unsigned char *pwd, - size_t pwdlen, size_t *use_len ); +int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len); /** * \brief PEM context memory freeing * * \param ctx context to be freed */ -void mbedtls_pem_free( mbedtls_pem_context *ctx ); +void mbedtls_pem_free(mbedtls_pem_context *ctx); #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) @@ -117,9 +100,9 @@ void mbedtls_pem_free( mbedtls_pem_context *ctx ); * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required * size. */ -int mbedtls_pem_write_buffer( const char *header, const char *footer, - const unsigned char *der_data, size_t der_len, - unsigned char *buf, size_t buf_len, size_t *olen ); +int mbedtls_pem_write_buffer(const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen); #endif /* MBEDTLS_PEM_WRITE_C */ #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pk.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/pk.h similarity index 75% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pk.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/pk.h index f9f9b9b..a25e358 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pk.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/pk.h @@ -1,52 +1,36 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_PK_H #define MBEDTLS_PK_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "md.h" #if defined(MBEDTLS_RSA_C) -#include "rsa.h" + #include "rsa.h" #endif #if defined(MBEDTLS_ECP_C) -#include "ecp.h" + #include "ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) -#include "ecdsa.h" + #include "ecdsa.h" #endif #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) -#define inline __inline + #define inline __inline #endif #define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ @@ -72,7 +56,7 @@ extern "C" { * \brief Public key types */ typedef enum { - MBEDTLS_PK_NONE=0, + MBEDTLS_PK_NONE = 0, MBEDTLS_PK_RSA, MBEDTLS_PK_ECKEY, MBEDTLS_PK_ECKEY_DH, @@ -85,8 +69,7 @@ typedef enum { * \brief Options for RSASSA-PSS signature verification. * See \c mbedtls_rsa_rsassa_pss_verify_ext() */ -typedef struct -{ +typedef struct { mbedtls_md_type_t mgf1_hash_id; int expected_salt_len; @@ -95,8 +78,7 @@ typedef struct /** * \brief Types for interfacing with the debug module */ -typedef enum -{ +typedef enum { MBEDTLS_PK_DEBUG_NONE = 0, MBEDTLS_PK_DEBUG_MPI, MBEDTLS_PK_DEBUG_ECP, @@ -105,8 +87,7 @@ typedef enum /** * \brief Item to send to the debug module */ -typedef struct -{ +typedef struct { mbedtls_pk_debug_type type; const char *name; void *value; @@ -123,10 +104,9 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; /** * \brief Public key container */ -typedef struct -{ - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ - void * pk_ctx; /**< Underlying public key context */ +typedef struct { + const mbedtls_pk_info_t *pk_info; /**< Public key informations */ + void *pk_ctx; /**< Underlying public key context */ } mbedtls_pk_context; #if defined(MBEDTLS_RSA_C) @@ -136,9 +116,9 @@ typedef struct * \warning You must make sure the PK context actually holds an RSA context * before using this function! */ -static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) { - return( (mbedtls_rsa_context *) (pk).pk_ctx ); + return ((mbedtls_rsa_context *)(pk).pk_ctx); } #endif /* MBEDTLS_RSA_C */ @@ -149,9 +129,9 @@ static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) * \warning You must make sure the PK context actually holds an EC context * before using this function! */ -static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) { - return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); + return ((mbedtls_ecp_keypair *)(pk).pk_ctx); } #endif /* MBEDTLS_ECP_C */ @@ -159,14 +139,14 @@ static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) /** * \brief Types for RSA-alt abstraction */ -typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len ); -typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig ); -typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len); +typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /** @@ -176,17 +156,17 @@ typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); * * \return The PK info associated with the type or NULL if not found. */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); +const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); /** * \brief Initialize a mbedtls_pk_context (as NONE) */ -void mbedtls_pk_init( mbedtls_pk_context *ctx ); +void mbedtls_pk_init(mbedtls_pk_context *ctx); /** * \brief Free a mbedtls_pk_context */ -void mbedtls_pk_free( mbedtls_pk_context *ctx ); +void mbedtls_pk_free(mbedtls_pk_context *ctx); /** * \brief Initialize a PK context with the information given @@ -202,7 +182,7 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx ); * \note For contexts holding an RSA-alt key, use * \c mbedtls_pk_setup_rsa_alt() instead. */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); +int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** @@ -219,10 +199,10 @@ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); * * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. */ -int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func ); +int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /** @@ -232,7 +212,7 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, * * \return Key size in bits, or 0 on error */ -size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); +size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); /** * \brief Get the length in bytes of the underlying key @@ -240,9 +220,9 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); * * \return Key length in bytes, or 0 on error */ -static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) { - return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); + return ((mbedtls_pk_get_bitlen(ctx) + 7) / 8); } /** @@ -254,7 +234,7 @@ static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) * \return 0 if context can't do the operations, * 1 otherwise. */ -int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); +int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); /** * \brief Verify signature (including padding if relevant). @@ -280,9 +260,9 @@ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); * * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); +int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len); /** * \brief Verify signature, with options. @@ -313,10 +293,10 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * to a mbedtls_pk_rsassa_pss_options structure, * otherwise it must be NULL. */ -int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); +int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len); /** * \brief Make signature, including padding if relevant. @@ -342,10 +322,10 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. */ -int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Decrypt message (including padding if relevant). @@ -363,10 +343,10 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * * \return 0 on success, or a specific error code. */ -int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Encrypt message (including padding if relevant). @@ -384,10 +364,10 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, * * \return 0 on success, or a specific error code. */ -int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Check if a public-private pair of keys matches. @@ -397,7 +377,7 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, * * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA */ -int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); +int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv); /** * \brief Export debug information @@ -407,7 +387,7 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte * * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA */ -int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); +int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items); /** * \brief Access the type name @@ -416,7 +396,7 @@ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *item * * \return Type name on success, or "invalid PK" */ -const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); +const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); /** * \brief Get the key type @@ -425,7 +405,7 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); * * \return Type on success, or MBEDTLS_PK_NONE */ -mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); +mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); #if defined(MBEDTLS_PK_PARSE_C) /** \ingroup pk_module */ @@ -447,9 +427,9 @@ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); * * \return 0 if successful, or a specific PK or PEM error code */ -int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ); +int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen); /** \ingroup pk_module */ /** @@ -468,8 +448,8 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, * * \return 0 if successful, or a specific PK or PEM error code */ -int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen ); +int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen); #if defined(MBEDTLS_FS_IO) /** \ingroup pk_module */ @@ -488,8 +468,8 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, * * \return 0 if successful, or a specific PK or PEM error code */ -int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, - const char *path, const char *password ); +int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, + const char *path, const char *password); /** \ingroup pk_module */ /** @@ -507,7 +487,7 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, * * \return 0 if successful, or a specific PK or PEM error code */ -int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C */ @@ -525,7 +505,7 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) * \return length of data written if successful, or a specific * error code */ -int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +int mbedtls_pk_write_key_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a public key to a SubjectPublicKeyInfo DER structure @@ -540,7 +520,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_ * \return length of data written if successful, or a specific * error code */ -int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #if defined(MBEDTLS_PEM_WRITE_C) /** @@ -552,7 +532,7 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, si * * \return 0 if successful, or a specific error code */ -int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a private key to a PKCS#1 or SEC1 PEM string @@ -563,7 +543,7 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, si * * \return 0 if successful, or a specific error code */ -int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +int mbedtls_pk_write_key_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ @@ -582,8 +562,8 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_ * * \return 0 if successful, or a specific PK error code */ -int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk ); +int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk); #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) @@ -597,8 +577,8 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, * * \return the length written or a negative error code */ -int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key ); +int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ /* @@ -606,7 +586,7 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, * know you do. */ #if defined(MBEDTLS_FS_IO) -int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); #endif #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pk_internal.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/pk_internal.h similarity index 77% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pk_internal.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/pk_internal.h index 01d0f21..f186825 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/pk_internal.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/pk_internal.h @@ -1,26 +1,10 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer: wrapper functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_PK_WRAP_H #define MBEDTLS_PK_WRAP_H diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/platform.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/platform.h similarity index 75% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/platform.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/platform.h index b1b019e..640094f 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/platform.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/platform.h @@ -1,36 +1,20 @@ -/** - * \file platform.h - * - * \brief mbed TLS Platform abstraction layer - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_PLATFORM_H #define MBEDTLS_PLATFORM_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" + #include "mbedtls/platform_time.h" #endif #ifdef __cplusplus @@ -111,8 +95,8 @@ extern "C" { #else /* For size_t */ #include -extern void * (*mbedtls_calloc)( size_t n, size_t size ); -extern void (*mbedtls_free)( void *ptr ); +extern void *(*mbedtls_calloc)(size_t n, size_t size); +extern void (*mbedtls_free)(void *ptr); /** * \brief Set your own memory implementation function pointers @@ -122,8 +106,8 @@ extern void (*mbedtls_free)( void *ptr ); * * \return 0 if successful */ -int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), - void (*free_func)( void * ) ); +int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), + void (*free_func)(void *)); #endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ #else /* !MBEDTLS_PLATFORM_MEMORY */ #define mbedtls_free free @@ -136,7 +120,7 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) /* We need FILE * */ #include -extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); +extern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...); /** * \brief Set your own fprintf function pointer @@ -145,8 +129,8 @@ extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); * * \return 0 */ -int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, - ... ) ); +int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *stream, const char *, + ...)); #else #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) #define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO @@ -159,7 +143,7 @@ int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char * The function pointers for printf */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) -extern int (*mbedtls_printf)( const char *format, ... ); +extern int (*mbedtls_printf)(const char *format, ...); /** * \brief Set your own printf function pointer @@ -168,7 +152,7 @@ extern int (*mbedtls_printf)( const char *format, ... ); * * \return 0 */ -int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)); #else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) #define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO @@ -188,11 +172,11 @@ int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); */ #if defined(_WIN32) /* For Windows (inc. MSYS2), we provide our own fixed implementation */ -int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...); #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); +extern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...); /** * \brief Set your own snprintf function pointer @@ -201,8 +185,8 @@ extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); * * \return 0 */ -int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, - const char * format, ... ) ); +int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, + const char *format, ...)); #else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO @@ -215,7 +199,7 @@ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, * The function pointers for exit */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) -extern void (*mbedtls_exit)( int status ); +extern void (*mbedtls_exit)(int status); /** * \brief Set your own exit function pointer @@ -224,7 +208,7 @@ extern void (*mbedtls_exit)( int status ); * * \return 0 */ -int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +int mbedtls_platform_set_exit(void (*exit_func)(int status)); #else #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) #define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO @@ -256,13 +240,13 @@ int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); #if defined(MBEDTLS_ENTROPY_NV_SEED) #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) /* Internal standard platform definitions */ -int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); -int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len); +int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len); #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); -extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len); +extern int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len); /** * \brief Set your own seed file writing/reading functions @@ -273,9 +257,9 @@ extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); * \return 0 */ int mbedtls_platform_set_nv_seed( - int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), - int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) - ); + int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len), + int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len) +); #else #if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/rsa.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/rsa.h similarity index 72% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/rsa.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/rsa.h index 54653df..4c9cee0 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/rsa.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/rsa.h @@ -1,39 +1,23 @@ -/** - * \file rsa.h - * - * \brief The RSA public-key cryptosystem - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_RSA_H #define MBEDTLS_RSA_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "bignum.h" #include "md.h" #if defined(MBEDTLS_THREADING_C) -#include "threading.h" + #include "threading.h" #endif /* @@ -76,8 +60,7 @@ extern "C" { /** * \brief RSA context structure */ -typedef struct -{ +typedef struct { int ver; /*!< always 0 */ size_t len; /*!< size(N) in chars */ @@ -134,9 +117,9 @@ mbedtls_rsa_context; * but can be overriden (and always is, if set to * MBEDTLS_MD_NONE) for verifying them. */ -void mbedtls_rsa_init( mbedtls_rsa_context *ctx, - int padding, - int hash_id); +void mbedtls_rsa_init(mbedtls_rsa_context *ctx, + int padding, + int hash_id); /** * \brief Set padding for an already initialized RSA context @@ -146,7 +129,7 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id); +void mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, int hash_id); /** * \brief Generate an RSA keypair @@ -162,10 +145,10 @@ void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id * * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code */ -int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ); +int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent); /** * \brief Check a public RSA key @@ -174,7 +157,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, * * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code */ -int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); +int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx); /** * \brief Check a private RSA key @@ -183,7 +166,7 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); * * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code */ -int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); +int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx); /** * \brief Check a public-private RSA key pair. @@ -194,7 +177,7 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); * * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); +int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv); /** * \brief Do an RSA public key operation @@ -212,9 +195,9 @@ int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rs * \note The input and output buffers must be large * enough (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_public( mbedtls_rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); +int mbedtls_rsa_public(mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output); /** * \brief Do an RSA private key operation @@ -230,11 +213,11 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, * \note The input and output buffers must be large * enough (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_private( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - const unsigned char *input, - unsigned char *output ); +int mbedtls_rsa_private(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output); /** * \brief Generic wrapper to perform a PKCS#1 encryption using the @@ -255,12 +238,12 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * \note The output buffer must be as large as the size * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); +int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output); /** * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) @@ -278,12 +261,12 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, * \note The output buffer must be as large as the size * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output); /** * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) @@ -304,14 +287,14 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, * \note The output buffer must be as large as the size * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ); +int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output); /** * \brief Generic wrapper to perform a PKCS#1 decryption using the @@ -333,13 +316,13 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise * an error is thrown. */ -int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); +int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len); /** * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) @@ -359,13 +342,13 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise * an error is thrown. */ -int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len); /** * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) @@ -387,15 +370,15 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise * an error is thrown. */ -int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); +int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len); /** * \brief Generic wrapper to perform a PKCS#1 signature using the @@ -421,14 +404,14 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * \note In case of PKCS#1 v2.1 encoding, see comments on * \note \c mbedtls_rsa_rsassa_pss_sign() for details on md_alg and hash_id. */ -int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); +int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig); /** * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) @@ -448,14 +431,14 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * \note The "sig" buffer must be as large as the size * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); +int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig); /** * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) @@ -481,14 +464,14 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * that is encoded. According to RFC 3447 it is advised to * keep both hashes the same. */ -int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); +int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig); /** * \brief Generic wrapper to perform a PKCS#1 verification using the @@ -513,14 +496,14 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, * \note In case of PKCS#1 v2.1 encoding, see comments on * \c mbedtls_rsa_rsassa_pss_verify() about md_alg and hash_id. */ -int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); +int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig); /** * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) @@ -540,14 +523,14 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, * \note The "sig" buffer must be as large as the size * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); +int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig); /** * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) @@ -574,14 +557,14 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, * keep both hashes the same. If hash_id in the RSA context is * unset, the md_alg from the function call is used. */ -int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); +int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig); /** * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) @@ -607,16 +590,16 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, * * \note The hash_id in the RSA context is ignored. */ -int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - mbedtls_md_type_t mgf1_hash_id, - int expected_salt_len, - const unsigned char *sig ); +int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig); /** * \brief Copy the components of an RSA context @@ -627,21 +610,21 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, * \return 0 on success, * MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure */ -int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); +int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src); /** * \brief Free the components of an RSA key * * \param ctx RSA Context to free */ -void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); +void mbedtls_rsa_free(mbedtls_rsa_context *ctx); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_rsa_self_test( int verbose ); +int mbedtls_rsa_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/sha1.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/sha1.h similarity index 54% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/sha1.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/sha1.h index 7a67c6c..3c247a6 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/sha1.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/sha1.h @@ -1,32 +1,16 @@ -/** - * \file sha1.h - * - * \brief SHA-1 cryptographic hash function - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include @@ -43,8 +27,7 @@ extern "C" { /** * \brief SHA-1 context structure */ -typedef struct -{ +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 */ @@ -56,14 +39,14 @@ mbedtls_sha1_context; * * \param ctx SHA-1 context to be initialized */ -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); +void mbedtls_sha1_init(mbedtls_sha1_context *ctx); /** * \brief Clear SHA-1 context * * \param ctx SHA-1 context to be cleared */ -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); +void mbedtls_sha1_free(mbedtls_sha1_context *ctx); /** * \brief Clone (the state of) a SHA-1 context @@ -71,15 +54,15 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); * \param dst The destination context * \param src The context to be cloned */ -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ); +void mbedtls_sha1_clone(mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src); /** * \brief SHA-1 context setup * * \param ctx context to be initialized */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); +void mbedtls_sha1_starts(mbedtls_sha1_context *ctx); /** * \brief SHA-1 process buffer @@ -88,7 +71,7 @@ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); * \param input buffer holding the data * \param ilen length of the input data */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); +void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen); /** * \brief SHA-1 final digest @@ -96,10 +79,10 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, * \param ctx SHA-1 context * \param output SHA-1 checksum result */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); +void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20]); /* Internal use */ -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); +void mbedtls_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]); #ifdef __cplusplus } @@ -120,14 +103,14 @@ extern "C" { * \param ilen length of the input data * \param output SHA-1 checksum result */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); +void mbedtls_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_sha1_self_test( int verbose ); +int mbedtls_sha1_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/sha256.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/sha256.h similarity index 55% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/sha256.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/sha256.h index f8041ad..38f1272 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/sha256.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/sha256.h @@ -1,32 +1,16 @@ -/** - * \file sha256.h - * - * \brief SHA-224 and SHA-256 cryptographic hash function - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include @@ -43,8 +27,7 @@ extern "C" { /** * \brief SHA-256 context structure */ -typedef struct -{ +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 */ @@ -57,14 +40,14 @@ mbedtls_sha256_context; * * \param ctx SHA-256 context to be initialized */ -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); +void mbedtls_sha256_init(mbedtls_sha256_context *ctx); /** * \brief Clear SHA-256 context * * \param ctx SHA-256 context to be cleared */ -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); +void mbedtls_sha256_free(mbedtls_sha256_context *ctx); /** * \brief Clone (the state of) a SHA-256 context @@ -72,8 +55,8 @@ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); * \param dst The destination context * \param src The context to be cloned */ -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ); +void mbedtls_sha256_clone(mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src); /** * \brief SHA-256 context setup @@ -81,7 +64,7 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, * \param ctx context to be initialized * \param is224 0 = use SHA256, 1 = use SHA224 */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); +void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224); /** * \brief SHA-256 process buffer @@ -90,8 +73,8 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); * \param input buffer holding the data * \param ilen length of the input data */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ); +void mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen); /** * \brief SHA-256 final digest @@ -99,10 +82,10 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in * \param ctx SHA-256 context * \param output SHA-224/256 checksum result */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); +void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32]); /* Internal use */ -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); +void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64]); #ifdef __cplusplus } @@ -124,15 +107,15 @@ extern "C" { * \param output SHA-224/256 checksum result * \param is224 0 = use SHA256, 1 = use SHA224 */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); +void mbedtls_sha256(const unsigned char *input, size_t ilen, + unsigned char output[32], int is224); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_sha256_self_test( int verbose ); +int mbedtls_sha256_self_test(int verbose); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl.h similarity index 88% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl.h index cb29b83..e350341 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl.h @@ -1,32 +1,16 @@ -/** - * \file ssl.h - * - * \brief SSL/TLS functions. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_SSL_H #define MBEDTLS_SSL_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "bignum.h" @@ -35,24 +19,24 @@ #include "ssl_ciphersuites.h" #if defined(MBEDTLS_X509_CRT_PARSE_C) -#include "x509_crt.h" -#include "x509_crl.h" + #include "x509_crt.h" + #include "x509_crl.h" #endif #if defined(MBEDTLS_DHM_C) -#include "dhm.h" + #include "dhm.h" #endif #if defined(MBEDTLS_ECDH_C) -#include "ecdh.h" + #include "ecdh.h" #endif #if defined(MBEDTLS_ZLIB_SUPPORT) -#include "zlib.h" + #include "zlib.h" #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" + #include "mbedtls/platform_time.h" #endif /* @@ -204,7 +188,7 @@ */ #if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) -#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ + #define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ #endif /* @@ -218,8 +202,22 @@ * if you're using the Max Fragment Length extension and you know all your * peers are using it too! */ + +/* + * !!!!! NOTE !!!!! + * + * Modification to value of MBEDTLS_SSL_MAX_CONTENT_LEN must be considered and verified carefully + * + * MBEDTLS_SSL_MAX_CONTENT_LEN >= 4096 + * + * is mandantory to connect Aliyun Servers + * + * THIS DEFAULT CONFIGURATION IS CHANGED AT YOUR OWN RISK + * + * !!!!! NOTE !!!!! + */ #if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ + #define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ #endif /* \} name SECTION: Module settings */ @@ -228,9 +226,9 @@ * Length of the verify data for secure renegotiation */ #if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 + #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 #else -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 + #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 #endif /* @@ -346,12 +344,11 @@ * Size defines */ #if !defined(MBEDTLS_PSK_MAX_LEN) -#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ + #define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ #endif /* Dummy type used only for its size */ -union mbedtls_ssl_premaster_secret -{ +union mbedtls_ssl_premaster_secret { #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ #endif @@ -392,8 +389,7 @@ extern "C" { /* * SSL state machine */ -typedef enum -{ +typedef enum { MBEDTLS_SSL_HELLO_REQUEST, MBEDTLS_SSL_CLIENT_HELLO, MBEDTLS_SSL_SERVER_HELLO, @@ -433,9 +429,9 @@ mbedtls_ssl_states; * \note The callback is allowed to send fewer bytes than requested. * It must always return the number of bytes actually sent. */ -typedef int mbedtls_ssl_send_t( void *ctx, - const unsigned char *buf, - size_t len ); +typedef int mbedtls_ssl_send_t(void *ctx, + const unsigned char *buf, + size_t len); /** * \brief Callback type: receive data from the network. @@ -456,9 +452,9 @@ typedef int mbedtls_ssl_send_t( void *ctx, * buffer. It must always return the number of bytes actually * received and written to the buffer. */ -typedef int mbedtls_ssl_recv_t( void *ctx, - unsigned char *buf, - size_t len ); +typedef int mbedtls_ssl_recv_t(void *ctx, + unsigned char *buf, + size_t len); /** * \brief Callback type: receive data from the network, with timeout @@ -482,10 +478,10 @@ typedef int mbedtls_ssl_recv_t( void *ctx, * buffer. It must always return the number of bytes actually * received and written to the buffer. */ -typedef int mbedtls_ssl_recv_timeout_t( void *ctx, - unsigned char *buf, - size_t len, - uint32_t timeout ); +typedef int mbedtls_ssl_recv_timeout_t(void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout); /** * \brief Callback type: set a pair of timers/delays to watch * @@ -508,9 +504,9 @@ typedef int mbedtls_ssl_recv_timeout_t( void *ctx, * function while a timer is running must cancel it. Cancelled * timers must not generate any event. */ -typedef void mbedtls_ssl_set_timer_t( void * ctx, - uint32_t int_ms, - uint32_t fin_ms ); +typedef void mbedtls_ssl_set_timer_t(void *ctx, + uint32_t int_ms, + uint32_t fin_ms); /** * \brief Callback type: get status of timers/delays @@ -523,7 +519,7 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx, * 1 if only the intermediate delay has passed, * 2 if the final delay has passed. */ -typedef int mbedtls_ssl_get_timer_t( void * ctx ); +typedef int mbedtls_ssl_get_timer_t(void *ctx); /* Defined below */ @@ -544,8 +540,7 @@ typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; /* * This structure is used for storing current session data. */ -struct mbedtls_ssl_session -{ +struct mbedtls_ssl_session { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t start; /*!< starting time */ #endif @@ -582,8 +577,7 @@ struct mbedtls_ssl_session /** * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. */ -struct mbedtls_ssl_config -{ +struct mbedtls_ssl_config { /* Group items by size (largest first) to minimize padding overhead */ /* @@ -597,7 +591,7 @@ struct mbedtls_ssl_config void *p_dbg; /*!< context for the debug function */ /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); + int (*f_rng)(void *, unsigned char *, size_t); void *p_rng; /*!< context for the RNG function */ /** Callback to retrieve a session from the cache */ @@ -626,27 +620,27 @@ struct mbedtls_ssl_config #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a cookie for ClientHello veirifcation */ - int (*f_cookie_write)( void *, unsigned char **, unsigned char *, - const unsigned char *, size_t ); + int (*f_cookie_write)(void *, unsigned char **, unsigned char *, + const unsigned char *, size_t); /** Callback to verify validity of a ClientHello cookie */ - int (*f_cookie_check)( void *, const unsigned char *, size_t, - const unsigned char *, size_t ); + int (*f_cookie_check)(void *, const unsigned char *, size_t, + const unsigned char *, size_t); void *p_cookie; /*!< context for the cookie callbacks */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a session ticket */ - int (*f_ticket_write)( void *, const mbedtls_ssl_session *, - unsigned char *, const unsigned char *, size_t *, uint32_t * ); + int (*f_ticket_write)(void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t *); /** Callback to parse a session ticket into a session structure */ - int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + int (*f_ticket_parse)(void *, mbedtls_ssl_session *, unsigned char *, size_t); void *p_ticket; /*!< context for the ticket callbacks */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_EXPORT_KEYS) /** Callback to export key block and master secret */ - int (*f_export_keys)( void *, const unsigned char *, - const unsigned char *, size_t, size_t, size_t ); + int (*f_export_keys)(void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t); void *p_export_keys; /*!< context for key export callback */ #endif @@ -759,8 +753,7 @@ struct mbedtls_ssl_config }; -struct mbedtls_ssl_context -{ +struct mbedtls_ssl_context { const mbedtls_ssl_config *conf; /*!< configuration information */ /* @@ -784,7 +777,7 @@ struct mbedtls_ssl_context mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ mbedtls_ssl_recv_timeout_t *f_recv_timeout; - /*!< Callback for network receive with timeout */ + /*!< Callback for network receive with timeout */ void *p_bio; /*!< context for I/O operations */ @@ -911,12 +904,12 @@ struct mbedtls_ssl_context #define MBEDTLS_SSL_CHANNEL_INBOUND 1 extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen); + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); @@ -930,7 +923,7 @@ extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); * \return a statically allocated array of ciphersuites, the last * entry is 0. */ -const int *mbedtls_ssl_list_ciphersuites( void ); +const int *mbedtls_ssl_list_ciphersuites(void); /** * \brief Return the name of the ciphersuite associated with the @@ -940,7 +933,7 @@ const int *mbedtls_ssl_list_ciphersuites( void ); * * \return a string containing the ciphersuite name */ -const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); +const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id); /** * \brief Return the ID of the ciphersuite associated with the @@ -950,7 +943,7 @@ const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); * * \return the ID with the ciphersuite or 0 if not found */ -int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); +int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name); /** * \brief Initialize an SSL context @@ -959,7 +952,7 @@ int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); * * \param ssl SSL context */ -void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_init(mbedtls_ssl_context *ssl); /** * \brief Set up an SSL context for use @@ -976,8 +969,8 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if * memory allocation failed */ -int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, - const mbedtls_ssl_config *conf ); +int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf); /** * \brief Reset an already initialized SSL context for re-use @@ -989,7 +982,7 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or * MBEDTLS_ERR_SSL_COMPRESSION_FAILED */ -int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); /** * \brief Set the current endpoint type @@ -997,7 +990,7 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); * \param conf SSL configuration * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER */ -void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); +void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint); /** * \brief Set the transport type (TLS or DTLS). @@ -1013,7 +1006,7 @@ void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. */ -void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); +void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport); /** * \brief Set the certificate verification mode @@ -1041,7 +1034,7 @@ void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); * the verification as soon as possible. For example, REQUIRED was protecting * against the "triple handshake" attack even before it was found. */ -void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); +void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode); #if defined(MBEDTLS_X509_CRT_PARSE_C) /** @@ -1055,9 +1048,9 @@ void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); * \param f_vrfy verification function * \param p_vrfy verification parameter */ -void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); +void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** @@ -1067,9 +1060,9 @@ void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, * \param f_rng RNG function * \param p_rng RNG parameter */ -void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Set the debug callback @@ -1085,9 +1078,9 @@ void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, * \param f_dbg debug function * \param p_dbg debug parameter */ -void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, - void (*f_dbg)(void *, int, const char *, int, const char *), - void *p_dbg ); +void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg); /** * \brief Set the underlying BIO callbacks for write, read and @@ -1119,11 +1112,11 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, * \c mbedtls_net_recv_timeout() that are suitable to be used * here. */ -void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, - void *p_bio, - mbedtls_ssl_send_t *f_send, - mbedtls_ssl_recv_t *f_recv, - mbedtls_ssl_recv_timeout_t *f_recv_timeout ); +void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout); /** * \brief Set the timeout period for mbedtls_ssl_read() @@ -1141,7 +1134,7 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, * \note With non-blocking I/O, you may also skip this function * altogether and handle timeouts at the application layer. */ -void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); +void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout); /** * \brief Set the timer callbacks (Mandatory for DTLS.) @@ -1163,10 +1156,10 @@ void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) * \note See also the "DTLS tutorial" article in our knowledge base. * https://tls.mbed.org/kb/how-to/dtls-tutorial */ -void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, - void *p_timer, - mbedtls_ssl_set_timer_t *f_set_timer, - mbedtls_ssl_get_timer_t *f_get_timer ); +void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer); /** * \brief Callback type: generate and write session ticket @@ -1187,12 +1180,12 @@ void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, * \return 0 if successful, or * a specific MBEDTLS_ERR_XXX code. */ -typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, - const mbedtls_ssl_session *session, - unsigned char *start, - const unsigned char *end, - size_t *tlen, - uint32_t *lifetime ); +typedef int mbedtls_ssl_ticket_write_t(void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime); #if defined(MBEDTLS_SSL_EXPORT_KEYS) /** @@ -1215,12 +1208,12 @@ typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, * \return 0 if successful, or * a specific MBEDTLS_ERR_XXX code. */ -typedef int mbedtls_ssl_export_keys_t( void *p_expkey, - const unsigned char *ms, - const unsigned char *kb, - size_t maclen, - size_t keylen, - size_t ivlen ); +typedef int mbedtls_ssl_export_keys_t(void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen); #endif /* MBEDTLS_SSL_EXPORT_KEYS */ /** @@ -1246,10 +1239,10 @@ typedef int mbedtls_ssl_export_keys_t( void *p_expkey, * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or * any other non-zero code for other failures. */ -typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, - mbedtls_ssl_session *session, - unsigned char *buf, - size_t len ); +typedef int mbedtls_ssl_ticket_parse_t(void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** @@ -1266,10 +1259,10 @@ typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, * \param f_ticket_parse Callback for parsing a ticket * \param p_ticket Context shared by the two callbacks */ -void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, +void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, - void *p_ticket ); + void *p_ticket); #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_EXPORT_KEYS) @@ -1283,9 +1276,9 @@ void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, * \param f_export_keys Callback for exporting keys * \param p_export_keys Context for the callback */ -void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, +void mbedtls_ssl_conf_export_keys_cb(mbedtls_ssl_config *conf, mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys ); + void *p_export_keys); #endif /* MBEDTLS_SSL_EXPORT_KEYS */ /** @@ -1302,9 +1295,9 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, * \return The callback must return 0 on success, * or a negative error code. */ -typedef int mbedtls_ssl_cookie_write_t( void *ctx, - unsigned char **p, unsigned char *end, - const unsigned char *info, size_t ilen ); +typedef int mbedtls_ssl_cookie_write_t(void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen); /** * \brief Callback type: verify a cookie @@ -1319,9 +1312,9 @@ typedef int mbedtls_ssl_cookie_write_t( void *ctx, * \return The callback must return 0 if cookie is valid, * or a negative error code. */ -typedef int mbedtls_ssl_cookie_check_t( void *ctx, - const unsigned char *cookie, size_t clen, - const unsigned char *info, size_t ilen ); +typedef int mbedtls_ssl_cookie_check_t(void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** @@ -1352,10 +1345,10 @@ typedef int mbedtls_ssl_cookie_check_t( void *ctx, * \param f_cookie_check Cookie check callback * \param p_cookie Context for both callbacks */ -void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie ); +void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie); /** * \brief Set client's transport-level identification info. @@ -1376,9 +1369,9 @@ void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. */ -int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, - const unsigned char *info, - size_t ilen ); +int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen); #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ @@ -1398,7 +1391,7 @@ int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, * packets and needs information about them to adjust its * transmission strategy, then you'll want to disable this. */ -void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode); #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) @@ -1425,7 +1418,7 @@ void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); * might make us waste resources checking authentication on * many bogus packets. */ -void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit); #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_DTLS) @@ -1460,7 +1453,7 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> * resend ... 5s -> give up and return a timeout error. */ -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, uint32_t max); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_SRV_C) @@ -1501,10 +1494,10 @@ void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, * \param f_get_cache session get callback * \param f_set_cache session set callback */ -void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, +void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, void *p_cache, int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); + int (*f_set_cache)(void *, const mbedtls_ssl_session *)); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) @@ -1522,7 +1515,7 @@ void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, * * \sa mbedtls_ssl_get_session() */ -int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** @@ -1540,8 +1533,8 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session * \param conf SSL configuration * \param ciphersuites 0-terminated list of allowed ciphersuites */ -void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, - const int *ciphersuites ); +void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, + const int *ciphersuites); /** * \brief Set the list of allowed ciphersuites and the @@ -1562,9 +1555,9 @@ void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 */ -void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor ); +void mbedtls_ssl_conf_ciphersuites_for_version(mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor); #if defined(MBEDTLS_X509_CRT_PARSE_C) /** @@ -1577,8 +1570,8 @@ void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, * \param conf SSL configuration * \param profile Profile to use */ -void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - const mbedtls_x509_crt_profile *profile ); +void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile); /** * \brief Set the data required to verify peer certificate @@ -1587,9 +1580,9 @@ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs */ -void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ); +void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl); /** * \brief Set own certificate chain and private key @@ -1619,9 +1612,9 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, * * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED */ -int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ); +int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) @@ -1645,9 +1638,9 @@ int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, * * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED */ -int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len ); +int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len); /** @@ -1662,8 +1655,8 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, * * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED */ -int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, - const unsigned char *psk, size_t psk_len ); +int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len); /** * \brief Set the PSK callback (server-side only). @@ -1689,10 +1682,10 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, * \param f_psk PSK identity function * \param p_psk PSK identity parameter */ -void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_psk ); +void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk); #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) @@ -1707,7 +1700,7 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, * * \return 0 if successful */ -int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ); +int mbedtls_ssl_conf_dh_param(mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G); /** * \brief Set the Diffie-Hellman public P and G values, @@ -1718,7 +1711,7 @@ int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, cons * * \return 0 if successful */ -int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx); #endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) @@ -1730,8 +1723,8 @@ int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context * \param conf SSL configuration * \param bitlen Minimum bit length of the DHM prime */ -void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, - unsigned int bitlen ); +void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, + unsigned int bitlen); #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_ECP_C) @@ -1762,8 +1755,8 @@ void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, * \param curves Ordered list of allowed curves, * terminated by MBEDTLS_ECP_DP_NONE. */ -void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curves ); +void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) @@ -1785,8 +1778,8 @@ void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, * \param hashes Ordered list of allowed signature hashes, * terminated by \c MBEDTLS_MD_NONE. */ -void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, - const int *hashes ); +void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, + const int *hashes); #endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -1801,7 +1794,7 @@ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, * * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED */ -int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -1817,9 +1810,9 @@ int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); * * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED */ -int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ); +int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key); /** * \brief Set the data required to verify peer certificate for the @@ -1832,9 +1825,9 @@ int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs */ -void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ); +void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl); /** * \brief Set authmode for the current handshake. @@ -1846,8 +1839,8 @@ void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or * MBEDTLS_SSL_VERIFY_REQUIRED */ -void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, - int authmode ); +void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, + int authmode); /** * \brief Set server side ServerName TLS extension callback @@ -1872,10 +1865,10 @@ void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, * \param f_sni verification function * \param p_sni verification parameter */ -void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, - int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_sni ); +void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni); #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1896,9 +1889,9 @@ void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, * * \return 0 on success, or a negative error code. */ -int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len ); +int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len); #endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) @@ -1914,7 +1907,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, * * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. */ -int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); +int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos); /** * \brief Get the name of the negotiated Application Layer Protocol. @@ -1925,7 +1918,7 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot * * \return Protcol name, or NULL if no protocol was negotiated. */ -const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_ALPN */ /** @@ -1944,7 +1937,7 @@ const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, * MBEDTLS_SSL_MINOR_VERSION_3 supported) */ -void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); +void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor); /** * \brief Set the minimum accepted SSL/TLS protocol version @@ -1964,7 +1957,7 @@ void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int mino * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, * MBEDTLS_SSL_MINOR_VERSION_3 supported) */ -void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); +void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor); #if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) /** @@ -1986,7 +1979,7 @@ void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int mino * \param conf SSL configuration * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK */ -void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +void mbedtls_ssl_conf_fallback(mbedtls_ssl_config *conf, char fallback); #endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) @@ -2001,7 +1994,7 @@ void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); * \param conf SSL configuration * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED */ -void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm); #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) @@ -2016,7 +2009,7 @@ void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); * \param conf SSL configuration * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED */ -void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems); #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_ARC4_C) @@ -2035,7 +2028,7 @@ void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems * \param conf SSL configuration * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED */ -void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +void mbedtls_ssl_conf_arc4_support(mbedtls_ssl_config *conf, char arc4); #endif /* MBEDTLS_ARC4_C */ #if defined(MBEDTLS_SSL_SRV_C) @@ -2048,8 +2041,8 @@ void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED */ -void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, - char cert_req_ca_list ); +void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, + char cert_req_ca_list); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) @@ -2068,7 +2061,7 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, * * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA */ -int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) @@ -2080,7 +2073,7 @@ int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_c * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) */ -void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +void mbedtls_ssl_conf_truncated_hmac(mbedtls_ssl_config *conf, int truncate); #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) @@ -2095,7 +2088,7 @@ void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED */ -void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +void mbedtls_ssl_conf_cbc_record_splitting(mbedtls_ssl_config *conf, char split); #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) @@ -2109,7 +2102,7 @@ void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) */ -void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets); #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_RENEGOTIATION) @@ -2130,7 +2123,7 @@ void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or * MBEDTLS_SSL_RENEGOTIATION_DISABLED) */ -void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** @@ -2160,7 +2153,7 @@ void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation * SSL_ALLOW_LEGACY_RENEGOTIATION or * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) */ -void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); +void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy); #if defined(MBEDTLS_SSL_RENEGOTIATION) /** @@ -2200,7 +2193,7 @@ void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_ * enforce renegotiation, or a non-negative value to enforce * it but allow for a grace period of max_records records. */ -void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); +void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records); /** * \brief Set record counter threshold for periodic renegotiation. @@ -2227,8 +2220,8 @@ void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_ * \param conf SSL configuration * \param period The threshold value: a big-endian 64-bit number. */ -void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, - const unsigned char period[8] ); +void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, + const unsigned char period[8]); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** @@ -2238,7 +2231,7 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, * * \return how many bytes are available in the read buffer */ -size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); +size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl); /** * \brief Return the result of the certificate verification @@ -2251,7 +2244,7 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); * a combination of BADCERT_xxx and BADCRL_xxx flags, see * x509.h */ -uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); +uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl); /** * \brief Return the name of the current ciphersuite @@ -2260,7 +2253,7 @@ uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); * * \return a string containing the ciphersuite name */ -const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); +const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl); /** * \brief Return the current SSL version (SSLv3/TLSv1/etc) @@ -2269,7 +2262,7 @@ const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); * * \return a string containing the SSL version */ -const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); +const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl); /** * \brief Return the (maximum) number of bytes added by the record @@ -2281,7 +2274,7 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is * enabled, which makes expansion much less predictable */ -int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); +int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** @@ -2300,7 +2293,7 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); * * \return Current maximum fragment length. */ -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +size_t mbedtls_ssl_get_max_frag_len(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -2318,7 +2311,7 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); * * \return the current peer certificate */ -const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) @@ -2338,7 +2331,7 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * * \sa mbedtls_ssl_set_session() */ -int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** @@ -2362,7 +2355,7 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * purposes, as it is an expected return value rather than an * actual error, but you still need to reset/free the context. */ -int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); /** * \brief Perform a single step of the SSL handshake @@ -2383,7 +2376,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or * a specific SSL error code. */ -int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_RENEGOTIATION) /** @@ -2404,7 +2397,7 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); * \c mbedtls_ssl_session_reset() on it before re-using it for * a new connection; the current connection must be closed. */ -int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** @@ -2441,7 +2434,7 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! */ -int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); +int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); /** * \brief Try to write exactly 'len' application data bytes @@ -2478,7 +2471,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * \c mbedtls_ssl_get_max_frag_len() may be used to query the * active maximum fragment length. */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); +int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); /** * \brief Send an alert message @@ -2496,9 +2489,9 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ * \c mbedtls_ssl_session_reset() on it before re-using it for * a new connection; the current connection must be closed. */ -int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, - unsigned char level, - unsigned char message ); +int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message); /** * \brief Notify the peer that the connection is being closed * @@ -2512,14 +2505,14 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, * \c mbedtls_ssl_session_reset() on it before re-using it for * a new connection; the current connection must be closed. */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); /** * \brief Free referenced items in an SSL context and clear memory * * \param ssl SSL context */ -void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_free(mbedtls_ssl_context *ssl); /** * \brief Initialize an SSL configuration context @@ -2531,7 +2524,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * * \param conf SSL configuration context */ -void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); +void mbedtls_ssl_config_init(mbedtls_ssl_config *conf); /** * \brief Load reasonnable default SSL configuration values. @@ -2548,22 +2541,22 @@ void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); * \return 0 if successful, or * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. */ -int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, - int endpoint, int transport, int preset ); +int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, + int endpoint, int transport, int preset); /** * \brief Free an SSL configuration context * * \param conf SSL configuration context */ -void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); +void mbedtls_ssl_config_free(mbedtls_ssl_config *conf); /** * \brief Initialize SSL session structure * * \param session SSL session */ -void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); +void mbedtls_ssl_session_init(mbedtls_ssl_session *session); /** * \brief Free referenced items in an SSL session including the @@ -2571,7 +2564,7 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); * * \param session SSL session */ -void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); +void mbedtls_ssl_session_free(mbedtls_ssl_session *session); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_ciphersuites.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h similarity index 92% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_ciphersuites.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h index deaaa37..9551b95 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_ciphersuites.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -1,25 +1,9 @@ -/** - * \file ssl_ciphersuites.h - * - * \brief SSL Ciphersuites for mbed TLS - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H @@ -285,10 +269,9 @@ typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; /** * \brief This structure is used for storing ciphersuite information */ -struct mbedtls_ssl_ciphersuite_t -{ +struct mbedtls_ssl_ciphersuite_t { int id; - const char * name; + const char *name; mbedtls_cipher_type_t cipher; mbedtls_md_type_t mac; @@ -302,17 +285,17 @@ struct mbedtls_ssl_ciphersuite_t unsigned char flags; }; -const int *mbedtls_ssl_list_ciphersuites( void ); +const int *mbedtls_ssl_list_ciphersuites(void); -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(const char *ciphersuite_name); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite_id); #if defined(MBEDTLS_PK_C) -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info); #endif -int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); -int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info); +int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info); #ifdef __cplusplus } diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_cookie.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_cookie.h similarity index 56% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_cookie.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_cookie.h index 037e1c3..27768f6 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_cookie.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_cookie.h @@ -1,32 +1,16 @@ -/** - * \file ssl_cookie.h - * - * \brief DTLS cookie callbacks implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H #include "ssl.h" #if defined(MBEDTLS_THREADING_C) -#include "threading.h" + #include "threading.h" #endif /** @@ -37,7 +21,7 @@ * \{ */ #ifndef MBEDTLS_SSL_COOKIE_TIMEOUT -#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + #define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ #endif /* \} name SECTION: Module settings */ @@ -49,8 +33,7 @@ extern "C" { /** * \brief Context for the default cookie functions. */ -typedef struct -{ +typedef struct { mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ #if !defined(MBEDTLS_HAVE_TIME) unsigned long serial; /*!< serial number for expiration */ @@ -66,14 +49,14 @@ typedef struct /** * \brief Initialize cookie context */ -void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); +void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx); /** * \brief Setup cookie context (generate keys) */ -int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); /** * \brief Set expiration delay for cookies @@ -84,12 +67,12 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, * issued in the meantime. * 0 to disable expiration (NOT recommended) */ -void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); +void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay); /** * \brief Free cookie context */ -void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); +void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx); /** * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_internal.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_internal.h similarity index 60% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_internal.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_internal.h index 668c0f5..3e97a1e 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/ssl_internal.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/ssl_internal.h @@ -1,91 +1,75 @@ -/** - * \file ssl_ticket.h - * - * \brief Internal functions shared by the SSL modules - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_SSL_INTERNAL_H #define MBEDTLS_SSL_INTERNAL_H #include "ssl.h" #if defined(MBEDTLS_MD5_C) -#include "md5.h" + #include "md5.h" #endif #if defined(MBEDTLS_SHA1_C) -#include "sha1.h" + #include "sha1.h" #endif #if defined(MBEDTLS_SHA256_C) -#include "sha256.h" + #include "sha256.h" #endif #if defined(MBEDTLS_SHA512_C) -#include "sha512.h" + #include "sha512.h" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#include "ecjpake.h" + #include "ecjpake.h" #endif #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) -#define inline __inline + #define inline __inline #endif /* Determine minimum supported version */ #define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 #if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 + #define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 #else -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ + #if defined(MBEDTLS_SSL_PROTO_TLS1) + #define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 + #else + #if defined(MBEDTLS_SSL_PROTO_TLS1_1) + #define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 + #else + #if defined(MBEDTLS_SSL_PROTO_TLS1_2) + #define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 + #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ + #endif /* MBEDTLS_SSL_PROTO_TLS1 */ #endif /* MBEDTLS_SSL_PROTO_SSL3 */ /* Determine maximum supported version */ #define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 + #define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 #else -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ + #if defined(MBEDTLS_SSL_PROTO_TLS1_1) + #define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 + #else + #if defined(MBEDTLS_SSL_PROTO_TLS1) + #define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 + #else + #if defined(MBEDTLS_SSL_PROTO_SSL3) + #define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 + #endif /* MBEDTLS_SSL_PROTO_SSL3 */ + #endif /* MBEDTLS_SSL_PROTO_TLS1 */ + #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 @@ -113,37 +97,37 @@ * enabled. */ #if defined(MBEDTLS_ZLIB_SUPPORT) -#define MBEDTLS_SSL_COMPRESSION_ADD 1024 + #define MBEDTLS_SSL_COMPRESSION_ADD 1024 #else -#define MBEDTLS_SSL_COMPRESSION_ADD 0 + #define MBEDTLS_SSL_COMPRESSION_ADD 0 #endif #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) -/* Ciphersuites using HMAC */ -#if defined(MBEDTLS_SHA512_C) -#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ -#elif defined(MBEDTLS_SHA256_C) -#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ + /* Ciphersuites using HMAC */ + #if defined(MBEDTLS_SHA512_C) + #define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ + #elif defined(MBEDTLS_SHA256_C) + #define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ + #else + #define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ + #endif #else -#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ -#endif -#else -/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ -#define MBEDTLS_SSL_MAC_ADD 16 + /* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ + #define MBEDTLS_SSL_MAC_ADD 16 #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_SSL_PADDING_ADD 256 + #define MBEDTLS_SSL_PADDING_ADD 256 #else -#define MBEDTLS_SSL_PADDING_ADD 0 + #define MBEDTLS_SSL_PADDING_ADD 0 #endif #define MBEDTLS_SSL_BUFFER_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ - + MBEDTLS_SSL_COMPRESSION_ADD \ - + 29 /* counter + header + IV */ \ - + MBEDTLS_SSL_MAC_ADD \ - + MBEDTLS_SSL_PADDING_ADD \ - ) + + MBEDTLS_SSL_COMPRESSION_ADD \ + + 29 /* counter + header + IV */ \ + + MBEDTLS_SSL_MAC_ADD \ + + MBEDTLS_SSL_PADDING_ADD \ + ) /* * TLS extension flags (for extensions with outgoing ServerHello content @@ -160,8 +144,7 @@ extern "C" { /* * This structure contains the parameters only needed during handshake. */ -struct mbedtls_ssl_handshake_params -{ +struct mbedtls_ssl_handshake_params { /* * Handshake specific crypto variables */ @@ -225,8 +208,8 @@ struct mbedtls_ssl_handshake_params */ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_context fin_md5; - mbedtls_sha1_context fin_sha1; + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) @@ -240,15 +223,15 @@ struct mbedtls_ssl_handshake_params void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); - int (*tls_prf)(const unsigned char *, size_t, const char *, - const unsigned char *, size_t, - unsigned char *, size_t); + int (*tls_prf)(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); size_t pmslen; /*!< premaster length */ unsigned char randbytes[64]; /*!< random bytes */ unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; - /*!< premaster secret */ + /*!< premaster secret */ int resume; /*!< session resume indicator*/ int max_major_ver; /*!< max. major version client*/ @@ -267,13 +250,12 @@ struct mbedtls_ssl_handshake_params * This structure contains a full set of runtime transform parameters * either in negotiation or active. */ -struct mbedtls_ssl_transform -{ +struct mbedtls_ssl_transform { /* * Session specific crypto layer */ const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - /*!< Chosen cipersuite_info */ + /*!< Chosen cipersuite_info */ unsigned int keylen; /*!< symmetric key length (bytes) */ size_t minlen; /*!< min. ciphertext length */ size_t ivlen; /*!< IV length */ @@ -308,8 +290,7 @@ struct mbedtls_ssl_transform /* * List of certificate + private key pairs */ -struct mbedtls_ssl_key_cert -{ +struct mbedtls_ssl_key_cert { mbedtls_x509_crt *cert; /*!< cert */ mbedtls_pk_context *key; /*!< private key */ mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ @@ -320,8 +301,7 @@ struct mbedtls_ssl_key_cert /* * List of handshake messages kept around for resending */ -struct mbedtls_ssl_flight_item -{ +struct mbedtls_ssl_flight_item { unsigned char *p; /*!< message, including handshake headers */ size_t len; /*!< length of p */ unsigned char type; /*!< type of the message: handshake or CCS */ @@ -336,7 +316,7 @@ struct mbedtls_ssl_flight_item * * \param transform SSL transform context */ -void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); +void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform); /** * \brief Free referenced items in an SSL handshake context and clear @@ -344,85 +324,87 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); * * \param handshake SSL handshake context */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); +void mbedtls_ssl_handshake_free(mbedtls_ssl_handshake_params *handshake); -int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); +int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); +void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl); -int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); -void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl); +int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl); -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_read_record_layer(mbedtls_ssl_context *ssl); +int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl); +int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl); +void mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl); -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); +int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl); +int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want); -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl); +int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl); -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl); +int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl); -int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl); +int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl); -int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl); +int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl); -void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); +void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); +int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex); #endif #if defined(MBEDTLS_PK_C) -unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig); #endif -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); -unsigned char mbedtls_ssl_hash_from_md_alg( int md ); -int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash); +unsigned char mbedtls_ssl_hash_from_md_alg(int md); +int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md); #if defined(MBEDTLS_ECP_C) -int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id); #endif #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md ); +int mbedtls_ssl_check_sig_hash(const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) -static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +static inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert; - if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { key_cert = ssl->handshake->key_cert; - else + } else { key_cert = ssl->conf->key_cert; + } - return( key_cert == NULL ? NULL : key_cert->key ); + return (key_cert == NULL ? NULL : key_cert->key); } -static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert; - if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { key_cert = ssl->handshake->key_cert; - else + } else { key_cert = ssl->conf->key_cert; + } - return( key_cert == NULL ? NULL : key_cert->cert ); + return (key_cert == NULL ? NULL : key_cert->cert); } /* @@ -434,63 +416,66 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) * * Return 0 if everything is OK, -1 if not. */ -int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags ); +int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags); #endif /* MBEDTLS_X509_CRT_PARSE_C */ -void mbedtls_ssl_write_version( int major, int minor, int transport, - unsigned char ver[2] ); -void mbedtls_ssl_read_version( int *major, int *minor, int transport, - const unsigned char ver[2] ); +void mbedtls_ssl_write_version(int major, int minor, int transport, + unsigned char ver[2]); +void mbedtls_ssl_read_version(int *major, int *minor, int transport, + const unsigned char ver[2]); -static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) +static inline size_t mbedtls_ssl_hdr_len(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 13 ); + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return (13); + } #else ((void) ssl); #endif - return( 5 ); + return (5); } -static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +static inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 12 ); + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return (12); + } #else ((void) ssl); #endif - return( 4 ); + return (4); } #if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl); +void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl); +int mbedtls_ssl_resend(mbedtls_ssl_context *ssl); #endif /* Visible for testing purposes only */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context *ssl); +void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl); #endif /* constant-time buffer comparison */ -static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) +static inline int mbedtls_ssl_safer_memcmp(const void *a, const void *b, size_t n) { size_t i; const unsigned char *A = (const unsigned char *) a; const unsigned char *B = (const unsigned char *) b; unsigned char diff = 0; - for( i = 0; i < n; i++ ) + for (i = 0; i < n; i++) { diff |= A[i] ^ B[i]; + } - return( diff ); + return (diff); } #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/timing.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/timing.h similarity index 66% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/timing.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/timing.h index ae7a713..776a6eb 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/timing.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/timing.h @@ -1,32 +1,16 @@ -/** - * \file timing.h - * - * \brief Portable interface to the CPU cycle counter - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_TIMING_H #define MBEDTLS_TIMING_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #if !defined(MBEDTLS_TIMING_ALT) @@ -42,16 +26,14 @@ extern "C" { /** * \brief timer structure */ -struct mbedtls_timing_hr_time -{ +struct mbedtls_timing_hr_time { unsigned char opaque[32]; }; /** * \brief Context for mbedtls_timing_set/get_delay() */ -typedef struct -{ +typedef struct { struct mbedtls_timing_hr_time timer; uint32_t int_ms; uint32_t fin_ms; @@ -66,7 +48,7 @@ extern volatile int mbedtls_timing_alarmed; * In particular, it is known to be unreliable on virtual * machines. */ -unsigned long mbedtls_timing_hardclock( void ); +unsigned long mbedtls_timing_hardclock(void); /** * \brief Return the elapsed time in milliseconds @@ -74,7 +56,7 @@ unsigned long mbedtls_timing_hardclock( void ); * \param val points to a timer structure * \param reset if set to 1, the timer is restarted */ -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); +unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); /** * \brief Setup an alarm clock @@ -85,7 +67,7 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int * context, this means one for the whole process, not one per * thread. */ -void mbedtls_set_alarm( int seconds ); +void mbedtls_set_alarm(int seconds); /** * \brief Set a pair of delays to watch @@ -97,7 +79,7 @@ void mbedtls_set_alarm( int seconds ); * \param fin_ms Second (final) delay in milliseconds. * Pass 0 to cancel the current delay. */ -void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); +void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms); /** * \brief Get the status of delays @@ -111,7 +93,7 @@ void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); * 1 if only the intermediate delay is passed, * 2 if the final delay is passed. */ -int mbedtls_timing_get_delay( void *data ); +int mbedtls_timing_get_delay(void *data); #ifdef __cplusplus } @@ -131,7 +113,7 @@ extern "C" { * * \return 0 if successful, or 1 if a test failed */ -int mbedtls_timing_self_test( int verbose ); +int mbedtls_timing_self_test(int verbose); #endif #ifdef __cplusplus diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509.h similarity index 74% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509.h index f219bf1..7fa899b 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509.h @@ -1,39 +1,23 @@ -/** - * \file x509.h - * - * \brief X.509 generic defines and structures - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_X509_H #define MBEDTLS_X509_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "asn1.h" #include "pk.h" #if defined(MBEDTLS_RSA_C) -#include "rsa.h" + #include "rsa.h" #endif /** @@ -42,15 +26,15 @@ */ #if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) -/** - * Maximum number of intermediate CAs in a verification chain. - * That is, maximum length of the chain, excluding the end-entity certificate - * and the trusted root certificate. - * - * Set this to a low value to prevent an adversary from making you waste - * resources verifying an overlong certificate chain. - */ -#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 + /** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ + #define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 #endif /** @@ -203,8 +187,7 @@ typedef mbedtls_asn1_named_data mbedtls_x509_name; typedef mbedtls_asn1_sequence mbedtls_x509_sequence; /** Container for date and time (precision in seconds). */ -typedef struct mbedtls_x509_time -{ +typedef struct mbedtls_x509_time { int year, mon, day; /**< Date. */ int hour, min, sec; /**< Time. */ } @@ -224,7 +207,7 @@ mbedtls_x509_time; * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ -int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); +int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn); /** * \brief Store the certificate serial in printable form into buf; @@ -237,7 +220,7 @@ int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ -int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); +int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial); /** * \brief Check a given mbedtls_x509_time against the system time @@ -251,7 +234,7 @@ int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *se * \return 1 if the given time is in the past or an error occured, * 0 otherwise. */ -int mbedtls_x509_time_is_past( const mbedtls_x509_time *time ); +int mbedtls_x509_time_is_past(const mbedtls_x509_time *time); /** * \brief Check a given mbedtls_x509_time against the system time @@ -265,61 +248,61 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *time ); * \return 1 if the given time is in the future or an error occured, * 0 otherwise. */ -int mbedtls_x509_time_is_future( const mbedtls_x509_time *time ); +int mbedtls_x509_time_is_future(const mbedtls_x509_time *time); /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ -int mbedtls_x509_self_test( int verbose ); +int mbedtls_x509_self_test(int verbose); /* * Internal module functions. You probably do not want to use these unless you * know you do. */ -int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, - mbedtls_x509_name *cur ); -int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg ); -int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur); +int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg); +int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) -int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, - mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, - int *salt_len ); +int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len); #endif -int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); -int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, - void **sig_opts ); -int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *time ); -int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *serial ); -int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *ext, int tag ); -int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const void *sig_opts ); -int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); -int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); -int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, - int critical, const unsigned char *val, - size_t val_len ); -int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ); -int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ); -int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - unsigned char *sig, size_t size ); +int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig); +int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts); +int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, + mbedtls_x509_time *time); +int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial); +int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag); +int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts); +int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name); +int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name); +int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len); +int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first); +int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first); +int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size); #define MBEDTLS_X509_SAFE_SNPRINTF \ do { \ if( ret < 0 || (size_t) ret >= n ) \ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ - \ + \ n -= (size_t) ret; \ p += (size_t) ret; \ } while( 0 ) diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509_crl.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509_crl.h similarity index 67% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509_crl.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509_crl.h index 7988439..75172d9 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509_crl.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509_crl.h @@ -1,32 +1,16 @@ -/** - * \file x509_crl.h - * - * \brief X.509 certificate revocation list parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_X509_CRL_H #define MBEDTLS_X509_CRL_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "x509.h" @@ -48,8 +32,7 @@ extern "C" { * Certificate revocation list entry. * Contains the CA-specific serial numbers and revocation dates. */ -typedef struct mbedtls_x509_crl_entry -{ +typedef struct mbedtls_x509_crl_entry { mbedtls_x509_buf raw; mbedtls_x509_buf serial; @@ -66,8 +49,7 @@ mbedtls_x509_crl_entry; * Certificate revocation list structure. * Every CRL may have multiple entries. */ -typedef struct mbedtls_x509_crl -{ +typedef struct mbedtls_x509_crl { mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ @@ -87,8 +69,10 @@ typedef struct mbedtls_x509_crl mbedtls_x509_buf sig_oid2; mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + mbedtls_md_type_t + sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t + sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ struct mbedtls_x509_crl *next; @@ -105,8 +89,8 @@ mbedtls_x509_crl; * * \return 0 if successful, or a specific X509 or PEM error code */ -int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, - const unsigned char *buf, size_t buflen ); +int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen); /** * \brief Parse one or more CRLs and append them to the chained list * @@ -119,7 +103,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, * * \return 0 if successful, or a specific X509 or PEM error code */ -int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); +int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** @@ -132,7 +116,7 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s * * \return 0 if successful, or a specific X509 or PEM error code */ -int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path); #endif /* MBEDTLS_FS_IO */ /** @@ -146,22 +130,22 @@ int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ -int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crl *crl ); +int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl); /** * \brief Initialize a CRL (chain) * * \param crl CRL chain to initialize */ -void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); +void mbedtls_x509_crl_init(mbedtls_x509_crl *crl); /** * \brief Unallocate all CRL data * * \param crl CRL chain to free */ -void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); +void mbedtls_x509_crl_free(mbedtls_x509_crl *crl); /* \} name */ /* \} addtogroup x509_module */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509_crt.h b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509_crt.h similarity index 79% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509_crt.h rename to iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509_crt.h index 383e484..c7ea581 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/x509_crt.h +++ b/iotkit-embedded/external_libs/mbedtls/include/mbedtls/x509_crt.h @@ -1,32 +1,16 @@ -/** - * \file x509_crt.h - * - * \brief X.509 certificate parsing and writing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #ifndef MBEDTLS_X509_CRT_H #define MBEDTLS_X509_CRT_H #if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" + #include "config.h" #else -#include MBEDTLS_CONFIG_FILE + #include MBEDTLS_CONFIG_FILE #endif #include "x509.h" @@ -49,8 +33,7 @@ extern "C" { /** * Container for an X.509 certificate. The certificate may be chained. */ -typedef struct mbedtls_x509_crt -{ +typedef struct mbedtls_x509_crt { mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ @@ -85,8 +68,10 @@ typedef struct mbedtls_x509_crt unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + mbedtls_md_type_t + sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t + sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ @@ -104,8 +89,7 @@ mbedtls_x509_crt; * * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). */ -typedef struct -{ +typedef struct { uint32_t allowed_mds; /**< MDs for signatures */ uint32_t allowed_pks; /**< PK algs for signatures */ uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ @@ -127,8 +111,7 @@ mbedtls_x509_crt_profile; /** * Container for writing a certificate (CRT) */ -typedef struct mbedtls_x509write_cert -{ +typedef struct mbedtls_x509write_cert { int version; mbedtls_mpi serial; mbedtls_pk_context *subject_key; @@ -170,8 +153,8 @@ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; * * \return 0 if successful, or a specific X509 or PEM error code */ -int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, - size_t buflen ); +int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen); /** * \brief Parse one or more certificates and add them @@ -188,7 +171,7 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ -int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); +int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** @@ -204,7 +187,7 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ -int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); +int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path); /** * \brief Load one or more certificate files from a path and add them @@ -219,7 +202,7 @@ int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ -int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path); #endif /* MBEDTLS_FS_IO */ /** @@ -234,8 +217,8 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ -int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt ); +int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt); /** * \brief Returns an informational string about the @@ -249,8 +232,8 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ -int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, - uint32_t flags ); +int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, + uint32_t flags); /** * \brief Verify the certificate signature @@ -296,12 +279,12 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * or another error in case of a fatal error encountered * during the verification process. */ -int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); +int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy); /** * \brief Verify the certificate signature according to profile @@ -330,13 +313,13 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, * or another error in case of a fatal error encountered * during the verification process. */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); +int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy); #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** @@ -360,8 +343,8 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * (intermediate) CAs the keyUsage extension is automatically * checked by \c mbedtls_x509_crt_verify(). */ -int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, - unsigned int usage ); +int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, + unsigned int usage); #endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) @@ -377,9 +360,9 @@ int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, * * \note Usually only makes sense on leaf certificates. */ -int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len ); +int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len); #endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) */ #if defined(MBEDTLS_X509_CRL_PARSE_C) @@ -392,7 +375,7 @@ int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, * \return 1 if the certificate is revoked, 0 otherwise * */ -int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl); #endif /* MBEDTLS_X509_CRL_PARSE_C */ /** @@ -400,14 +383,14 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509 * * \param crt Certificate chain to initialize */ -void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); +void mbedtls_x509_crt_init(mbedtls_x509_crt *crt); /** * \brief Unallocate all certificate data * * \param crt Certificate chain to free */ -void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); +void mbedtls_x509_crt_free(mbedtls_x509_crt *crt); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* \} name */ @@ -419,7 +402,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); * * \param ctx CRT context to initialize */ -void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); +void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx); /** * \brief Set the verion for a Certificate @@ -429,7 +412,7 @@ void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or * MBEDTLS_X509_CRT_VERSION_3) */ -void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); +void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version); /** * \brief Set the serial number for a Certificate. @@ -439,7 +422,7 @@ void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version * * \return 0 if successful */ -int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); +int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); /** * \brief Set the validity period for a Certificate @@ -455,8 +438,8 @@ int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls * \return 0 if timestamp was parsed successfully, or * a specific error code */ -int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, - const char *not_after ); +int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after); /** * \brief Set the issuer name for a Certificate @@ -470,8 +453,8 @@ int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char * \return 0 if issuer name was parsed successfully, or * a specific error code */ -int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, - const char *issuer_name ); +int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, + const char *issuer_name); /** * \brief Set the subject name for a Certificate @@ -485,8 +468,8 @@ int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, * \return 0 if subject name was parsed successfully, or * a specific error code */ -int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, - const char *subject_name ); +int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx, + const char *subject_name); /** * \brief Set the subject public key for the certificate @@ -494,7 +477,7 @@ int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, * \param ctx CRT context to use * \param key public key to include */ -void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); +void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key); /** * \brief Set the issuer key used for signing the certificate @@ -502,7 +485,7 @@ void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls * \param ctx CRT context to use * \param key private key to sign with */ -void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); +void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key); /** * \brief Set the MD algorithm to use for the signature @@ -511,7 +494,7 @@ void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_ * \param ctx CRT context to use * \param md_alg MD algorithm to use */ -void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); +void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg); /** * \brief Generic function to add to or replace an extension in the @@ -526,10 +509,10 @@ void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_t * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ -int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, - const char *oid, size_t oid_len, - int critical, - const unsigned char *val, size_t val_len ); +int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len); /** * \brief Set the basicConstraints extension for a CRT @@ -542,8 +525,8 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ -int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, - int is_ca, int max_pathlen ); +int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen); #if defined(MBEDTLS_SHA1_C) /** @@ -555,7 +538,7 @@ int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ -int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); +int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx); /** * \brief Set the authorityKeyIdentifier extension for a CRT @@ -566,7 +549,7 @@ int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ct * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ -int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx); #endif /* MBEDTLS_SHA1_C */ /** @@ -578,8 +561,8 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert * * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ -int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, - unsigned int key_usage ); +int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, + unsigned int key_usage); /** * \brief Set the Netscape Cert Type flags @@ -590,15 +573,15 @@ int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ -int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, - unsigned char ns_cert_type ); +int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type); /** * \brief Free the contents of a CRT write context * * \param ctx CRT context to free */ -void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); +void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx); /** * \brief Write a built up certificate to a X509 DER structure @@ -620,9 +603,9 @@ void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); * for countermeasures against timing attacks). * ECDSA signatures always require a non-NULL f_rng. */ -int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); #if defined(MBEDTLS_PEM_WRITE_C) /** @@ -641,9 +624,9 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, * for countermeasures against timing attacks). * ECDSA signatures always require a non-NULL f_rng. */ -int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/iotkit-embedded/external_libs/mbedtls/iot.mk b/iotkit-embedded/external_libs/mbedtls/iot.mk new file mode 100644 index 0000000..5a90afd --- /dev/null +++ b/iotkit-embedded/external_libs/mbedtls/iot.mk @@ -0,0 +1,6 @@ +LIBA_TARGET := libiot_tls.a + +HDR_REFS += src/infra + +CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS)) +CFLAGS := $(filter-out -ansi,$(CFLAGS)) diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/.gitignore b/iotkit-embedded/external_libs/mbedtls/library/.gitignore similarity index 100% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/.gitignore rename to iotkit-embedded/external_libs/mbedtls/library/.gitignore diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/Makefile b/iotkit-embedded/external_libs/mbedtls/library/Makefile similarity index 100% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/Makefile rename to iotkit-embedded/external_libs/mbedtls/library/Makefile diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/aes.c b/iotkit-embedded/external_libs/mbedtls/library/aes.c similarity index 98% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/aes.c rename to iotkit-embedded/external_libs/mbedtls/library/aes.c index 5e01c4f..d944aa4 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/aes.c +++ b/iotkit-embedded/external_libs/mbedtls/library/aes.c @@ -1,23 +1,9 @@ /* - * FIPS-197 compliant AES implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. * @@ -48,7 +34,8 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" +#define mbedtls_printf tls_info #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/asn1parse.c b/iotkit-embedded/external_libs/mbedtls/library/asn1parse.c similarity index 92% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/asn1parse.c rename to iotkit-embedded/external_libs/mbedtls/library/asn1parse.c index 4dd65c0..8a1a55e 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/asn1parse.c +++ b/iotkit-embedded/external_libs/mbedtls/library/asn1parse.c @@ -1,24 +1,10 @@ /* - * Generic ASN.1 parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/base64.c b/iotkit-embedded/external_libs/mbedtls/library/base64.c similarity index 89% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/base64.c rename to iotkit-embedded/external_libs/mbedtls/library/base64.c index f06b57b..b31531f 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/base64.c +++ b/iotkit-embedded/external_libs/mbedtls/library/base64.c @@ -1,24 +1,10 @@ /* - * RFC 1521 base64 encoding/decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -37,7 +23,9 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/bignum.c b/iotkit-embedded/external_libs/mbedtls/library/bignum.c similarity index 98% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/bignum.c rename to iotkit-embedded/external_libs/mbedtls/library/bignum.c index 8b9082c..da75c46 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/bignum.c +++ b/iotkit-embedded/external_libs/mbedtls/library/bignum.c @@ -1,24 +1,10 @@ /* - * Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The following sources were referenced in the design of this Multi-precision * Integer library: @@ -53,7 +39,9 @@ #else #include #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info #define mbedtls_calloc calloc #define mbedtls_free free #endif @@ -292,6 +280,7 @@ int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) int ret; MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + MBEDTLS_MPI_CHK( (X->p == NULL) ); memset( X->p, 0, X->n * ciL ); X->p[0] = ( z < 0 ) ? -z : z; diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/cipher.c b/iotkit-embedded/external_libs/mbedtls/library/cipher.c similarity index 96% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/cipher.c rename to iotkit-embedded/external_libs/mbedtls/library/cipher.c index e9e0b22..70967d4 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/cipher.c +++ b/iotkit-embedded/external_libs/mbedtls/library/cipher.c @@ -1,28 +1,10 @@ -/** - * \file cipher.c - * - * \brief Generic cipher wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -367,11 +349,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i */ if( 0 != ilen ) { - if( 0 == block_size ) - { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } - copy_len = ilen % block_size; if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) copy_len = block_size; diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/cipher_wrap.c b/iotkit-embedded/external_libs/mbedtls/library/cipher_wrap.c similarity index 97% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/cipher_wrap.c rename to iotkit-embedded/external_libs/mbedtls/library/cipher_wrap.c index dc76af8..2ff1063 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/cipher_wrap.c +++ b/iotkit-embedded/external_libs/mbedtls/library/cipher_wrap.c @@ -1,28 +1,10 @@ -/** - * \file cipher_wrap.c - * - * \brief Generic cipher wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ctr_drbg.c b/iotkit-embedded/external_libs/mbedtls/library/ctr_drbg.c similarity index 95% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ctr_drbg.c rename to iotkit-embedded/external_libs/mbedtls/library/ctr_drbg.c index 55612c7..6b282c2 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ctr_drbg.c +++ b/iotkit-embedded/external_libs/mbedtls/library/ctr_drbg.c @@ -1,23 +1,9 @@ /* - * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The NIST SP 800-90 DRBGs are described in the following publucation. * @@ -45,7 +31,9 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ @@ -291,7 +279,8 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, size_t seedlen = 0; if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || - len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len || + len < 0) return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); diff --git a/iotkit-embedded/external_libs/mbedtls/library/debug.c b/iotkit-embedded/external_libs/mbedtls/library/debug.c new file mode 100644 index 0000000..a5e3062 --- /dev/null +++ b/iotkit-embedded/external_libs/mbedtls/library/debug.c @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "mbedtls/config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) + #include "mbedtls/platform.h" +#else + #include + #define mbedtls_calloc calloc + #define mbedtls_free free + #define mbedtls_time_t time_t + #define mbedtls_snprintf snprintf +#endif + +#include "mbedtls/debug.h" + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) + #define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold(int threshold) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *)ssl, str); + ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr); +#else + ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str); +#endif +} + +void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ...) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret; + + if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { + return; + } + + va_start(argp, format); +#if defined(_WIN32) +#if defined(_TRUNCATE) + ret = _vsnprintf_s(str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp); +#else + ret = _vsnprintf(str, DEBUG_BUF_SIZE, format, argp); + if (ret < 0 || (size_t) ret == DEBUG_BUF_SIZE) { + str[DEBUG_BUF_SIZE - 1] = '\0'; + ret = -1; + } +#endif +#else + ret = vsnprintf(str, DEBUG_BUF_SIZE, format, argp); +#endif + va_end(argp); + + if (ret >= 0 && ret < DEBUG_BUF_SIZE - 1) { + //str[ret] = '\n'; + str[ret] = '\0'; + } + + debug_send_line(ssl, level, file, line, str); +} + +void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret) +{ + char str[DEBUG_BUF_SIZE]; + + if (ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold) { + return; + } + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + return; + } + + mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)", + text, ret, -ret); + + debug_send_line(ssl, level, file, line, str); +} + +void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if (ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold) { + return; + } + + mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)", + text, (unsigned int) len); + + debug_send_line(ssl, level, file, line, str); + + idx = 0; + memset(txt, 0, sizeof(txt)); + for (i = 0; i < len; i++) { + if (i >= 4096) { + break; + } + + if (i % 16 == 0) { + if (i > 0) { + mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s", txt); + debug_send_line(ssl, level, file, line, str); + + idx = 0; + memset(txt, 0, sizeof(txt)); + } + + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ", + (unsigned int) i); + + } + + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", + (unsigned int) buf[i]); + txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.' ; + } + + if (len > 0) { + for (/* i = i */; i % 16 != 0; i++) { + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " "); + } + + mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s", txt); + debug_send_line(ssl, level, file, line, str); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X) +{ + char str[DEBUG_BUF_SIZE]; + + if (ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold) { + return; + } + + mbedtls_snprintf(str, sizeof(str), "%s(X)", text); + mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X); + + mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); + mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X) +{ + char str[DEBUG_BUF_SIZE]; + int j, k, zeros = 1; + size_t i, n, idx = 0; + + if (ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold) { + return; + } + + for (n = X->n - 1; n > 0; n--) + if (X->p[n] != 0) { + break; + } + + for (j = (sizeof(mbedtls_mpi_uint) << 3) - 1; j >= 0; j--) + if (((X->p[n] >> j) & 1) != 0) { + break; + } + + mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%d bits) is:\n", + text, (int)((n * (sizeof(mbedtls_mpi_uint) << 3)) + j + 1)); + + debug_send_line(ssl, level, file, line, str); + + idx = 0; + for (i = n + 1, j = 0; i > 0; i--) { + if (zeros && X->p[i - 1] == 0) { + continue; + } + + for (k = sizeof(mbedtls_mpi_uint) - 1; k >= 0; k--) { + if (zeros && ((X->p[i - 1] >> (k << 3)) & 0xFF) == 0) { + continue; + } else { + zeros = 0; + } + + if (j % 16 == 0) { + if (j > 0) { + mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); + debug_send_line(ssl, level, file, line, str); + idx = 0; + } + } + + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", (unsigned int) + (X->p[i - 1] >> (k << 3)) & 0xFF); + + j++; + } + + } + + if (zeros == 1) { + idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " 00"); + } + + mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); + debug_send_line(ssl, level, file, line, str); +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void debug_print_pk(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset(items, 0, sizeof(items)); + + if (mbedtls_pk_debug(pk, items) != 0) { + debug_send_line(ssl, level, file, line, + "invalid PK context\n"); + return; + } + + for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) { + if (items[i].type == MBEDTLS_PK_DEBUG_NONE) { + return; + } + + mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name); + name[sizeof(name) - 1] = '\0'; + + if (items[i].type == MBEDTLS_PK_DEBUG_MPI) { + mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value); + } else +#if defined(MBEDTLS_ECP_C) + if (items[i].type == MBEDTLS_PK_DEBUG_ECP) { + mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value); + } else +#endif + debug_send_line(ssl, level, file, line, + "should not happen\n"); + } +} + +static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for (cur = text; *cur != '\0'; cur++) { + if (*cur == '\n') { + size_t len = cur - start + 1; + if (len > DEBUG_BUF_SIZE - 1) { + len = DEBUG_BUF_SIZE - 1; + } + + memcpy(str, start, len); + str[len] = '\0'; + + debug_send_line(ssl, level, file, line, str); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if (ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold) { + return; + } + + while (crt != NULL) { + char buf[1024]; + + mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i); + debug_send_line(ssl, level, file, line, str); + + mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); + debug_print_line_by_line(ssl, level, file, line, buf); + + debug_print_pk(ssl, level, file, line, "crt->", &crt->pk); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#endif /* MBEDTLS_DEBUG_C */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/entropy.c b/iotkit-embedded/external_libs/mbedtls/library/entropy.c similarity index 95% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/entropy.c rename to iotkit-embedded/external_libs/mbedtls/library/entropy.c index d4d1b27..97381db 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/entropy.c +++ b/iotkit-embedded/external_libs/mbedtls/library/entropy.c @@ -1,24 +1,10 @@ /* - * Entropy accumulator implementation - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -51,7 +37,9 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/entropy_poll.c b/iotkit-embedded/external_libs/mbedtls/library/entropy_poll.c similarity index 88% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/entropy_poll.c rename to iotkit-embedded/external_libs/mbedtls/library/entropy_poll.c index a116e60..33d114d 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/entropy_poll.c +++ b/iotkit-embedded/external_libs/mbedtls/library/entropy_poll.c @@ -1,24 +1,10 @@ /* - * Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/error.c b/iotkit-embedded/external_libs/mbedtls/library/error.c similarity index 97% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/error.c rename to iotkit-embedded/external_libs/mbedtls/library/error.c index dd2db0c..e2d8489 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/error.c +++ b/iotkit-embedded/external_libs/mbedtls/library/error.c @@ -1,24 +1,10 @@ /* - * Error message information - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/md.c b/iotkit-embedded/external_libs/mbedtls/library/md.c similarity index 92% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/md.c rename to iotkit-embedded/external_libs/mbedtls/library/md.c index eda98f6..0034b10 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/md.c +++ b/iotkit-embedded/external_libs/mbedtls/library/md.c @@ -1,28 +1,10 @@ -/** - * \file mbedtls_md.c - * - * \brief Generic message digest wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/md_wrap.c b/iotkit-embedded/external_libs/mbedtls/library/md_wrap.c similarity index 93% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/md_wrap.c rename to iotkit-embedded/external_libs/mbedtls/library/md_wrap.c index 2cfcae2..e3bfba0 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/md_wrap.c +++ b/iotkit-embedded/external_libs/mbedtls/library/md_wrap.c @@ -1,28 +1,10 @@ -/** - * \file md_wrap.c - * - * \brief Generic message digest wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/net_sockets.c b/iotkit-embedded/external_libs/mbedtls/library/net_sockets.c similarity index 95% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/net_sockets.c rename to iotkit-embedded/external_libs/mbedtls/library/net_sockets.c index 80be6ec..e035430 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/net_sockets.c +++ b/iotkit-embedded/external_libs/mbedtls/library/net_sockets.c @@ -1,24 +1,10 @@ /* - * TCP/IP or UDP/IP networking functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/oid.c b/iotkit-embedded/external_libs/mbedtls/library/oid.c similarity index 96% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/oid.c rename to iotkit-embedded/external_libs/mbedtls/library/oid.c index f13826e..ab46171 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/oid.c +++ b/iotkit-embedded/external_libs/mbedtls/library/oid.c @@ -1,26 +1,10 @@ -/** - * \file oid.c - * - * \brief Object Identifier (OID) database - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pem.c b/iotkit-embedded/external_libs/mbedtls/library/pem.c similarity index 94% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pem.c rename to iotkit-embedded/external_libs/mbedtls/library/pem.c index 8dd86a4..89f3b5a 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pem.c +++ b/iotkit-embedded/external_libs/mbedtls/library/pem.c @@ -1,24 +1,10 @@ /* - * Privacy Enhanced Mail (PEM) decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pk.c b/iotkit-embedded/external_libs/mbedtls/library/pk.c similarity index 92% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pk.c rename to iotkit-embedded/external_libs/mbedtls/library/pk.c index 8d13bc5..24ee3c5 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pk.c +++ b/iotkit-embedded/external_libs/mbedtls/library/pk.c @@ -1,24 +1,10 @@ /* - * Public Key abstraction layer - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pk_wrap.c b/iotkit-embedded/external_libs/mbedtls/library/pk_wrap.c similarity index 94% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pk_wrap.c rename to iotkit-embedded/external_libs/mbedtls/library/pk_wrap.c index db6274c..952349b 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pk_wrap.c +++ b/iotkit-embedded/external_libs/mbedtls/library/pk_wrap.c @@ -1,24 +1,10 @@ /* - * Public Key abstraction layer: wrapper functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pkparse.c b/iotkit-embedded/external_libs/mbedtls/library/pkparse.c similarity index 97% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pkparse.c rename to iotkit-embedded/external_libs/mbedtls/library/pkparse.c index efdf437..d4e7f9b 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/pkparse.c +++ b/iotkit-embedded/external_libs/mbedtls/library/pkparse.c @@ -1,24 +1,10 @@ /* - * Public Key layer for parsing key files and structures - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/platform.c b/iotkit-embedded/external_libs/mbedtls/library/platform.c similarity index 90% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/platform.c rename to iotkit-embedded/external_libs/mbedtls/library/platform.c index 8b336c3..32523f5 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/platform.c +++ b/iotkit-embedded/external_libs/mbedtls/library/platform.c @@ -1,24 +1,10 @@ /* - * Platform abstraction layer - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/rsa.c b/iotkit-embedded/external_libs/mbedtls/library/rsa.c similarity index 98% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/rsa.c rename to iotkit-embedded/external_libs/mbedtls/library/rsa.c index 122bc13..0c983d6 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/rsa.c +++ b/iotkit-embedded/external_libs/mbedtls/library/rsa.c @@ -1,23 +1,9 @@ /* - * The RSA public-key cryptosystem - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The following sources were referenced in the design of this implementation * of the RSA algorithm: diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/sha1.c b/iotkit-embedded/external_libs/mbedtls/library/sha1.c similarity index 93% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/sha1.c rename to iotkit-embedded/external_libs/mbedtls/library/sha1.c index 2ccf2a2..f6146f4 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/sha1.c +++ b/iotkit-embedded/external_libs/mbedtls/library/sha1.c @@ -1,23 +1,9 @@ /* - * FIPS-180-1 compliant SHA-1 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The SHA-1 standard was published by NIST in 1993. * @@ -41,7 +27,9 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/sha256.c b/iotkit-embedded/external_libs/mbedtls/library/sha256.c similarity index 93% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/sha256.c rename to iotkit-embedded/external_libs/mbedtls/library/sha256.c index ad25d38..7c8e139 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/sha256.c +++ b/iotkit-embedded/external_libs/mbedtls/library/sha256.c @@ -1,23 +1,9 @@ /* - * FIPS-180-2 compliant SHA-256 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. * @@ -42,7 +28,9 @@ #else #include #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info #define mbedtls_calloc calloc #define mbedtls_free free #endif /* MBEDTLS_PLATFORM_C */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_ciphersuites.c b/iotkit-embedded/external_libs/mbedtls/library/ssl_ciphersuites.c similarity index 99% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_ciphersuites.c rename to iotkit-embedded/external_libs/mbedtls/library/ssl_ciphersuites.c index a762bf7..1648ca7 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_ciphersuites.c +++ b/iotkit-embedded/external_libs/mbedtls/library/ssl_ciphersuites.c @@ -1,26 +1,10 @@ -/** - * \file ssl_ciphersuites.c - * - * \brief SSL ciphersuites for mbed TLS - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_cli.c b/iotkit-embedded/external_libs/mbedtls/library/ssl_cli.c similarity index 99% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_cli.c rename to iotkit-embedded/external_libs/mbedtls/library/ssl_cli.c index 223823b..e341502 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_cli.c +++ b/iotkit-embedded/external_libs/mbedtls/library/ssl_cli.c @@ -1,24 +1,10 @@ /* - * SSLv3/TLSv1 client-side functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_cookie.c b/iotkit-embedded/external_libs/mbedtls/library/ssl_cookie.c similarity index 89% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_cookie.c rename to iotkit-embedded/external_libs/mbedtls/library/ssl_cookie.c index caf1199..ee1b9f9 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_cookie.c +++ b/iotkit-embedded/external_libs/mbedtls/library/ssl_cookie.c @@ -1,23 +1,9 @@ /* - * DTLS cookie callbacks implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * These session callbacks use a simple chained list * to store and retrieve the session information. diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_tls.c b/iotkit-embedded/external_libs/mbedtls/library/ssl_tls.c similarity index 99% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_tls.c rename to iotkit-embedded/external_libs/mbedtls/library/ssl_tls.c index 00a57ff..38d967a 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/ssl_tls.c +++ b/iotkit-embedded/external_libs/mbedtls/library/ssl_tls.c @@ -1,23 +1,9 @@ /* - * SSLv3/TLSv1 shared functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The SSL 3.0 specification was drafted by Netscape in 1996, * and became an IETF standard in 1999. diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/timing.c b/iotkit-embedded/external_libs/mbedtls/library/timing.c similarity index 94% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/timing.c rename to iotkit-embedded/external_libs/mbedtls/library/timing.c index 2c7cfe0..0a976b8 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/timing.c +++ b/iotkit-embedded/external_libs/mbedtls/library/timing.c @@ -1,24 +1,10 @@ /* - * Portable interface to the CPU cycle counter - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -29,7 +15,8 @@ #include "mbedtls/platform.h" #else #include -#define mbedtls_printf printf +#include "mbedtls/debug.h" +#define mbedtls_printf tls_info #endif #if defined(MBEDTLS_TIMING_C) @@ -232,6 +219,14 @@ static struct timeval tv_init; #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif +#ifndef _TIMEZONE_DEFINED +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; +#endif + int mbedtls_gettimeofday(struct timeval *tv, struct timezone *tz) { unsigned __int64 tmpres = 0; diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/x509.c b/iotkit-embedded/external_libs/mbedtls/library/x509.c similarity index 97% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/x509.c rename to iotkit-embedded/external_libs/mbedtls/library/x509.c index e438770..62ffca5 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/x509.c +++ b/iotkit-embedded/external_libs/mbedtls/library/x509.c @@ -1,23 +1,9 @@ /* - * X.509 common functions for parsing and verification - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The ITU-T X.509 standard defines a certificate format for PKI. * diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/x509_crt.c b/iotkit-embedded/external_libs/mbedtls/library/x509_crt.c similarity index 98% rename from iotkit-embedded/src/tls/mbedtls-in-iotkit/library/x509_crt.c rename to iotkit-embedded/external_libs/mbedtls/library/x509_crt.c index 234f145..f21c988 100644 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/x509_crt.c +++ b/iotkit-embedded/external_libs/mbedtls/library/x509_crt.c @@ -1,23 +1,9 @@ /* - * X.509 certificate parsing and verification - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + + /* * The ITU-T X.509 standard defines a certificate format for PKI. * @@ -711,7 +697,7 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * memcpy( p, buf, crt->raw.len ); - // Direct pointers to the new buffer + // Direct pointers to the new buffer p += crt->raw.len - len; end = crt_end = p + len; diff --git a/iotkit-embedded/external_libs/nghttp2/iot.mk b/iotkit-embedded/external_libs/nghttp2/iot.mk new file mode 100644 index 0000000..3b18482 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/iot.mk @@ -0,0 +1,2 @@ +LIBA_TARGET := libiot_nghttp2.a +HDR_REFS += src/infra diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2.h b/iotkit-embedded/external_libs/nghttp2/nghttp2.h new file mode 100644 index 0000000..8b96d25 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_buf.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_buf.c new file mode 100644 index 0000000..b40d567 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_buf.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_buf.h new file mode 100644 index 0000000..7e33a52 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_callbacks.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_callbacks.c new file mode 100644 index 0000000..a2f7e3f --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_callbacks.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_callbacks.h new file mode 100644 index 0000000..542df19 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_debug.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_debug.c new file mode 100644 index 0000000..6533f98 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_debug.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_debug.h new file mode 100644 index 0000000..6fed6ea --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_frame.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_frame.c new file mode 100644 index 0000000..76c919e --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_frame.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_frame.h new file mode 100644 index 0000000..07aeb8b --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_hd.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_hd.c new file mode 100644 index 0000000..d7e80a2 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_hd.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_hd.h new file mode 100644 index 0000000..584dad3 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_hd_huffman.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_hd_huffman.c new file mode 100644 index 0000000..661668d --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_hd_huffman.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_hd_huffman.h new file mode 100644 index 0000000..979f6b1 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_hd_huffman_data.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_hd_huffman_data.c new file mode 100644 index 0000000..085b2e9 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_helper.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_helper.c new file mode 100644 index 0000000..8d80eb9 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_helper.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_helper.h new file mode 100644 index 0000000..be85fd2 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_http.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_http.c new file mode 100644 index 0000000..49caa10 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_http.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_http.h new file mode 100644 index 0000000..bde7023 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_int.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_int.h new file mode 100644 index 0000000..56c071a --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_map.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_map.c new file mode 100644 index 0000000..9de8299 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_map.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_map.h new file mode 100644 index 0000000..48096a2 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_mem.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_mem.c new file mode 100644 index 0000000..5a66973 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_mem.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_mem.h new file mode 100644 index 0000000..be33ac5 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_net.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_net.c new file mode 100644 index 0000000..c71af3e --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_net.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_net.h new file mode 100644 index 0000000..b1adc40 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_npn.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_npn.c new file mode 100644 index 0000000..0527ec9 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_npn.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_npn.h new file mode 100644 index 0000000..c9fe50c --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_option.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_option.c new file mode 100644 index 0000000..1d62f5b --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_option.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_option.h new file mode 100644 index 0000000..16b64e0 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_outbound_item.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_outbound_item.c new file mode 100644 index 0000000..3d35983 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_outbound_item.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_outbound_item.h new file mode 100644 index 0000000..3391835 --- /dev/null +++ b/iotkit-embedded/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/iotkit-embedded/external_libs/nghttp2/nghttp2_pq.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_pq.c new file mode 100644 index 0000000..79aa156 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_pq.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "nghttp2_pq.h" + +#include +#include + +#include "nghttp2_helper.h" + +int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) { + pq->mem = mem; + pq->capacity = 0; + pq->q = NULL; + pq->length = 0; + pq->less = less; + return 0; +} + +void nghttp2_pq_free(nghttp2_pq *pq) { + nghttp2_mem_free(pq->mem, pq->q); + pq->q = NULL; +} + +static void swap(nghttp2_pq *pq, size_t i, size_t j) { + nghttp2_pq_entry *a = pq->q[i]; + nghttp2_pq_entry *b = pq->q[j]; + + pq->q[i] = b; + b->index = i; + pq->q[j] = a; + a->index = j; +} + +static void bubble_up(nghttp2_pq *pq, size_t index) { + size_t parent; + while (index != 0) { + parent = (index - 1) / 2; + if (!pq->less(pq->q[index], pq->q[parent])) { + return; + } + swap(pq, parent, index); + index = parent; + } +} + +int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item) { + if (pq->capacity <= pq->length) { + void *nq; + size_t ncapacity; + + ncapacity = nghttp2_max(4, (pq->capacity * 2)); + + nq = nghttp2_mem_realloc(pq->mem, pq->q, + ncapacity * sizeof(nghttp2_pq_entry *)); + if (nq == NULL) { + return NGHTTP2_ERR_NOMEM; + } + pq->capacity = ncapacity; + pq->q = nq; + } + pq->q[pq->length] = item; + item->index = pq->length; + ++pq->length; + bubble_up(pq, pq->length - 1); + return 0; +} + +nghttp2_pq_entry *nghttp2_pq_top(nghttp2_pq *pq) { + if (pq->length == 0) { + return NULL; + } else { + return pq->q[0]; + } +} + +static void bubble_down(nghttp2_pq *pq, size_t index) { + size_t i, j, minindex; + for (;;) { + j = index * 2 + 1; + minindex = index; + for (i = 0; i < 2; ++i, ++j) { + if (j >= pq->length) { + break; + } + if (pq->less(pq->q[j], pq->q[minindex])) { + minindex = j; + } + } + if (minindex == index) { + return; + } + swap(pq, index, minindex); + index = minindex; + } +} + +void nghttp2_pq_pop(nghttp2_pq *pq) { + if (pq->length > 0) { + pq->q[0] = pq->q[pq->length - 1]; + pq->q[0]->index = 0; + --pq->length; + bubble_down(pq, 0); + } +} + +void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item) { + assert(pq->q[item->index] == item); + + if (item->index == 0) { + nghttp2_pq_pop(pq); + return; + } + + if (item->index == pq->length - 1) { + --pq->length; + return; + } + + pq->q[item->index] = pq->q[pq->length - 1]; + pq->q[item->index]->index = item->index; + --pq->length; + + if (pq->less(item, pq->q[item->index])) { + bubble_down(pq, item->index); + } else { + bubble_up(pq, item->index); + } +} + +int nghttp2_pq_empty(nghttp2_pq *pq) { return pq->length == 0; } + +size_t nghttp2_pq_size(nghttp2_pq *pq) { return pq->length; } + +void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg) { + size_t i; + int rv = 0; + if (pq->length == 0) { + return; + } + for (i = 0; i < pq->length; ++i) { + rv |= (*fun)(pq->q[i], arg); + } + if (rv) { + for (i = pq->length; i > 0; --i) { + bubble_down(pq, i - 1); + } + } +} + +int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg) { + size_t i; + + if (pq->length == 0) { + return 0; + } + for (i = 0; i < pq->length; ++i) { + if ((*fun)(pq->q[i], arg)) { + return 1; + } + } + return 0; +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_pq.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_pq.h new file mode 100644 index 0000000..a527db1 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_pq.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_PQ_H +#define NGHTTP2_PQ_H + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" +#include "nghttp2_int.h" +#include "nghttp2_mem.h" + +/* Implementation of priority queue */ + +typedef struct { + size_t index; +} nghttp2_pq_entry; + +typedef struct { + /* The pointer to the pointer to the item stored */ + nghttp2_pq_entry **q; + /* Memory allocator */ + nghttp2_mem *mem; + /* The number of items stored */ + size_t length; + /* The maximum number of items this pq can store. This is + automatically extended when length is reached to this value. */ + size_t capacity; + /* The less function between items */ + nghttp2_less less; +} nghttp2_pq; + +/* + * Initializes priority queue |pq| with compare function |cmp|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem); + +/* + * Deallocates any resources allocated for |pq|. The stored items are + * not freed by this function. + */ +void nghttp2_pq_free(nghttp2_pq *pq); + +/* + * Adds |item| to the priority queue |pq|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item); + +/* + * Returns item at the top of the queue |pq|. If the queue is empty, + * this function returns NULL. + */ +nghttp2_pq_entry *nghttp2_pq_top(nghttp2_pq *pq); + +/* + * Pops item at the top of the queue |pq|. The popped item is not + * freed by this function. + */ +void nghttp2_pq_pop(nghttp2_pq *pq); + +/* + * Returns nonzero if the queue |pq| is empty. + */ +int nghttp2_pq_empty(nghttp2_pq *pq); + +/* + * Returns the number of items in the queue |pq|. + */ +size_t nghttp2_pq_size(nghttp2_pq *pq); + +typedef int (*nghttp2_pq_item_cb)(nghttp2_pq_entry *item, void *arg); + +/* + * Updates each item in |pq| using function |fun| and re-construct + * priority queue. The |fun| must return non-zero if it modifies the + * item in a way that it affects ordering in the priority queue. The + * |arg| is passed to the 2nd parameter of |fun|. + */ +void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg); + +/* + * Applys |fun| to each item in |pq|. The |arg| is passed as arg + * parameter to callback function. This function must not change the + * ordering key. If the return value from callback is nonzero, this + * function returns 1 immediately without iterating remaining items. + * Otherwise this function returns 0. + */ +int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg); + +/* + * Removes |item| from priority queue. + */ +void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item); + +#endif /* NGHTTP2_PQ_H */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_priority_spec.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_priority_spec.c new file mode 100644 index 0000000..b3d64e6 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_priority_spec.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "nghttp2_priority_spec.h" + +void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, + int32_t stream_id, int32_t weight, + int exclusive) { + pri_spec->stream_id = stream_id; + pri_spec->weight = weight; + pri_spec->exclusive = exclusive != 0; +} + +void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) { + pri_spec->stream_id = 0; + pri_spec->weight = NGHTTP2_DEFAULT_WEIGHT; + pri_spec->exclusive = 0; +} + +int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) { + return pri_spec->stream_id == 0 && + pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 0; +} + +void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec) { + if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) { + pri_spec->weight = NGHTTP2_MIN_WEIGHT; + } else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) { + pri_spec->weight = NGHTTP2_MAX_WEIGHT; + } +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_priority_spec.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_priority_spec.h new file mode 100644 index 0000000..d5f9956 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_priority_spec.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_PRIORITY_SPEC_H +#define NGHTTP2_PRIORITY_SPEC_H + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" + +/* + * This function normalizes pri_spec->weight if it is out of range. + * If pri_spec->weight is less than NGHTTP2_MIN_WEIGHT, it is set to + * NGHTTP2_MIN_WEIGHT. If pri_spec->weight is larger than + * NGHTTP2_MAX_WEIGHT, it is set to NGHTTP2_MAX_WEIGHT. + */ +void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec); + +#endif /* NGHTTP2_PRIORITY_SPEC_H */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_queue.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_queue.c new file mode 100644 index 0000000..4c45dfe --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_queue.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include "nghttp2_queue.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_QUEUE_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "nghttp2.queue") +#define NGHTTP2_QUEUE_FREE(ptr) LITE_free(ptr) +#else +#define NGHTTP2_QUEUE_MALLOC(size) HAL_Malloc(size) +#define NGHTTP2_QUEUE_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;} +#endif + +void nghttp2_queue_init(nghttp2_queue *queue) { + queue->front = queue->back = NULL; +} + +void nghttp2_queue_free(nghttp2_queue *queue) { + if (!queue) { + return; + } else { + nghttp2_queue_cell *p = queue->front; + while (p) { + nghttp2_queue_cell *next = p->next; + NGHTTP2_QUEUE_FREE(p); + p = next; + } + } +} + +int nghttp2_queue_push(nghttp2_queue *queue, void *data) { + nghttp2_queue_cell *new_cell = + (nghttp2_queue_cell *)NGHTTP2_QUEUE_MALLOC(sizeof(nghttp2_queue_cell)); + if (!new_cell) { + return NGHTTP2_ERR_NOMEM; + } + new_cell->data = data; + new_cell->next = NULL; + if (queue->back) { + queue->back->next = new_cell; + queue->back = new_cell; + + } else { + queue->front = queue->back = new_cell; + } + return 0; +} + +void nghttp2_queue_pop(nghttp2_queue *queue) { + nghttp2_queue_cell *front = queue->front; + assert(front); + queue->front = front->next; + if (front == queue->back) { + queue->back = NULL; + } + NGHTTP2_QUEUE_FREE(front); +} + +void *nghttp2_queue_front(nghttp2_queue *queue) { + assert(queue->front); + return queue->front->data; +} + +void *nghttp2_queue_back(nghttp2_queue *queue) { + assert(queue->back); + return queue->back->data; +} + +int nghttp2_queue_empty(nghttp2_queue *queue) { return queue->front == NULL; } diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_queue.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_queue.h new file mode 100644 index 0000000..3ffdc14 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_queue.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_QUEUE_H +#define NGHTTP2_QUEUE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" + +typedef struct nghttp2_queue_cell { + void *data; + struct nghttp2_queue_cell *next; +} nghttp2_queue_cell; + +typedef struct { + nghttp2_queue_cell *front, *back; +} nghttp2_queue; + +void nghttp2_queue_init(nghttp2_queue *queue); +void nghttp2_queue_free(nghttp2_queue *queue); +int nghttp2_queue_push(nghttp2_queue *queue, void *data); +void nghttp2_queue_pop(nghttp2_queue *queue); +void *nghttp2_queue_front(nghttp2_queue *queue); +void *nghttp2_queue_back(nghttp2_queue *queue); +int nghttp2_queue_empty(nghttp2_queue *queue); + +#endif /* NGHTTP2_QUEUE_H */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_rcbuf.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_rcbuf.c new file mode 100644 index 0000000..0fc440e --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_rcbuf.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "nghttp2_rcbuf.h" + +#include +#include + +#include "nghttp2_mem.h" +#include "nghttp2_helper.h" + +int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size, + nghttp2_mem *mem) { + uint8_t *p; + + p = nghttp2_mem_malloc(mem, sizeof(nghttp2_rcbuf) + size); + if (p == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + *rcbuf_ptr = (void *)p; + + (*rcbuf_ptr)->mem_user_data = mem->mem_user_data; + (*rcbuf_ptr)->free = mem->free; + (*rcbuf_ptr)->base = p + sizeof(nghttp2_rcbuf); + (*rcbuf_ptr)->len = size; + (*rcbuf_ptr)->ref = 1; + + return 0; +} + +int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src, + size_t srclen, nghttp2_mem *mem) { + int rv; + + rv = nghttp2_rcbuf_new(rcbuf_ptr, srclen + 1, mem); + if (rv != 0) { + return rv; + } + + (*rcbuf_ptr)->len = srclen; + *nghttp2_cpymem((*rcbuf_ptr)->base, src, srclen) = '\0'; + + return 0; +} + +/* + * Frees |rcbuf| itself, regardless of its reference cout. + */ +void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf) { + nghttp2_mem_free2(rcbuf->free, rcbuf, rcbuf->mem_user_data); +} + +void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf) { + if (rcbuf->ref == -1) { + return; + } + + ++rcbuf->ref; +} + +void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf) { + if (rcbuf == NULL || rcbuf->ref == -1) { + return; + } + + assert(rcbuf->ref > 0); + + if (--rcbuf->ref == 0) { + nghttp2_rcbuf_del(rcbuf); + } +} + +nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) { + nghttp2_vec res = {rcbuf->base, rcbuf->len}; + return res; +} + +int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf) { + return rcbuf->ref == -1; +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_rcbuf.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_rcbuf.h new file mode 100644 index 0000000..edb1c59 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_rcbuf.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_RCBUF_H +#define NGHTTP2_RCBUF_H + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" + +struct nghttp2_rcbuf { + /* custom memory allocator belongs to the mem parameter when + creating this object. */ + void *mem_user_data; + nghttp2_free free; + /* The pointer to the underlying buffer */ + uint8_t *base; + /* Size of buffer pointed by |base|. */ + size_t len; + /* Reference count */ + int32_t ref; +}; + +/* + * Allocates nghttp2_rcbuf object with |size| as initial buffer size. + * When the function succeeds, the reference count becomes 1. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM: + * Out of memory. + */ +int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size, nghttp2_mem *mem); + +/* + * Like nghttp2_rcbuf_new(), but initializes the buffer with |src| of + * length |srclen|. This function allocates additional byte at the + * end and puts '\0' into it, so that the resulting buffer could be + * used as NULL-terminated string. Still (*rcbuf_ptr)->len equals to + * |srclen|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM: + * Out of memory. + */ +int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src, + size_t srclen, nghttp2_mem *mem); + +/* + * Frees |rcbuf| itself, regardless of its reference cout. + */ +void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf); + +#endif /* NGHTTP2_RCBUF_H */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_session.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_session.c new file mode 100644 index 0000000..6299b0f --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_session.c @@ -0,0 +1,7504 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "nghttp2_session.h" + +#include +#include +#include +#include +#include + +#include "nghttp2_helper.h" +#include "nghttp2_net.h" +#include "nghttp2_priority_spec.h" +#include "nghttp2_option.h" +#include "nghttp2_http.h" +#include "nghttp2_pq.h" +#include "nghttp2_debug.h" + +extern int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap); + +/* + * Returns non-zero if the number of outgoing opened streams is larger + * than or equal to + * remote_settings.max_concurrent_streams. + */ +static int +session_is_outgoing_concurrent_streams_max(nghttp2_session *session) { + return session->remote_settings.max_concurrent_streams <= + session->num_outgoing_streams; +} + +/* + * Returns non-zero if the number of incoming opened streams is larger + * than or equal to + * local_settings.max_concurrent_streams. + */ +static int +session_is_incoming_concurrent_streams_max(nghttp2_session *session) { + return session->local_settings.max_concurrent_streams <= + session->num_incoming_streams; +} + +/* + * Returns non-zero if the number of incoming opened streams is larger + * than or equal to + * session->pending_local_max_concurrent_stream. + */ +static int +session_is_incoming_concurrent_streams_pending_max(nghttp2_session *session) { + return session->pending_local_max_concurrent_stream <= + session->num_incoming_streams; +} + +/* + * Returns non-zero if |lib_error| is non-fatal error. + */ +static int is_non_fatal(int lib_error_code) { + return lib_error_code < 0 && lib_error_code > NGHTTP2_ERR_FATAL; +} + +int nghttp2_is_fatal(int lib_error_code) { + return lib_error_code < NGHTTP2_ERR_FATAL; +} + +static int session_enforce_http_messaging(nghttp2_session *session) { + return (session->opt_flags & NGHTTP2_OPTMASK_NO_HTTP_MESSAGING) == 0; +} + +/* + * Returns nonzero if |frame| is trailer headers. + */ +static int session_trailer_headers(nghttp2_session *session, + nghttp2_stream *stream, + nghttp2_frame *frame) { + if (!stream || frame->hd.type != NGHTTP2_HEADERS) { + return 0; + } + if (session->server) { + return frame->headers.cat == NGHTTP2_HCAT_HEADERS; + } + + return frame->headers.cat == NGHTTP2_HCAT_HEADERS && + (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) == 0; +} + +/* Returns nonzero if the |stream| is in reserved(remote) state */ +static int state_reserved_remote(nghttp2_session *session, + nghttp2_stream *stream) { + return stream->state == NGHTTP2_STREAM_RESERVED && + !nghttp2_session_is_my_stream_id(session, stream->stream_id); +} + +/* Returns nonzero if the |stream| is in reserved(local) state */ +static int state_reserved_local(nghttp2_session *session, + nghttp2_stream *stream) { + return stream->state == NGHTTP2_STREAM_RESERVED && + nghttp2_session_is_my_stream_id(session, stream->stream_id); +} + +/* + * Checks whether received stream_id is valid. This function returns + * 1 if it succeeds, or 0. + */ +static int session_is_new_peer_stream_id(nghttp2_session *session, + int32_t stream_id) { + return stream_id != 0 && + !nghttp2_session_is_my_stream_id(session, stream_id) && + session->last_recv_stream_id < stream_id; +} + +static int session_detect_idle_stream(nghttp2_session *session, + int32_t stream_id) { + /* Assume that stream object with stream_id does not exist */ + if (nghttp2_session_is_my_stream_id(session, stream_id)) { + if (session->last_sent_stream_id < stream_id) { + return 1; + } + return 0; + } + if (session_is_new_peer_stream_id(session, stream_id)) { + return 1; + } + return 0; +} + +static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) { + return (ext_types[type / 8] & (1 << (type & 0x7))) > 0; +} + +static int session_call_error_callback(nghttp2_session *session, + int lib_error_code, const char *fmt, + ...) { + size_t bufsize; + va_list ap; + char *buf; + int rv; + nghttp2_mem *mem; + + if (!session->callbacks.error_callback && + !session->callbacks.error_callback2) { + return 0; + } + + mem = &session->mem; + + va_start(ap, fmt); + rv = HAL_Vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + if (rv < 0) { + return NGHTTP2_ERR_NOMEM; + } + + bufsize = (size_t)(rv + 1); + + buf = nghttp2_mem_malloc(mem, bufsize); + if (buf == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + va_start(ap, fmt); + rv = HAL_Vsnprintf(buf, bufsize, fmt, ap); + va_end(ap); + + if (rv < 0) { + nghttp2_mem_free(mem, buf); + /* vsnprintf may return error because of various things we can + imagine, but typically we don't want to drop session just for + debug callback. */ + DEBUGF("error_callback: vsnprintf failed. The template was %s\n", fmt); + return 0; + } + + if (session->callbacks.error_callback2) { + rv = session->callbacks.error_callback2(session, lib_error_code, buf, + (size_t)rv, session->user_data); + } else { + rv = session->callbacks.error_callback(session, buf, (size_t)rv, + session->user_data); + } + + nghttp2_mem_free(mem, buf); + + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} + +static int session_terminate_session(nghttp2_session *session, + int32_t last_stream_id, + uint32_t error_code, const char *reason) { + int rv; + const uint8_t *debug_data; + size_t debug_datalen; + + if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) { + return 0; + } + + if (reason == NULL) { + debug_data = NULL; + debug_datalen = 0; + } else { + debug_data = (const uint8_t *)reason; + debug_datalen = strlen(reason); + } + + rv = nghttp2_session_add_goaway(session, last_stream_id, error_code, + debug_data, debug_datalen, + NGHTTP2_GOAWAY_AUX_TERM_ON_SEND); + + if (rv != 0) { + return rv; + } + + session->goaway_flags |= NGHTTP2_GOAWAY_TERM_ON_SEND; + + return 0; +} + +int nghttp2_session_terminate_session(nghttp2_session *session, + uint32_t error_code) { + return session_terminate_session(session, session->last_proc_stream_id, + error_code, NULL); +} + +int nghttp2_session_terminate_session2(nghttp2_session *session, + int32_t last_stream_id, + uint32_t error_code) { + return session_terminate_session(session, last_stream_id, error_code, NULL); +} + +int nghttp2_session_terminate_session_with_reason(nghttp2_session *session, + uint32_t error_code, + const char *reason) { + return session_terminate_session(session, session->last_proc_stream_id, + error_code, reason); +} + +int nghttp2_session_is_my_stream_id(nghttp2_session *session, + int32_t stream_id) { + int rem; + if (stream_id == 0) { + return 0; + } + rem = stream_id & 0x1; + if (session->server) { + return rem == 0; + } + return rem == 1; +} + +nghttp2_stream *nghttp2_session_get_stream(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + + stream = (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id); + + if (stream == NULL || (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) || + stream->state == NGHTTP2_STREAM_IDLE) { + return NULL; + } + + return stream; +} + +nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session, + int32_t stream_id) { + return (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id); +} + +static void session_inbound_frame_reset(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_mem *mem = &session->mem; + /* A bit risky code, since if this function is called from + nghttp2_session_new(), we rely on the fact that + iframe->frame.hd.type is 0, so that no free is performed. */ + switch (iframe->frame.hd.type) { + case NGHTTP2_DATA: + break; + case NGHTTP2_HEADERS: + nghttp2_frame_headers_free(&iframe->frame.headers, mem); + break; + case NGHTTP2_PRIORITY: + nghttp2_frame_priority_free(&iframe->frame.priority); + break; + case NGHTTP2_RST_STREAM: + nghttp2_frame_rst_stream_free(&iframe->frame.rst_stream); + break; + case NGHTTP2_SETTINGS: + nghttp2_frame_settings_free(&iframe->frame.settings, mem); + + nghttp2_mem_free(mem, iframe->iv); + + iframe->iv = NULL; + iframe->niv = 0; + iframe->max_niv = 0; + + break; + case NGHTTP2_PUSH_PROMISE: + nghttp2_frame_push_promise_free(&iframe->frame.push_promise, mem); + break; + case NGHTTP2_PING: + nghttp2_frame_ping_free(&iframe->frame.ping); + break; + case NGHTTP2_GOAWAY: + nghttp2_frame_goaway_free(&iframe->frame.goaway, mem); + break; + case NGHTTP2_WINDOW_UPDATE: + nghttp2_frame_window_update_free(&iframe->frame.window_update); + break; + default: + /* extension frame */ + if (check_ext_type_set(session->user_recv_ext_types, + iframe->frame.hd.type)) { + nghttp2_frame_extension_free(&iframe->frame.ext); + } else { + switch (iframe->frame.hd.type) { + case NGHTTP2_ALTSVC: + if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == 0) { + break; + } + nghttp2_frame_altsvc_free(&iframe->frame.ext, mem); + break; + } + } + + break; + } + + memset(&iframe->frame, 0, sizeof(nghttp2_frame)); + memset(&iframe->ext_frame_payload, 0, sizeof(nghttp2_ext_frame_payload)); + + iframe->state = NGHTTP2_IB_READ_HEAD; + + nghttp2_buf_wrap_init(&iframe->sbuf, iframe->raw_sbuf, + sizeof(iframe->raw_sbuf)); + iframe->sbuf.mark += NGHTTP2_FRAME_HDLEN; + + nghttp2_buf_free(&iframe->lbuf, mem); + nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0); + + iframe->raw_lbuf = NULL; + + iframe->payloadleft = 0; + iframe->padlen = 0; +} + +static void init_settings(nghttp2_settings_storage *settings) { + settings->header_table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; + settings->enable_push = 1; + settings->max_concurrent_streams = NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS; + settings->initial_window_size = NGHTTP2_INITIAL_WINDOW_SIZE; + settings->max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN; + settings->max_header_list_size = UINT32_MAX; +} + +static void active_outbound_item_reset(nghttp2_active_outbound_item *aob, + nghttp2_mem *mem) { + DEBUGF("send: reset nghttp2_active_outbound_item\n"); + DEBUGF("send: aob->item = %p\n", aob->item); + nghttp2_outbound_item_free(aob->item, mem); + nghttp2_mem_free(mem, aob->item); + aob->item = NULL; + nghttp2_bufs_reset(&aob->framebufs); + aob->state = NGHTTP2_OB_POP_ITEM; +} + +int nghttp2_enable_strict_preface = 1; + +static int session_new(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, int server, + const nghttp2_option *option, nghttp2_mem *mem) { + int rv; + size_t nbuffer; + size_t max_deflate_dynamic_table_size = + NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE; + + if (mem == NULL) { + mem = nghttp2_mem_default(); + } + + *session_ptr = nghttp2_mem_calloc(mem, 1, sizeof(nghttp2_session)); + if (*session_ptr == NULL) { + rv = NGHTTP2_ERR_NOMEM; + goto fail_session; + } + + (*session_ptr)->mem = *mem; + mem = &(*session_ptr)->mem; + + /* next_stream_id is initialized in either + nghttp2_session_client_new2 or nghttp2_session_server_new2 */ + + nghttp2_stream_init(&(*session_ptr)->root, 0, NGHTTP2_STREAM_FLAG_NONE, + NGHTTP2_STREAM_IDLE, NGHTTP2_DEFAULT_WEIGHT, 0, 0, NULL, + mem); + + (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; + (*session_ptr)->recv_window_size = 0; + (*session_ptr)->consumed_size = 0; + (*session_ptr)->recv_reduction = 0; + (*session_ptr)->local_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; + + (*session_ptr)->goaway_flags = NGHTTP2_GOAWAY_NONE; + (*session_ptr)->local_last_stream_id = (1u << 31) - 1; + (*session_ptr)->remote_last_stream_id = (1u << 31) - 1; + + (*session_ptr)->pending_local_max_concurrent_stream = + NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS; + (*session_ptr)->pending_enable_push = 1; + + if (server) { + (*session_ptr)->server = 1; + } + + init_settings(&(*session_ptr)->remote_settings); + init_settings(&(*session_ptr)->local_settings); + + (*session_ptr)->max_incoming_reserved_streams = + NGHTTP2_MAX_INCOMING_RESERVED_STREAMS; + + /* Limit max outgoing concurrent streams to sensible value */ + (*session_ptr)->remote_settings.max_concurrent_streams = 100; + + (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN; + + if (option) { + if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) && + option->no_auto_window_update) { + + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE; + } + + if (option->opt_set_mask & NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS) { + + (*session_ptr)->remote_settings.max_concurrent_streams = + option->peer_max_concurrent_streams; + } + + if (option->opt_set_mask & NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS) { + + (*session_ptr)->max_incoming_reserved_streams = + option->max_reserved_remote_streams; + } + + if ((option->opt_set_mask & NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC) && + option->no_recv_client_magic) { + + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC; + } + + if ((option->opt_set_mask & NGHTTP2_OPT_NO_HTTP_MESSAGING) && + option->no_http_messaging) { + + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING; + } + + if (option->opt_set_mask & NGHTTP2_OPT_USER_RECV_EXT_TYPES) { + memcpy((*session_ptr)->user_recv_ext_types, option->user_recv_ext_types, + sizeof((*session_ptr)->user_recv_ext_types)); + } + + if (option->opt_set_mask & NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES) { + (*session_ptr)->builtin_recv_ext_types = option->builtin_recv_ext_types; + } + + if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_PING_ACK) && + option->no_auto_ping_ack) { + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_PING_ACK; + } + + if (option->opt_set_mask & NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH) { + (*session_ptr)->max_send_header_block_length = + option->max_send_header_block_length; + } + + if (option->opt_set_mask & NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE) { + max_deflate_dynamic_table_size = option->max_deflate_dynamic_table_size; + } + + if ((option->opt_set_mask & NGHTTP2_OPT_NO_CLOSED_STREAMS) && + option->no_closed_streams) { + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_CLOSED_STREAMS; + } + } + + rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater, + max_deflate_dynamic_table_size, mem); + if (rv != 0) { + goto fail_hd_deflater; + } + rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, mem); + if (rv != 0) { + goto fail_hd_inflater; + } + rv = nghttp2_map_init(&(*session_ptr)->streams, mem); + if (rv != 0) { + goto fail_map; + } + + nbuffer = ((*session_ptr)->max_send_header_block_length + + NGHTTP2_FRAMEBUF_CHUNKLEN - 1) / + NGHTTP2_FRAMEBUF_CHUNKLEN; + + if (nbuffer == 0) { + nbuffer = 1; + } + + /* 1 for Pad Field. */ + rv = nghttp2_bufs_init3(&(*session_ptr)->aob.framebufs, + NGHTTP2_FRAMEBUF_CHUNKLEN, nbuffer, 1, + NGHTTP2_FRAME_HDLEN + 1, mem); + if (rv != 0) { + goto fail_aob_framebuf; + } + + active_outbound_item_reset(&(*session_ptr)->aob, mem); + + (*session_ptr)->callbacks = *callbacks; + (*session_ptr)->user_data = user_data; + + session_inbound_frame_reset(*session_ptr); + + if (nghttp2_enable_strict_preface) { + nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe; + + if (server && ((*session_ptr)->opt_flags & + NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == 0) { + iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC; + iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN; + } else { + iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS; + } + + if (!server) { + (*session_ptr)->aob.state = NGHTTP2_OB_SEND_CLIENT_MAGIC; + nghttp2_bufs_add(&(*session_ptr)->aob.framebufs, NGHTTP2_CLIENT_MAGIC, + NGHTTP2_CLIENT_MAGIC_LEN); + } + } + + return 0; + +fail_aob_framebuf: + nghttp2_map_free(&(*session_ptr)->streams); +fail_map: + nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater); +fail_hd_inflater: + nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater); +fail_hd_deflater: + nghttp2_mem_free(mem, *session_ptr); +fail_session: + return rv; +} + +int nghttp2_session_client_new(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data) { + return nghttp2_session_client_new3(session_ptr, callbacks, user_data, NULL, + NULL); +} + +int nghttp2_session_client_new2(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option) { + return nghttp2_session_client_new3(session_ptr, callbacks, user_data, option, + NULL); +} + +int nghttp2_session_client_new3(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option, + nghttp2_mem *mem) { + int rv; + nghttp2_session *session; + + rv = session_new(&session, callbacks, user_data, 0, option, mem); + + if (rv != 0) { + return rv; + } + /* IDs for use in client */ + session->next_stream_id = 1; + + *session_ptr = session; + + return 0; +} + +int nghttp2_session_server_new(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data) { + return nghttp2_session_server_new3(session_ptr, callbacks, user_data, NULL, + NULL); +} + +int nghttp2_session_server_new2(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option) { + return nghttp2_session_server_new3(session_ptr, callbacks, user_data, option, + NULL); +} + +int nghttp2_session_server_new3(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option, + nghttp2_mem *mem) { + int rv; + nghttp2_session *session; + + rv = session_new(&session, callbacks, user_data, 1, option, mem); + + if (rv != 0) { + return rv; + } + /* IDs for use in client */ + session->next_stream_id = 2; + + *session_ptr = session; + + return 0; +} + +static int free_streams(nghttp2_map_entry *entry, void *ptr) { + nghttp2_session *session; + nghttp2_stream *stream; + nghttp2_outbound_item *item; + nghttp2_mem *mem; + + session = (nghttp2_session *)ptr; + mem = &session->mem; + stream = (nghttp2_stream *)entry; + item = stream->item; + + if (item && !item->queued && item != session->aob.item) { + nghttp2_outbound_item_free(item, mem); + nghttp2_mem_free(mem, item); + } + + nghttp2_stream_free(stream); + nghttp2_mem_free(mem, stream); + + return 0; +} + +static void ob_q_free(nghttp2_outbound_queue *q, nghttp2_mem *mem) { + nghttp2_outbound_item *item, *next; + for (item = q->head; item;) { + next = item->qnext; + nghttp2_outbound_item_free(item, mem); + nghttp2_mem_free(mem, item); + item = next; + } +} + +static int inflight_settings_new(nghttp2_inflight_settings **settings_ptr, + const nghttp2_settings_entry *iv, size_t niv, + nghttp2_mem *mem) { + *settings_ptr = nghttp2_mem_malloc(mem, sizeof(nghttp2_inflight_settings)); + if (!*settings_ptr) { + return NGHTTP2_ERR_NOMEM; + } + + if (niv > 0) { + (*settings_ptr)->iv = nghttp2_frame_iv_copy(iv, niv, mem); + if (!(*settings_ptr)->iv) { + nghttp2_mem_free(mem, *settings_ptr); + return NGHTTP2_ERR_NOMEM; + } + } else { + (*settings_ptr)->iv = NULL; + } + + (*settings_ptr)->niv = niv; + (*settings_ptr)->next = NULL; + + return 0; +} + +static void inflight_settings_del(nghttp2_inflight_settings *settings, + nghttp2_mem *mem) { + if (!settings) { + return; + } + + nghttp2_mem_free(mem, settings->iv); + nghttp2_mem_free(mem, settings); +} + +void nghttp2_session_del(nghttp2_session *session) { + nghttp2_mem *mem; + nghttp2_inflight_settings *settings; + + if (session == NULL) { + return; + } + + mem = &session->mem; + + for (settings = session->inflight_settings_head; settings;) { + nghttp2_inflight_settings *next = settings->next; + inflight_settings_del(settings, mem); + settings = next; + } + + nghttp2_stream_free(&session->root); + + /* Have to free streams first, so that we can check + stream->item->queued */ + nghttp2_map_each_free(&session->streams, free_streams, session); + nghttp2_map_free(&session->streams); + + ob_q_free(&session->ob_urgent, mem); + ob_q_free(&session->ob_reg, mem); + ob_q_free(&session->ob_syn, mem); + + active_outbound_item_reset(&session->aob, mem); + session_inbound_frame_reset(session); + nghttp2_hd_deflate_free(&session->hd_deflater); + nghttp2_hd_inflate_free(&session->hd_inflater); + nghttp2_bufs_free(&session->aob.framebufs); + nghttp2_mem_free(mem, session); +} + +int nghttp2_session_reprioritize_stream( + nghttp2_session *session, nghttp2_stream *stream, + const nghttp2_priority_spec *pri_spec_in) { + int rv; + nghttp2_stream *dep_stream = NULL; + nghttp2_priority_spec pri_spec_default; + const nghttp2_priority_spec *pri_spec = pri_spec_in; + + assert(pri_spec->stream_id != stream->stream_id); + + if (!nghttp2_stream_in_dep_tree(stream)) { + return 0; + } + + if (pri_spec->stream_id != 0) { + dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); + + if (!dep_stream && + session_detect_idle_stream(session, pri_spec->stream_id)) { + + nghttp2_priority_spec_default_init(&pri_spec_default); + + dep_stream = nghttp2_session_open_stream( + session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_IDLE, NULL); + + if (dep_stream == NULL) { + return NGHTTP2_ERR_NOMEM; + } + } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { + nghttp2_priority_spec_default_init(&pri_spec_default); + pri_spec = &pri_spec_default; + } + } + + if (pri_spec->stream_id == 0) { + dep_stream = &session->root; + } else if (nghttp2_stream_dep_find_ancestor(dep_stream, stream)) { + DEBUGF("stream: cycle detected, dep_stream(%p)=%d stream(%p)=%d\n", + dep_stream, dep_stream->stream_id, stream, stream->stream_id); + + nghttp2_stream_dep_remove_subtree(dep_stream); + rv = nghttp2_stream_dep_add_subtree(stream->dep_prev, dep_stream); + if (rv != 0) { + return rv; + } + } + + assert(dep_stream); + + if (dep_stream == stream->dep_prev && !pri_spec->exclusive) { + /* This is minor optimization when just weight is changed. */ + nghttp2_stream_change_weight(stream, pri_spec->weight); + + return 0; + } + + nghttp2_stream_dep_remove_subtree(stream); + + /* We have to update weight after removing stream from tree */ + stream->weight = pri_spec->weight; + + if (pri_spec->exclusive) { + rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream); + } else { + rv = nghttp2_stream_dep_add_subtree(dep_stream, stream); + } + + if (rv != 0) { + return rv; + } + + return 0; +} + +int nghttp2_session_add_item(nghttp2_session *session, + nghttp2_outbound_item *item) { + /* TODO Return error if stream is not found for the frame requiring + stream presence. */ + int rv = 0; + nghttp2_stream *stream; + nghttp2_frame *frame; + + frame = &item->frame; + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + switch (frame->hd.type) { + case NGHTTP2_DATA: + if (!stream) { + return NGHTTP2_ERR_STREAM_CLOSED; + } + + if (stream->item) { + return NGHTTP2_ERR_DATA_EXIST; + } + + rv = nghttp2_stream_attach_item(stream, item); + + if (rv != 0) { + return rv; + } + + return 0; + case NGHTTP2_HEADERS: + /* We push request HEADERS and push response HEADERS to + dedicated queue because their transmission is affected by + SETTINGS_MAX_CONCURRENT_STREAMS */ + /* TODO If 2 HEADERS are submitted for reserved stream, then + both of them are queued into ob_syn, which is not + desirable. */ + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST || + (stream && stream->state == NGHTTP2_STREAM_RESERVED)) { + nghttp2_outbound_queue_push(&session->ob_syn, item); + item->queued = 1; + return 0; + ; + } + + nghttp2_outbound_queue_push(&session->ob_reg, item); + item->queued = 1; + return 0; + case NGHTTP2_SETTINGS: + case NGHTTP2_PING: + nghttp2_outbound_queue_push(&session->ob_urgent, item); + item->queued = 1; + return 0; + case NGHTTP2_RST_STREAM: + if (stream) { + stream->state = NGHTTP2_STREAM_CLOSING; + } + nghttp2_outbound_queue_push(&session->ob_reg, item); + item->queued = 1; + return 0; + case NGHTTP2_PUSH_PROMISE: { + nghttp2_headers_aux_data *aux_data; + nghttp2_priority_spec pri_spec; + + aux_data = &item->aux_data.headers; + + if (!stream) { + return NGHTTP2_ERR_STREAM_CLOSED; + } + + nghttp2_priority_spec_init(&pri_spec, stream->stream_id, + NGHTTP2_DEFAULT_WEIGHT, 0); + + if (!nghttp2_session_open_stream( + session, frame->push_promise.promised_stream_id, + NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_RESERVED, + aux_data->stream_user_data)) { + return NGHTTP2_ERR_NOMEM; + } + + /* We don't have to call nghttp2_session_adjust_closed_stream() + here, since stream->stream_id is local stream_id, and it does + not affect closed stream count. */ + + nghttp2_outbound_queue_push(&session->ob_reg, item); + item->queued = 1; + + return 0; + } + case NGHTTP2_WINDOW_UPDATE: + if (stream) { + stream->window_update_queued = 1; + } else if (frame->hd.stream_id == 0) { + session->window_update_queued = 1; + } + nghttp2_outbound_queue_push(&session->ob_reg, item); + item->queued = 1; + return 0; + default: + nghttp2_outbound_queue_push(&session->ob_reg, item); + item->queued = 1; + return 0; + } +} + +int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, + uint32_t error_code) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_stream *stream; + nghttp2_mem *mem; + + mem = &session->mem; + stream = nghttp2_session_get_stream(session, stream_id); + if (stream && stream->state == NGHTTP2_STREAM_CLOSING) { + return 0; + } + + /* Cancel pending request HEADERS in ob_syn if this RST_STREAM + refers to that stream. */ + if (!session->server && nghttp2_session_is_my_stream_id(session, stream_id) && + nghttp2_outbound_queue_top(&session->ob_syn)) { + nghttp2_headers_aux_data *aux_data; + nghttp2_frame *headers_frame; + + headers_frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame; + assert(headers_frame->hd.type == NGHTTP2_HEADERS); + + if (headers_frame->hd.stream_id <= stream_id && + (uint32_t)stream_id < session->next_stream_id) { + + for (item = session->ob_syn.head; item; item = item->qnext) { + aux_data = &item->aux_data.headers; + + if (item->frame.hd.stream_id < stream_id) { + continue; + } + + /* stream_id in ob_syn queue must be strictly increasing. If + we found larger ID, then we can break here. */ + if (item->frame.hd.stream_id > stream_id || aux_data->canceled) { + break; + } + + aux_data->error_code = error_code; + aux_data->canceled = 1; + + return 0; + } + } + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + + nghttp2_frame_rst_stream_init(&frame->rst_stream, stream_id, error_code); + rv = nghttp2_session_add_item(session, item); + if (rv != 0) { + nghttp2_frame_rst_stream_free(&frame->rst_stream); + nghttp2_mem_free(mem, item); + return rv; + } + return 0; +} + +nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, + int32_t stream_id, uint8_t flags, + nghttp2_priority_spec *pri_spec_in, + nghttp2_stream_state initial_state, + void *stream_user_data) { + int rv; + nghttp2_stream *stream; + nghttp2_stream *dep_stream = NULL; + int stream_alloc = 0; + nghttp2_priority_spec pri_spec_default; + nghttp2_priority_spec *pri_spec = pri_spec_in; + nghttp2_mem *mem; + + mem = &session->mem; + stream = nghttp2_session_get_stream_raw(session, stream_id); + + if (stream) { + assert(stream->state == NGHTTP2_STREAM_IDLE); + assert(nghttp2_stream_in_dep_tree(stream)); + nghttp2_session_detach_idle_stream(session, stream); + rv = nghttp2_stream_dep_remove(stream); + if (rv != 0) { + return NULL; + } + } else { + stream = nghttp2_mem_malloc(mem, sizeof(nghttp2_stream)); + if (stream == NULL) { + return NULL; + } + + stream_alloc = 1; + } + + if (pri_spec->stream_id != 0) { + dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); + + if (!dep_stream && + session_detect_idle_stream(session, pri_spec->stream_id)) { + /* Depends on idle stream, which does not exist in memory. + Assign default priority for it. */ + nghttp2_priority_spec_default_init(&pri_spec_default); + + dep_stream = nghttp2_session_open_stream( + session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_IDLE, NULL); + + if (dep_stream == NULL) { + if (stream_alloc) { + nghttp2_mem_free(mem, stream); + } + + return NULL; + } + } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { + /* If dep_stream is not part of dependency tree, stream will get + default priority. This handles the case when + pri_spec->stream_id == stream_id. This happens because we + don't check pri_spec->stream_id against new stream ID in + nghttp2_submit_request. This also handles the case when idle + stream created by PRIORITY frame was opened. Somehow we + first remove the idle stream from dependency tree. This is + done to simplify code base, but ideally we should retain old + dependency. But I'm not sure this adds values. */ + nghttp2_priority_spec_default_init(&pri_spec_default); + pri_spec = &pri_spec_default; + } + } + + if (initial_state == NGHTTP2_STREAM_RESERVED) { + flags |= NGHTTP2_STREAM_FLAG_PUSH; + } + + if (stream_alloc) { + nghttp2_stream_init(stream, stream_id, flags, initial_state, + pri_spec->weight, + (int32_t)session->remote_settings.initial_window_size, + (int32_t)session->local_settings.initial_window_size, + stream_user_data, mem); + + rv = nghttp2_map_insert(&session->streams, &stream->map_entry); + if (rv != 0) { + nghttp2_stream_free(stream); + nghttp2_mem_free(mem, stream); + return NULL; + } + } else { + stream->flags = flags; + stream->state = initial_state; + stream->weight = pri_spec->weight; + stream->stream_user_data = stream_user_data; + } + + switch (initial_state) { + case NGHTTP2_STREAM_RESERVED: + if (nghttp2_session_is_my_stream_id(session, stream_id)) { + /* reserved (local) */ + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + } else { + /* reserved (remote) */ + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); + ++session->num_incoming_reserved_streams; + } + /* Reserved stream does not count in the concurrent streams + limit. That is one of the DOS vector. */ + break; + case NGHTTP2_STREAM_IDLE: + /* Idle stream does not count toward the concurrent streams limit. + This is used as anchor node in dependency tree. */ + nghttp2_session_keep_idle_stream(session, stream); + break; + default: + if (nghttp2_session_is_my_stream_id(session, stream_id)) { + ++session->num_outgoing_streams; + } else { + ++session->num_incoming_streams; + } + } + + if (pri_spec->stream_id == 0) { + dep_stream = &session->root; + } + + assert(dep_stream); + + if (pri_spec->exclusive) { + rv = nghttp2_stream_dep_insert(dep_stream, stream); + if (rv != 0) { + return NULL; + } + } else { + nghttp2_stream_dep_add(dep_stream, stream); + } + + return stream; +} + +int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, + uint32_t error_code) { + int rv; + nghttp2_stream *stream; + nghttp2_mem *mem; + int is_my_stream_id; + + mem = &session->mem; + stream = nghttp2_session_get_stream(session, stream_id); + + if (!stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + DEBUGF("stream: stream(%p)=%d close\n", stream, stream->stream_id); + + if (stream->item) { + nghttp2_outbound_item *item; + + item = stream->item; + + rv = nghttp2_stream_detach_item(stream); + + if (rv != 0) { + return rv; + } + + /* If item is queued, it will be deleted when it is popped + (nghttp2_session_prep_frame() will fail). If session->aob.item + points to this item, let active_outbound_item_reset() + free the item. */ + if (!item->queued && item != session->aob.item) { + nghttp2_outbound_item_free(item, mem); + nghttp2_mem_free(mem, item); + } + } + + /* We call on_stream_close_callback even if stream->state is + NGHTTP2_STREAM_INITIAL. This will happen while sending request + HEADERS, a local endpoint receives RST_STREAM for that stream. It + may be PROTOCOL_ERROR, but without notifying stream closure will + hang the stream in a local endpoint. + */ + + if (session->callbacks.on_stream_close_callback) { + if (session->callbacks.on_stream_close_callback( + session, stream_id, error_code, session->user_data) != 0) { + + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + + is_my_stream_id = nghttp2_session_is_my_stream_id(session, stream_id); + + /* pushed streams which is not opened yet is not counted toward max + concurrent limits */ + if ((stream->flags & NGHTTP2_STREAM_FLAG_PUSH)) { + if (!is_my_stream_id) { + --session->num_incoming_reserved_streams; + } + } else { + if (is_my_stream_id) { + --session->num_outgoing_streams; + } else { + --session->num_incoming_streams; + } + } + + /* Closes both directions just in case they are not closed yet */ + stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED; + + if ((session->opt_flags & NGHTTP2_OPTMASK_NO_CLOSED_STREAMS) == 0 && + session->server && !is_my_stream_id && + nghttp2_stream_in_dep_tree(stream)) { + /* On server side, retain stream at most MAX_CONCURRENT_STREAMS + combined with the current active incoming streams to make + dependency tree work better. */ + nghttp2_session_keep_closed_stream(session, stream); + } else { + rv = nghttp2_session_destroy_stream(session, stream); + if (rv != 0) { + return rv; + } + } + + return 0; +} + +int nghttp2_session_destroy_stream(nghttp2_session *session, + nghttp2_stream *stream) { + nghttp2_mem *mem; + int rv; + + DEBUGF("stream: destroy closed stream(%p)=%d\n", stream, stream->stream_id); + + mem = &session->mem; + + if (nghttp2_stream_in_dep_tree(stream)) { + rv = nghttp2_stream_dep_remove(stream); + if (rv != 0) { + return rv; + } + } + + nghttp2_map_remove(&session->streams, stream->stream_id); + nghttp2_stream_free(stream); + nghttp2_mem_free(mem, stream); + + return 0; +} + +void nghttp2_session_keep_closed_stream(nghttp2_session *session, + nghttp2_stream *stream) { + DEBUGF("stream: keep closed stream(%p)=%d, state=%d\n", stream, + stream->stream_id, stream->state); + + if (session->closed_stream_tail) { + session->closed_stream_tail->closed_next = stream; + stream->closed_prev = session->closed_stream_tail; + } else { + session->closed_stream_head = stream; + } + session->closed_stream_tail = stream; + + ++session->num_closed_streams; +} + +void nghttp2_session_keep_idle_stream(nghttp2_session *session, + nghttp2_stream *stream) { + DEBUGF("stream: keep idle stream(%p)=%d, state=%d\n", stream, + stream->stream_id, stream->state); + + if (session->idle_stream_tail) { + session->idle_stream_tail->closed_next = stream; + stream->closed_prev = session->idle_stream_tail; + } else { + session->idle_stream_head = stream; + } + session->idle_stream_tail = stream; + + ++session->num_idle_streams; +} + +void nghttp2_session_detach_idle_stream(nghttp2_session *session, + nghttp2_stream *stream) { + nghttp2_stream *prev_stream, *next_stream; + + DEBUGF("stream: detach idle stream(%p)=%d, state=%d\n", stream, + stream->stream_id, stream->state); + + prev_stream = stream->closed_prev; + next_stream = stream->closed_next; + + if (prev_stream) { + prev_stream->closed_next = next_stream; + } else { + session->idle_stream_head = next_stream; + } + + if (next_stream) { + next_stream->closed_prev = prev_stream; + } else { + session->idle_stream_tail = prev_stream; + } + + stream->closed_prev = NULL; + stream->closed_next = NULL; + + --session->num_idle_streams; +} + +int nghttp2_session_adjust_closed_stream(nghttp2_session *session) { + size_t num_stream_max; + int rv; + + if (session->local_settings.max_concurrent_streams == + NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS) { + num_stream_max = session->pending_local_max_concurrent_stream; + } else { + num_stream_max = session->local_settings.max_concurrent_streams; + } + + DEBUGF("stream: adjusting kept closed streams num_closed_streams=%zu, " + "num_incoming_streams=%zu, max_concurrent_streams=%zu\n", + session->num_closed_streams, session->num_incoming_streams, + num_stream_max); + + while (session->num_closed_streams > 0 && + session->num_closed_streams + session->num_incoming_streams > + num_stream_max) { + nghttp2_stream *head_stream; + nghttp2_stream *next; + + head_stream = session->closed_stream_head; + + assert(head_stream); + + next = head_stream->closed_next; + + rv = nghttp2_session_destroy_stream(session, head_stream); + if (rv != 0) { + return rv; + } + + /* head_stream is now freed */ + + session->closed_stream_head = next; + + if (session->closed_stream_head) { + session->closed_stream_head->closed_prev = NULL; + } else { + session->closed_stream_tail = NULL; + } + + --session->num_closed_streams; + } + + return 0; +} + +int nghttp2_session_adjust_idle_stream(nghttp2_session *session) { + size_t max; + int rv; + + /* Make minimum number of idle streams 16, and maximum 100, which + are arbitrary chosen numbers. */ + max = nghttp2_min( + 100, nghttp2_max( + 16, nghttp2_min(session->local_settings.max_concurrent_streams, + session->pending_local_max_concurrent_stream))); + + DEBUGF("stream: adjusting kept idle streams num_idle_streams=%zu, max=%zu\n", + session->num_idle_streams, max); + + while (session->num_idle_streams > max) { + nghttp2_stream *head; + nghttp2_stream *next; + + head = session->idle_stream_head; + assert(head); + + next = head->closed_next; + + rv = nghttp2_session_destroy_stream(session, head); + if (rv != 0) { + return rv; + } + + /* head is now destroyed */ + + session->idle_stream_head = next; + + if (session->idle_stream_head) { + session->idle_stream_head->closed_prev = NULL; + } else { + session->idle_stream_tail = NULL; + } + + --session->num_idle_streams; + } + + return 0; +} + +/* + * Closes stream with stream ID |stream_id| if both transmission and + * reception of the stream were disallowed. The |error_code| indicates + * the reason of the closure. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_INVALID_ARGUMENT + * The stream is not found. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session, + nghttp2_stream *stream) { + if ((stream->shut_flags & NGHTTP2_SHUT_RDWR) == NGHTTP2_SHUT_RDWR) { + return nghttp2_session_close_stream(session, stream->stream_id, + NGHTTP2_NO_ERROR); + } + return 0; +} + +/* + * Returns nonzero if local endpoint allows reception of new stream + * from remote. + */ +static int session_allow_incoming_new_stream(nghttp2_session *session) { + return (session->goaway_flags & + (NGHTTP2_GOAWAY_TERM_ON_SEND | NGHTTP2_GOAWAY_SENT)) == 0; +} + +/* + * This function returns nonzero if session is closing. + */ +static int session_is_closing(nghttp2_session *session) { + return (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) != 0 || + (nghttp2_session_want_read(session) == 0 && + nghttp2_session_want_write(session) == 0); +} + +/* + * Check that we can send a frame to the |stream|. This function + * returns 0 if we can send a frame to the |frame|, or one of the + * following negative error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed. + * NGHTTP2_ERR_STREAM_SHUT_WR + * The stream is half-closed for transmission. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + */ +static int session_predicate_for_stream_send(nghttp2_session *session, + nghttp2_stream *stream) { + if (stream == NULL) { + return NGHTTP2_ERR_STREAM_CLOSED; + } + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + if (stream->shut_flags & NGHTTP2_SHUT_WR) { + return NGHTTP2_ERR_STREAM_SHUT_WR; + } + return 0; +} + +int nghttp2_session_check_request_allowed(nghttp2_session *session) { + return !session->server && session->next_stream_id <= INT32_MAX && + (session->goaway_flags & NGHTTP2_GOAWAY_RECV) == 0 && + !session_is_closing(session); +} + +/* + * This function checks request HEADERS frame, which opens stream, can + * be sent at this time. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED + * New stream cannot be created because of GOAWAY: session is + * going down or received last_stream_id is strictly less than + * frame->hd.stream_id. + * NGHTTP2_ERR_STREAM_CLOSING + * request HEADERS was canceled by RST_STREAM while it is in queue. + */ +static int session_predicate_request_headers_send(nghttp2_session *session, + nghttp2_outbound_item *item) { + if (item->aux_data.headers.canceled) { + return NGHTTP2_ERR_STREAM_CLOSING; + } + /* If we are terminating session (NGHTTP2_GOAWAY_TERM_ON_SEND), + GOAWAY was received from peer, or session is about to close, new + request is not allowed. */ + if ((session->goaway_flags & NGHTTP2_GOAWAY_RECV) || + session_is_closing(session)) { + return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; + } + return 0; +} + +/* + * This function checks HEADERS, which is the first frame from the + * server, with the |stream| can be sent at this time. The |stream| + * can be NULL. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed or does not exist. + * NGHTTP2_ERR_STREAM_SHUT_WR + * The transmission is not allowed for this stream (e.g., a frame + * with END_STREAM flag set has already sent) + * NGHTTP2_ERR_INVALID_STREAM_ID + * The stream ID is invalid. + * NGHTTP2_ERR_STREAM_CLOSING + * RST_STREAM was queued for this stream. + * NGHTTP2_ERR_INVALID_STREAM_STATE + * The state of the stream is not valid. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + * NGHTTP2_ERR_PROTO + * Client side attempted to send response. + */ +static int session_predicate_response_headers_send(nghttp2_session *session, + nghttp2_stream *stream) { + int rv; + rv = session_predicate_for_stream_send(session, stream); + if (rv != 0) { + return rv; + } + assert(stream); + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } + if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) { + return NGHTTP2_ERR_INVALID_STREAM_ID; + } + switch (stream->state) { + case NGHTTP2_STREAM_OPENING: + return 0; + case NGHTTP2_STREAM_CLOSING: + return NGHTTP2_ERR_STREAM_CLOSING; + default: + return NGHTTP2_ERR_INVALID_STREAM_STATE; + } +} + +/* + * This function checks HEADERS for reserved stream can be sent. The + * |stream| must be reserved state and the |session| is server side. + * The |stream| can be NULL. + * + * This function returns 0 if it succeeds, or one of the following + * error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed. + * NGHTTP2_ERR_STREAM_SHUT_WR + * The stream is half-closed for transmission. + * NGHTTP2_ERR_PROTO + * The stream is not reserved state + * NGHTTP2_ERR_STREAM_CLOSED + * RST_STREAM was queued for this stream. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED + * New stream cannot be created because GOAWAY is already sent or + * received. + * NGHTTP2_ERR_PROTO + * Client side attempted to send push response. + */ +static int +session_predicate_push_response_headers_send(nghttp2_session *session, + nghttp2_stream *stream) { + int rv; + /* TODO Should disallow HEADERS if GOAWAY has already been issued? */ + rv = session_predicate_for_stream_send(session, stream); + if (rv != 0) { + return rv; + } + assert(stream); + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } + if (stream->state != NGHTTP2_STREAM_RESERVED) { + return NGHTTP2_ERR_PROTO; + } + if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) { + return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; + } + return 0; +} + +/* + * This function checks HEADERS, which is neither stream-opening nor + * first response header, with the |stream| can be sent at this time. + * The |stream| can be NULL. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed or does not exist. + * NGHTTP2_ERR_STREAM_SHUT_WR + * The transmission is not allowed for this stream (e.g., a frame + * with END_STREAM flag set has already sent) + * NGHTTP2_ERR_STREAM_CLOSING + * RST_STREAM was queued for this stream. + * NGHTTP2_ERR_INVALID_STREAM_STATE + * The state of the stream is not valid. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + */ +static int session_predicate_headers_send(nghttp2_session *session, + nghttp2_stream *stream) { + int rv; + rv = session_predicate_for_stream_send(session, stream); + if (rv != 0) { + return rv; + } + assert(stream); + + switch (stream->state) { + case NGHTTP2_STREAM_OPENED: + return 0; + case NGHTTP2_STREAM_CLOSING: + return NGHTTP2_ERR_STREAM_CLOSING; + default: + if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) { + return 0; + } + return NGHTTP2_ERR_INVALID_STREAM_STATE; + } +} + +/* + * This function checks PUSH_PROMISE frame |frame| with the |stream| + * can be sent at this time. The |stream| can be NULL. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED + * New stream cannot be created because GOAWAY is already sent or + * received. + * NGHTTP2_ERR_PROTO + * The client side attempts to send PUSH_PROMISE, or the server + * sends PUSH_PROMISE for the stream not initiated by the client. + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed or does not exist. + * NGHTTP2_ERR_STREAM_CLOSING + * RST_STREAM was queued for this stream. + * NGHTTP2_ERR_STREAM_SHUT_WR + * The transmission is not allowed for this stream (e.g., a frame + * with END_STREAM flag set has already sent) + * NGHTTP2_ERR_PUSH_DISABLED + * The remote peer disabled reception of PUSH_PROMISE. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + */ +static int session_predicate_push_promise_send(nghttp2_session *session, + nghttp2_stream *stream) { + int rv; + + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } + + rv = session_predicate_for_stream_send(session, stream); + if (rv != 0) { + return rv; + } + + assert(stream); + + if (session->remote_settings.enable_push == 0) { + return NGHTTP2_ERR_PUSH_DISABLED; + } + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_STREAM_CLOSING; + } + if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) { + return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; + } + return 0; +} + +/* + * This function checks WINDOW_UPDATE with the stream ID |stream_id| + * can be sent at this time. Note that END_STREAM flag of the previous + * frame does not affect the transmission of the WINDOW_UPDATE frame. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed or does not exist. + * NGHTTP2_ERR_STREAM_CLOSING + * RST_STREAM was queued for this stream. + * NGHTTP2_ERR_INVALID_STREAM_STATE + * The state of the stream is not valid. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + */ +static int session_predicate_window_update_send(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + + if (stream_id == 0) { + /* Connection-level window update */ + return 0; + } + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { + return NGHTTP2_ERR_STREAM_CLOSED; + } + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_STREAM_CLOSING; + } + if (state_reserved_local(session, stream)) { + return NGHTTP2_ERR_INVALID_STREAM_STATE; + } + return 0; +} + +static int session_predicate_altsvc_send(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + + if (stream_id == 0) { + return 0; + } + + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { + return NGHTTP2_ERR_STREAM_CLOSED; + } + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_STREAM_CLOSING; + } + + return 0; +} + +/* Take into account settings max frame size and both connection-level + flow control here */ +static ssize_t +nghttp2_session_enforce_flow_control_limits(nghttp2_session *session, + nghttp2_stream *stream, + ssize_t requested_window_size) { + ssize_t window_size = 0; + window_size = nghttp2_min(nghttp2_min(nghttp2_min(requested_window_size, + stream->remote_window_size), + session->remote_window_size), + (int32_t)session->remote_settings.max_frame_size); + return window_size; +} + +/* + * Returns the maximum length of next data read. If the + * connection-level and/or stream-wise flow control are enabled, the + * return value takes into account those current window sizes. The remote + * settings for max frame size is also taken into account. + */ +static size_t nghttp2_session_next_data_read(nghttp2_session *session, + nghttp2_stream *stream) { + ssize_t window_size; + + window_size = nghttp2_session_enforce_flow_control_limits( + session, stream, NGHTTP2_DATA_PAYLOADLEN); + + DEBUGF("send: available window=%zd\n", window_size); + + return window_size > 0 ? (size_t)window_size : 0; +} + +/* + * This function checks DATA with the |stream| can be sent at this + * time. The |stream| can be NULL. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed or does not exist. + * NGHTTP2_ERR_STREAM_SHUT_WR + * The transmission is not allowed for this stream (e.g., a frame + * with END_STREAM flag set has already sent) + * NGHTTP2_ERR_STREAM_CLOSING + * RST_STREAM was queued for this stream. + * NGHTTP2_ERR_INVALID_STREAM_STATE + * The state of the stream is not valid. + * NGHTTP2_ERR_SESSION_CLOSING + * This session is closing. + */ +static int nghttp2_session_predicate_data_send(nghttp2_session *session, + nghttp2_stream *stream) { + int rv; + rv = session_predicate_for_stream_send(session, stream); + if (rv != 0) { + return rv; + } + assert(stream); + if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) { + /* Request body data */ + /* If stream->state is NGHTTP2_STREAM_CLOSING, RST_STREAM was + queued but not yet sent. In this case, we won't send DATA + frames. */ + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_STREAM_CLOSING; + } + if (stream->state == NGHTTP2_STREAM_RESERVED) { + return NGHTTP2_ERR_INVALID_STREAM_STATE; + } + return 0; + } + /* Response body data */ + if (stream->state == NGHTTP2_STREAM_OPENED) { + return 0; + } + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_STREAM_CLOSING; + } + return NGHTTP2_ERR_INVALID_STREAM_STATE; +} + +static ssize_t session_call_select_padding(nghttp2_session *session, + const nghttp2_frame *frame, + size_t max_payloadlen) { + ssize_t rv; + + if (frame->hd.length >= max_payloadlen) { + return (ssize_t)frame->hd.length; + } + + if (session->callbacks.select_padding_callback) { + size_t max_paddedlen; + + max_paddedlen = + nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen); + + rv = session->callbacks.select_padding_callback( + session, frame, max_paddedlen, session->user_data); + if (rv < (ssize_t)frame->hd.length || rv > (ssize_t)max_paddedlen) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + return rv; + } + return (ssize_t)frame->hd.length; +} + +/* Add padding to HEADERS or PUSH_PROMISE. We use + frame->headers.padlen in this function to use the fact that + frame->push_promise has also padlen in the same position. */ +static int session_headers_add_pad(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + ssize_t padded_payloadlen; + nghttp2_active_outbound_item *aob; + nghttp2_bufs *framebufs; + size_t padlen; + size_t max_payloadlen; + + aob = &session->aob; + framebufs = &aob->framebufs; + + max_payloadlen = nghttp2_min(NGHTTP2_MAX_PAYLOADLEN, + frame->hd.length + NGHTTP2_MAX_PADLEN); + + padded_payloadlen = + session_call_select_padding(session, frame, max_payloadlen); + + if (nghttp2_is_fatal((int)padded_payloadlen)) { + return (int)padded_payloadlen; + } + + padlen = (size_t)padded_payloadlen - frame->hd.length; + + DEBUGF("send: padding selected: payloadlen=%zd, padlen=%zu\n", + padded_payloadlen, padlen); + + rv = nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0); + + if (rv != 0) { + return rv; + } + + frame->headers.padlen = padlen; + + return 0; +} + +static size_t session_estimate_headers_payload(nghttp2_session *session, + const nghttp2_nv *nva, + size_t nvlen, + size_t additional) { + return nghttp2_hd_deflate_bound(&session->hd_deflater, nva, nvlen) + + additional; +} + +static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs, + nghttp2_frame *frame) { + ssize_t rv; + nghttp2_buf *buf; + size_t buflen; + size_t framelen; + + assert(session->callbacks.pack_extension_callback); + + buf = &bufs->head->buf; + buflen = nghttp2_min(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN); + + rv = session->callbacks.pack_extension_callback(session, buf->last, buflen, + frame, session->user_data); + if (rv == NGHTTP2_ERR_CANCEL) { + return (int)rv; + } + + if (rv < 0 || (size_t)rv > buflen) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + framelen = (size_t)rv; + + frame->hd.length = framelen; + + assert(buf->pos == buf->last); + buf->last += framelen; + buf->pos -= NGHTTP2_FRAME_HDLEN; + + nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); + + return 0; +} + +/* + * This function serializes frame for transmission. + * + * This function returns 0 if it succeeds, or one of negative error + * codes, including both fatal and non-fatal ones. + */ +static int session_prep_frame(nghttp2_session *session, + nghttp2_outbound_item *item) { + int rv; + nghttp2_frame *frame; + nghttp2_mem *mem; + + mem = &session->mem; + frame = &item->frame; + + switch (frame->hd.type) { + case NGHTTP2_DATA: { + size_t next_readmax; + nghttp2_stream *stream; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + if (stream) { + assert(stream->item == item); + } + + rv = nghttp2_session_predicate_data_send(session, stream); + if (rv != 0) { + /* If stream was already closed, nghttp2_session_get_stream() + returns NULL, but item is still attached to the stream. + Search stream including closed again.*/ + stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); + if (stream) { + int rv2; + + rv2 = nghttp2_stream_detach_item(stream); + + if (nghttp2_is_fatal(rv2)) { + return rv2; + } + } + + return rv; + } + /* Assuming stream is not NULL */ + assert(stream); + next_readmax = nghttp2_session_next_data_read(session, stream); + + if (next_readmax == 0) { + + /* This must be true since we only pop DATA frame item from + queue when session->remote_window_size > 0 */ + assert(session->remote_window_size > 0); + + rv = nghttp2_stream_defer_item(stream, + NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session->aob.item = NULL; + active_outbound_item_reset(&session->aob, mem); + return NGHTTP2_ERR_DEFERRED; + } + + rv = nghttp2_session_pack_data(session, &session->aob.framebufs, + next_readmax, frame, &item->aux_data.data, + stream); + if (rv == NGHTTP2_ERR_PAUSE) { + return rv; + } + if (rv == NGHTTP2_ERR_DEFERRED) { + rv = nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session->aob.item = NULL; + active_outbound_item_reset(&session->aob, mem); + return NGHTTP2_ERR_DEFERRED; + } + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = nghttp2_stream_detach_item(stream); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, + NGHTTP2_INTERNAL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + if (rv != 0) { + int rv2; + + rv2 = nghttp2_stream_detach_item(stream); + + if (nghttp2_is_fatal(rv2)) { + return rv2; + } + + return rv; + } + return 0; + } + case NGHTTP2_HEADERS: { + nghttp2_headers_aux_data *aux_data; + size_t estimated_payloadlen; + + aux_data = &item->aux_data.headers; + + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + /* initial HEADERS, which opens stream */ + nghttp2_stream *stream; + + stream = nghttp2_session_open_stream( + session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, + &frame->headers.pri_spec, NGHTTP2_STREAM_INITIAL, + aux_data->stream_user_data); + + if (stream == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + /* We don't call nghttp2_session_adjust_closed_stream() here, + since we don't keep closed stream in client side */ + + rv = session_predicate_request_headers_send(session, item); + if (rv != 0) { + return rv; + } + + if (session_enforce_http_messaging(session)) { + nghttp2_http_record_request_method(stream, frame); + } + } else { + nghttp2_stream *stream; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + if (stream && stream->state == NGHTTP2_STREAM_RESERVED) { + rv = session_predicate_push_response_headers_send(session, stream); + if (rv == 0) { + frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; + + if (aux_data->stream_user_data) { + stream->stream_user_data = aux_data->stream_user_data; + } + } + } else if (session_predicate_response_headers_send(session, stream) == + 0) { + frame->headers.cat = NGHTTP2_HCAT_RESPONSE; + rv = 0; + } else { + frame->headers.cat = NGHTTP2_HCAT_HEADERS; + + rv = session_predicate_headers_send(session, stream); + } + + if (rv != 0) { + return rv; + } + } + + estimated_payloadlen = session_estimate_headers_payload( + session, frame->headers.nva, frame->headers.nvlen, + NGHTTP2_PRIORITY_SPECLEN); + + if (estimated_payloadlen > session->max_send_header_block_length) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; + } + + rv = nghttp2_frame_pack_headers(&session->aob.framebufs, &frame->headers, + &session->hd_deflater); + + if (rv != 0) { + return rv; + } + + DEBUGF("send: before padding, HEADERS serialized in %zd bytes\n", + nghttp2_bufs_len(&session->aob.framebufs)); + + rv = session_headers_add_pad(session, frame); + + if (rv != 0) { + return rv; + } + + DEBUGF("send: HEADERS finally serialized in %zd bytes\n", + nghttp2_bufs_len(&session->aob.framebufs)); + + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + assert(session->last_sent_stream_id < frame->hd.stream_id); + session->last_sent_stream_id = frame->hd.stream_id; + } + + return 0; + } + case NGHTTP2_PRIORITY: { + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + /* PRIORITY frame can be sent at any time and to any stream + ID. */ + nghttp2_frame_pack_priority(&session->aob.framebufs, &frame->priority); + + /* Peer can send PRIORITY frame against idle stream to create + "anchor" in dependency tree. Only client can do this in + nghttp2. In nghttp2, only server retains non-active (closed + or idle) streams in memory, so we don't open stream here. */ + return 0; + } + case NGHTTP2_RST_STREAM: + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + nghttp2_frame_pack_rst_stream(&session->aob.framebufs, &frame->rst_stream); + return 0; + case NGHTTP2_SETTINGS: { + if (frame->hd.flags & NGHTTP2_FLAG_ACK) { + assert(session->obq_flood_counter_ > 0); + --session->obq_flood_counter_; + /* When session is about to close, don't send SETTINGS ACK. + We are required to send SETTINGS without ACK though; for + example, we have to send SETTINGS as a part of connection + preface. */ + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + } + + rv = nghttp2_frame_pack_settings(&session->aob.framebufs, &frame->settings); + if (rv != 0) { + return rv; + } + return 0; + } + case NGHTTP2_PUSH_PROMISE: { + nghttp2_stream *stream; + size_t estimated_payloadlen; + + /* stream could be NULL if associated stream was already + closed. */ + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + /* predicate should fail if stream is NULL. */ + rv = session_predicate_push_promise_send(session, stream); + if (rv != 0) { + return rv; + } + + assert(stream); + + estimated_payloadlen = session_estimate_headers_payload( + session, frame->push_promise.nva, frame->push_promise.nvlen, 0); + + if (estimated_payloadlen > session->max_send_header_block_length) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; + } + + rv = nghttp2_frame_pack_push_promise( + &session->aob.framebufs, &frame->push_promise, &session->hd_deflater); + if (rv != 0) { + return rv; + } + rv = session_headers_add_pad(session, frame); + if (rv != 0) { + return rv; + } + + assert(session->last_sent_stream_id + 2 <= + frame->push_promise.promised_stream_id); + session->last_sent_stream_id = frame->push_promise.promised_stream_id; + + return 0; + } + case NGHTTP2_PING: + if (frame->hd.flags & NGHTTP2_FLAG_ACK) { + assert(session->obq_flood_counter_ > 0); + --session->obq_flood_counter_; + } + /* PING frame is allowed to be sent unless termination GOAWAY is + sent */ + if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping); + return 0; + case NGHTTP2_GOAWAY: + rv = nghttp2_frame_pack_goaway(&session->aob.framebufs, &frame->goaway); + if (rv != 0) { + return rv; + } + session->local_last_stream_id = frame->goaway.last_stream_id; + + return 0; + case NGHTTP2_WINDOW_UPDATE: + rv = session_predicate_window_update_send(session, frame->hd.stream_id); + if (rv != 0) { + return rv; + } + nghttp2_frame_pack_window_update(&session->aob.framebufs, + &frame->window_update); + return 0; + case NGHTTP2_CONTINUATION: + /* We never handle CONTINUATION here. */ + assert(0); + return 0; + default: { + nghttp2_ext_aux_data *aux_data; + + /* extension frame */ + + aux_data = &item->aux_data.ext; + + if (aux_data->builtin == 0) { + if (session_is_closing(session)) { + return NGHTTP2_ERR_SESSION_CLOSING; + } + + return session_pack_extension(session, &session->aob.framebufs, frame); + } + + switch (frame->hd.type) { + case NGHTTP2_ALTSVC: + rv = session_predicate_altsvc_send(session, frame->hd.stream_id); + if (rv != 0) { + return rv; + } + + nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext); + + return 0; + default: + /* Unreachable here */ + assert(0); + return 0; + } + } + } +} + +nghttp2_outbound_item * +nghttp2_session_get_next_ob_item(nghttp2_session *session) { + if (nghttp2_outbound_queue_top(&session->ob_urgent)) { + return nghttp2_outbound_queue_top(&session->ob_urgent); + } + + if (nghttp2_outbound_queue_top(&session->ob_reg)) { + return nghttp2_outbound_queue_top(&session->ob_reg); + } + + if (!session_is_outgoing_concurrent_streams_max(session)) { + if (nghttp2_outbound_queue_top(&session->ob_syn)) { + return nghttp2_outbound_queue_top(&session->ob_syn); + } + } + + if (session->remote_window_size > 0) { + return nghttp2_stream_next_outbound_item(&session->root); + } + + return NULL; +} + +nghttp2_outbound_item * +nghttp2_session_pop_next_ob_item(nghttp2_session *session) { + nghttp2_outbound_item *item; + + item = nghttp2_outbound_queue_top(&session->ob_urgent); + if (item) { + nghttp2_outbound_queue_pop(&session->ob_urgent); + item->queued = 0; + return item; + } + + item = nghttp2_outbound_queue_top(&session->ob_reg); + if (item) { + nghttp2_outbound_queue_pop(&session->ob_reg); + item->queued = 0; + return item; + } + + if (!session_is_outgoing_concurrent_streams_max(session)) { + item = nghttp2_outbound_queue_top(&session->ob_syn); + if (item) { + nghttp2_outbound_queue_pop(&session->ob_syn); + item->queued = 0; + return item; + } + } + + if (session->remote_window_size > 0) { + return nghttp2_stream_next_outbound_item(&session->root); + } + + return NULL; +} + +static int session_call_before_frame_send(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + if (session->callbacks.before_frame_send_callback) { + rv = session->callbacks.before_frame_send_callback(session, frame, + session->user_data); + if (rv == NGHTTP2_ERR_CANCEL) { + return rv; + } + + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return 0; +} + +static int session_call_on_frame_send(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + if (session->callbacks.on_frame_send_callback) { + rv = session->callbacks.on_frame_send_callback(session, frame, + session->user_data); + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return 0; +} + +static int find_stream_on_goaway_func(nghttp2_map_entry *entry, void *ptr) { + nghttp2_close_stream_on_goaway_arg *arg; + nghttp2_stream *stream; + + arg = (nghttp2_close_stream_on_goaway_arg *)ptr; + stream = (nghttp2_stream *)entry; + + if (nghttp2_session_is_my_stream_id(arg->session, stream->stream_id)) { + if (arg->incoming) { + return 0; + } + } else if (!arg->incoming) { + return 0; + } + + if (stream->state != NGHTTP2_STREAM_IDLE && + (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) == 0 && + stream->stream_id > arg->last_stream_id) { + /* We are collecting streams to close because we cannot call + nghttp2_session_close_stream() inside nghttp2_map_each(). + Reuse closed_next member.. bad choice? */ + assert(stream->closed_next == NULL); + assert(stream->closed_prev == NULL); + + if (arg->head) { + stream->closed_next = arg->head; + arg->head = stream; + } else { + arg->head = stream; + } + } + + return 0; +} + +/* Closes non-idle and non-closed streams whose stream ID > + last_stream_id. If incoming is nonzero, we are going to close + incoming streams. Otherwise, close outgoing streams. */ +static int session_close_stream_on_goaway(nghttp2_session *session, + int32_t last_stream_id, + int incoming) { + int rv; + nghttp2_stream *stream, *next_stream; + nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id, + incoming}; + + rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg); + assert(rv == 0); + + stream = arg.head; + while (stream) { + next_stream = stream->closed_next; + stream->closed_next = NULL; + rv = nghttp2_session_close_stream(session, stream->stream_id, + NGHTTP2_REFUSED_STREAM); + + /* stream may be deleted here */ + + stream = next_stream; + + if (nghttp2_is_fatal(rv)) { + /* Clean up closed_next member just in case */ + while (stream) { + next_stream = stream->closed_next; + stream->closed_next = NULL; + stream = next_stream; + } + return rv; + } + } + + return 0; +} + +static void reschedule_stream(nghttp2_stream *stream) { + stream->last_writelen = stream->item->frame.hd.length; + + nghttp2_stream_reschedule(stream); +} + +static int session_update_stream_consumed_size(nghttp2_session *session, + nghttp2_stream *stream, + size_t delta_size); + +static int session_update_connection_consumed_size(nghttp2_session *session, + size_t delta_size); + +static int session_update_recv_connection_window_size(nghttp2_session *session, + size_t delta_size); + +static int session_update_recv_stream_window_size(nghttp2_session *session, + nghttp2_stream *stream, + size_t delta_size, + int send_window_update); + +/* + * Called after a frame is sent. This function runs + * on_frame_send_callback and handles stream closure upon END_STREAM + * or RST_STREAM. This function does not reset session->aob. It is a + * responsibility of session_after_frame_sent2. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +static int session_after_frame_sent1(nghttp2_session *session) { + int rv; + nghttp2_active_outbound_item *aob = &session->aob; + nghttp2_outbound_item *item = aob->item; + nghttp2_bufs *framebufs = &aob->framebufs; + nghttp2_frame *frame; + nghttp2_stream *stream; + + frame = &item->frame; + + if (frame->hd.type == NGHTTP2_DATA) { + nghttp2_data_aux_data *aux_data; + + aux_data = &item->aux_data.data; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + /* We update flow control window after a frame was completely + sent. This is possible because we choose payload length not to + exceed the window */ + session->remote_window_size -= (int32_t)frame->hd.length; + if (stream) { + stream->remote_window_size -= (int32_t)frame->hd.length; + } + + if (stream && aux_data->eof) { + rv = nghttp2_stream_detach_item(stream); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + /* Call on_frame_send_callback after + nghttp2_stream_detach_item(), so that application can issue + nghttp2_submit_data() in the callback. */ + if (session->callbacks.on_frame_send_callback) { + rv = session_call_on_frame_send(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + int stream_closed; + + stream_closed = + (stream->shut_flags & NGHTTP2_SHUT_RDWR) == NGHTTP2_SHUT_RDWR; + + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); + + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); + if (nghttp2_is_fatal(rv)) { + return rv; + } + /* stream may be NULL if it was closed */ + if (stream_closed) { + stream = NULL; + } + } + return 0; + } + + if (session->callbacks.on_frame_send_callback) { + rv = session_call_on_frame_send(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + return 0; + } + + /* non-DATA frame */ + + if (frame->hd.type == NGHTTP2_HEADERS || + frame->hd.type == NGHTTP2_PUSH_PROMISE) { + if (nghttp2_bufs_next_present(framebufs)) { + DEBUGF("send: CONTINUATION exists, just return\n"); + return 0; + } + } + rv = session_call_on_frame_send(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + switch (frame->hd.type) { + case NGHTTP2_HEADERS: { + nghttp2_headers_aux_data *aux_data; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream) { + return 0; + } + + switch (frame->headers.cat) { + case NGHTTP2_HCAT_REQUEST: { + stream->state = NGHTTP2_STREAM_OPENING; + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); + } + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); + if (nghttp2_is_fatal(rv)) { + return rv; + } + /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ + aux_data = &item->aux_data.headers; + if (aux_data->data_prd.read_callback) { + /* nghttp2_submit_data() makes a copy of aux_data->data_prd */ + rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, + frame->hd.stream_id, &aux_data->data_prd); + if (nghttp2_is_fatal(rv)) { + return rv; + } + /* TODO nghttp2_submit_data() may fail if stream has already + DATA frame item. We might have to handle it here. */ + } + return 0; + } + case NGHTTP2_HCAT_PUSH_RESPONSE: + stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH); + ++session->num_outgoing_streams; + /* Fall through */ + case NGHTTP2_HCAT_RESPONSE: + stream->state = NGHTTP2_STREAM_OPENED; + /* Fall through */ + case NGHTTP2_HCAT_HEADERS: + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); + } + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); + if (nghttp2_is_fatal(rv)) { + return rv; + } + /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ + aux_data = &item->aux_data.headers; + if (aux_data->data_prd.read_callback) { + rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, + frame->hd.stream_id, &aux_data->data_prd); + if (nghttp2_is_fatal(rv)) { + return rv; + } + /* TODO nghttp2_submit_data() may fail if stream has already + DATA frame item. We might have to handle it here. */ + } + return 0; + default: + /* Unreachable */ + assert(0); + return 0; + } + } + case NGHTTP2_PRIORITY: + if (session->server) { + return 0; + ; + } + + stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); + + if (!stream) { + if (!session_detect_idle_stream(session, frame->hd.stream_id)) { + return 0; + } + + stream = nghttp2_session_open_stream( + session, frame->hd.stream_id, NGHTTP2_FLAG_NONE, + &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL); + if (!stream) { + return NGHTTP2_ERR_NOMEM; + } + } else { + rv = nghttp2_session_reprioritize_stream(session, stream, + &frame->priority.pri_spec); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + rv = nghttp2_session_adjust_idle_stream(session); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; + case NGHTTP2_RST_STREAM: + rv = nghttp2_session_close_stream(session, frame->hd.stream_id, + frame->rst_stream.error_code); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return 0; + case NGHTTP2_GOAWAY: { + nghttp2_goaway_aux_data *aux_data; + + aux_data = &item->aux_data.goaway; + + if ((aux_data->flags & NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE) == 0) { + + if (aux_data->flags & NGHTTP2_GOAWAY_AUX_TERM_ON_SEND) { + session->goaway_flags |= NGHTTP2_GOAWAY_TERM_SENT; + } + + session->goaway_flags |= NGHTTP2_GOAWAY_SENT; + + rv = session_close_stream_on_goaway(session, frame->goaway.last_stream_id, + 1); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + return 0; + } + case NGHTTP2_WINDOW_UPDATE: + if (frame->hd.stream_id == 0) { + session->window_update_queued = 0; + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { + rv = session_update_connection_consumed_size(session, 0); + } else { + rv = session_update_recv_connection_window_size(session, 0); + } + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; + } + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream) { + return 0; + } + + stream->window_update_queued = 0; + + /* We don't have to send WINDOW_UPDATE if END_STREAM from peer + is seen. */ + if (stream->shut_flags & NGHTTP2_SHUT_RD) { + return 0; + } + + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { + rv = session_update_stream_consumed_size(session, stream, 0); + } else { + rv = session_update_recv_stream_window_size(session, stream, 0, 1); + } + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; + default: + return 0; + } +} + +/* + * Called after a frame is sent and session_after_frame_sent1. This + * function is responsible to reset session->aob. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +static int session_after_frame_sent2(nghttp2_session *session) { + int rv; + nghttp2_active_outbound_item *aob = &session->aob; + nghttp2_outbound_item *item = aob->item; + nghttp2_bufs *framebufs = &aob->framebufs; + nghttp2_frame *frame; + nghttp2_mem *mem; + nghttp2_stream *stream; + nghttp2_data_aux_data *aux_data; + + mem = &session->mem; + frame = &item->frame; + + if (frame->hd.type != NGHTTP2_DATA) { + + if (frame->hd.type == NGHTTP2_HEADERS || + frame->hd.type == NGHTTP2_PUSH_PROMISE) { + + if (nghttp2_bufs_next_present(framebufs)) { + framebufs->cur = framebufs->cur->next; + + DEBUGF("send: next CONTINUATION frame, %zu bytes\n", + nghttp2_buf_len(&framebufs->cur->buf)); + + return 0; + } + } + + active_outbound_item_reset(&session->aob, mem); + + return 0; + } + + /* DATA frame */ + + aux_data = &item->aux_data.data; + + /* On EOF, we have already detached data. Please note that + application may issue nghttp2_submit_data() in + on_frame_send_callback (call from session_after_frame_sent1), + which attach data to stream. We don't want to detach it. */ + if (aux_data->eof) { + active_outbound_item_reset(aob, mem); + + return 0; + } + + /* Reset no_copy here because next write may not use this. */ + aux_data->no_copy = 0; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + /* If session is closed or RST_STREAM was queued, we won't send + further data. */ + if (nghttp2_session_predicate_data_send(session, stream) != 0) { + if (stream) { + rv = nghttp2_stream_detach_item(stream); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + active_outbound_item_reset(aob, mem); + + return 0; + } + + aob->item = NULL; + active_outbound_item_reset(&session->aob, mem); + + return 0; +} + +static int session_call_send_data(nghttp2_session *session, + nghttp2_outbound_item *item, + nghttp2_bufs *framebufs) { + int rv; + nghttp2_buf *buf; + size_t length; + nghttp2_frame *frame; + nghttp2_data_aux_data *aux_data; + + buf = &framebufs->cur->buf; + frame = &item->frame; + length = frame->hd.length - frame->data.padlen; + aux_data = &item->aux_data.data; + + rv = session->callbacks.send_data_callback(session, frame, buf->pos, length, + &aux_data->data_prd.source, + session->user_data); + + switch (rv) { + case 0: + case NGHTTP2_ERR_WOULDBLOCK: + case NGHTTP2_ERR_PAUSE: + case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE: + return rv; + default: + return NGHTTP2_ERR_CALLBACK_FAILURE; + } +} + +static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + const uint8_t **data_ptr, + int fast_cb) { + int rv; + nghttp2_active_outbound_item *aob; + nghttp2_bufs *framebufs; + nghttp2_mem *mem; + + mem = &session->mem; + aob = &session->aob; + framebufs = &aob->framebufs; + + /* We may have idle streams more than we expect (e.g., + nghttp2_session_change_stream_priority() or + nghttp2_session_create_idle_stream()). Adjust them here. */ + rv = nghttp2_session_adjust_idle_stream(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + for (;;) { + switch (aob->state) { + case NGHTTP2_OB_POP_ITEM: { + nghttp2_outbound_item *item; + + item = nghttp2_session_pop_next_ob_item(session); + if (item == NULL) { + return 0; + } + + rv = session_prep_frame(session, item); + if (rv == NGHTTP2_ERR_PAUSE) { + return 0; + } + if (rv == NGHTTP2_ERR_DEFERRED) { + DEBUGF("send: frame transmission deferred\n"); + break; + } + if (rv < 0) { + int32_t opened_stream_id = 0; + uint32_t error_code = NGHTTP2_INTERNAL_ERROR; + + DEBUGF("send: frame preparation failed with %s\n", + nghttp2_strerror(rv)); + /* TODO If the error comes from compressor, the connection + must be closed. */ + if (item->frame.hd.type != NGHTTP2_DATA && + session->callbacks.on_frame_not_send_callback && is_non_fatal(rv)) { + nghttp2_frame *frame = &item->frame; + /* The library is responsible for the transmission of + WINDOW_UPDATE frame, so we don't call error callback for + it. */ + if (frame->hd.type != NGHTTP2_WINDOW_UPDATE && + session->callbacks.on_frame_not_send_callback( + session, frame, rv, session->user_data) != 0) { + + nghttp2_outbound_item_free(item, mem); + nghttp2_mem_free(mem, item); + + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + /* We have to close stream opened by failed request HEADERS + or PUSH_PROMISE. */ + switch (item->frame.hd.type) { + case NGHTTP2_HEADERS: + if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) { + opened_stream_id = item->frame.hd.stream_id; + if (item->aux_data.headers.canceled) { + error_code = item->aux_data.headers.error_code; + } else { + /* Set error_code to REFUSED_STREAM so that application + can send request again. */ + error_code = NGHTTP2_REFUSED_STREAM; + } + } + break; + case NGHTTP2_PUSH_PROMISE: + opened_stream_id = item->frame.push_promise.promised_stream_id; + break; + } + if (opened_stream_id) { + /* careful not to override rv */ + int rv2; + rv2 = nghttp2_session_close_stream(session, opened_stream_id, + error_code); + + if (nghttp2_is_fatal(rv2)) { + return rv2; + } + } + + nghttp2_outbound_item_free(item, mem); + nghttp2_mem_free(mem, item); + active_outbound_item_reset(aob, mem); + + if (rv == NGHTTP2_ERR_HEADER_COMP) { + /* If header compression error occurred, should terminiate + connection. */ + rv = nghttp2_session_terminate_session(session, + NGHTTP2_INTERNAL_ERROR); + } + if (nghttp2_is_fatal(rv)) { + return rv; + } + break; + } + + aob->item = item; + + nghttp2_bufs_rewind(framebufs); + + if (item->frame.hd.type != NGHTTP2_DATA) { + nghttp2_frame *frame; + + frame = &item->frame; + + DEBUGF("send: next frame: payloadlen=%zu, type=%u, flags=0x%02x, " + "stream_id=%d\n", + frame->hd.length, frame->hd.type, frame->hd.flags, + frame->hd.stream_id); + + rv = session_call_before_frame_send(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (rv == NGHTTP2_ERR_CANCEL) { + int32_t opened_stream_id = 0; + uint32_t error_code = NGHTTP2_INTERNAL_ERROR; + + if (session->callbacks.on_frame_not_send_callback) { + if (session->callbacks.on_frame_not_send_callback( + session, frame, rv, session->user_data) != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + + /* We have to close stream opened by canceled request + HEADERS or PUSH_PROMISE. */ + switch (item->frame.hd.type) { + case NGHTTP2_HEADERS: + if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) { + opened_stream_id = item->frame.hd.stream_id; + /* We don't have to check + item->aux_data.headers.canceled since it has already + been checked. */ + /* Set error_code to REFUSED_STREAM so that application + can send request again. */ + error_code = NGHTTP2_REFUSED_STREAM; + } + break; + case NGHTTP2_PUSH_PROMISE: + opened_stream_id = item->frame.push_promise.promised_stream_id; + break; + } + if (opened_stream_id) { + /* careful not to override rv */ + int rv2; + rv2 = nghttp2_session_close_stream(session, opened_stream_id, + error_code); + + if (nghttp2_is_fatal(rv2)) { + return rv2; + } + } + + active_outbound_item_reset(aob, mem); + + break; + } + } else { + DEBUGF("send: next frame: DATA\n"); + + if (item->aux_data.data.no_copy) { + aob->state = NGHTTP2_OB_SEND_NO_COPY; + break; + } + } + + DEBUGF("send: start transmitting frame type=%u, length=%zd\n", + framebufs->cur->buf.pos[3], + framebufs->cur->buf.last - framebufs->cur->buf.pos); + + aob->state = NGHTTP2_OB_SEND_DATA; + + break; + } + case NGHTTP2_OB_SEND_DATA: { + size_t datalen; + nghttp2_buf *buf; + + buf = &framebufs->cur->buf; + + if (buf->pos == buf->last) { + DEBUGF("send: end transmission of a frame\n"); + + /* Frame has completely sent */ + if (fast_cb) { + rv = session_after_frame_sent2(session); + } else { + rv = session_after_frame_sent1(session); + if (rv < 0) { + /* FATAL */ + assert(nghttp2_is_fatal(rv)); + return rv; + } + rv = session_after_frame_sent2(session); + } + if (rv < 0) { + /* FATAL */ + assert(nghttp2_is_fatal(rv)); + return rv; + } + /* We have already adjusted the next state */ + break; + } + + *data_ptr = buf->pos; + datalen = nghttp2_buf_len(buf); + + /* We increment the offset here. If send_callback does not send + everything, we will adjust it. */ + buf->pos += datalen; + + return (ssize_t)datalen; + } + case NGHTTP2_OB_SEND_NO_COPY: { + nghttp2_stream *stream; + nghttp2_frame *frame; + int pause; + + DEBUGF("send: no copy DATA\n"); + + frame = &aob->item->frame; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (stream == NULL) { + DEBUGF("send: no copy DATA cancelled because stream was closed\n"); + + active_outbound_item_reset(aob, mem); + + break; + } + + rv = session_call_send_data(session, aob->item, framebufs); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = nghttp2_stream_detach_item(stream); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, + NGHTTP2_INTERNAL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + active_outbound_item_reset(aob, mem); + + break; + } + + if (rv == NGHTTP2_ERR_WOULDBLOCK) { + return 0; + } + + pause = (rv == NGHTTP2_ERR_PAUSE); + + rv = session_after_frame_sent1(session); + if (rv < 0) { + assert(nghttp2_is_fatal(rv)); + return rv; + } + rv = session_after_frame_sent2(session); + if (rv < 0) { + assert(nghttp2_is_fatal(rv)); + return rv; + } + + /* We have already adjusted the next state */ + + if (pause) { + return 0; + } + + break; + } + case NGHTTP2_OB_SEND_CLIENT_MAGIC: { + size_t datalen; + nghttp2_buf *buf; + + buf = &framebufs->cur->buf; + + if (buf->pos == buf->last) { + DEBUGF("send: end transmission of client magic\n"); + active_outbound_item_reset(aob, mem); + break; + } + + *data_ptr = buf->pos; + datalen = nghttp2_buf_len(buf); + + buf->pos += datalen; + + return (ssize_t)datalen; + } + } + } +} + +ssize_t nghttp2_session_mem_send(nghttp2_session *session, + const uint8_t **data_ptr) { + int rv; + ssize_t len; + + *data_ptr = NULL; + + len = nghttp2_session_mem_send_internal(session, data_ptr, 1); + if (len <= 0) { + return len; + } + + if (session->aob.item) { + /* We have to call session_after_frame_sent1 here to handle stream + closure upon transmission of frames. Otherwise, END_STREAM may + be reached to client before we call nghttp2_session_mem_send + again and we may get exceeding number of incoming streams. */ + rv = session_after_frame_sent1(session); + if (rv < 0) { + assert(nghttp2_is_fatal(rv)); + return (ssize_t)rv; + } + } + + return len; +} + +int nghttp2_session_send(nghttp2_session *session) { + const uint8_t *data = NULL; + ssize_t datalen; + ssize_t sentlen; + nghttp2_bufs *framebufs; + + framebufs = &session->aob.framebufs; + + for (;;) { + datalen = nghttp2_session_mem_send_internal(session, &data, 0); + if (datalen <= 0) { + return (int)datalen; + } + sentlen = session->callbacks.send_callback(session, data, (size_t)datalen, + 0, session->user_data); + if (sentlen < 0) { + if (sentlen == NGHTTP2_ERR_WOULDBLOCK) { + /* Transmission canceled. Rewind the offset */ + framebufs->cur->buf.pos -= datalen; + + return 0; + } + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + /* Rewind the offset to the amount of unsent bytes */ + framebufs->cur->buf.pos -= datalen - sentlen; + } +} + +static ssize_t session_recv(nghttp2_session *session, uint8_t *buf, + size_t len) { + ssize_t rv; + rv = session->callbacks.recv_callback(session, buf, len, 0, + session->user_data); + if (rv > 0) { + if ((size_t)rv > len) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } else if (rv < 0 && rv != NGHTTP2_ERR_WOULDBLOCK && rv != NGHTTP2_ERR_EOF) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + return rv; +} + +static int session_call_on_begin_frame(nghttp2_session *session, + const nghttp2_frame_hd *hd) { + int rv; + + if (session->callbacks.on_begin_frame_callback) { + + rv = session->callbacks.on_begin_frame_callback(session, hd, + session->user_data); + + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + + return 0; +} + +static int session_call_on_frame_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + if (session->callbacks.on_frame_recv_callback) { + rv = session->callbacks.on_frame_recv_callback(session, frame, + session->user_data); + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return 0; +} + +static int session_call_on_begin_headers(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + DEBUGF("recv: call on_begin_headers callback stream_id=%d\n", + frame->hd.stream_id); + if (session->callbacks.on_begin_headers_callback) { + rv = session->callbacks.on_begin_headers_callback(session, frame, + session->user_data); + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + return rv; + } + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return 0; +} + +static int session_call_on_header(nghttp2_session *session, + const nghttp2_frame *frame, + const nghttp2_hd_nv *nv) { + int rv = 0; + if (session->callbacks.on_header_callback2) { + rv = session->callbacks.on_header_callback2( + session, frame, nv->name, nv->value, nv->flags, session->user_data); + } else if (session->callbacks.on_header_callback) { + rv = session->callbacks.on_header_callback( + session, frame, nv->name->base, nv->name->len, nv->value->base, + nv->value->len, nv->flags, session->user_data); + } + + if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + return rv; + } + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} + +static int session_call_on_invalid_header(nghttp2_session *session, + const nghttp2_frame *frame, + const nghttp2_hd_nv *nv) { + int rv; + if (session->callbacks.on_invalid_header_callback2) { + rv = session->callbacks.on_invalid_header_callback2( + session, frame, nv->name, nv->value, nv->flags, session->user_data); + } else if (session->callbacks.on_invalid_header_callback) { + rv = session->callbacks.on_invalid_header_callback( + session, frame, nv->name->base, nv->name->len, nv->value->base, + nv->value->len, nv->flags, session->user_data); + } else { + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + return rv; + } + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + return 0; +} + +static int +session_call_on_extension_chunk_recv_callback(nghttp2_session *session, + const uint8_t *data, size_t len) { + int rv; + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + if (session->callbacks.on_extension_chunk_recv_callback) { + rv = session->callbacks.on_extension_chunk_recv_callback( + session, &frame->hd, data, len, session->user_data); + if (rv == NGHTTP2_ERR_CANCEL) { + return rv; + } + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + + return 0; +} + +static int session_call_unpack_extension_callback(nghttp2_session *session) { + int rv; + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + void *payload = NULL; + + rv = session->callbacks.unpack_extension_callback( + session, &payload, &frame->hd, session->user_data); + if (rv == NGHTTP2_ERR_CANCEL) { + return rv; + } + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + frame->ext.payload = payload; + + return 0; +} + +/* + * Handles frame size error. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int session_handle_frame_size_error(nghttp2_session *session) { + /* TODO Currently no callback is called for this error, because we + call this callback before reading any payload */ + return nghttp2_session_terminate_session(session, NGHTTP2_FRAME_SIZE_ERROR); +} + +static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { + switch (lib_error_code) { + case NGHTTP2_ERR_STREAM_CLOSED: + return NGHTTP2_STREAM_CLOSED; + case NGHTTP2_ERR_HEADER_COMP: + return NGHTTP2_COMPRESSION_ERROR; + case NGHTTP2_ERR_FRAME_SIZE_ERROR: + return NGHTTP2_FRAME_SIZE_ERROR; + case NGHTTP2_ERR_FLOW_CONTROL: + return NGHTTP2_FLOW_CONTROL_ERROR; + case NGHTTP2_ERR_REFUSED_STREAM: + return NGHTTP2_REFUSED_STREAM; + case NGHTTP2_ERR_PROTO: + case NGHTTP2_ERR_HTTP_HEADER: + case NGHTTP2_ERR_HTTP_MESSAGING: + return NGHTTP2_PROTOCOL_ERROR; + default: + return NGHTTP2_INTERNAL_ERROR; + } +} + +/* + * Calls on_invalid_frame_recv_callback if it is set to |session|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_CALLBACK_FAILURE + * User defined callback function fails. + */ +static int session_call_on_invalid_frame_recv_callback(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error_code) { + if (session->callbacks.on_invalid_frame_recv_callback) { + if (session->callbacks.on_invalid_frame_recv_callback( + session, frame, lib_error_code, session->user_data) != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return 0; +} + +static int session_handle_invalid_stream2(nghttp2_session *session, + int32_t stream_id, + nghttp2_frame *frame, + int lib_error_code) { + int rv; + rv = nghttp2_session_add_rst_stream( + session, stream_id, get_error_code_from_lib_error_code(lib_error_code)); + if (rv != 0) { + return rv; + } + if (session->callbacks.on_invalid_frame_recv_callback) { + if (session->callbacks.on_invalid_frame_recv_callback( + session, frame, lib_error_code, session->user_data) != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return 0; +} + +static int session_handle_invalid_stream(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error_code) { + return session_handle_invalid_stream2(session, frame->hd.stream_id, frame, + lib_error_code); +} + +static int session_inflate_handle_invalid_stream(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error_code) { + int rv; + rv = session_handle_invalid_stream(session, frame, lib_error_code); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_IGN_HEADER_BLOCK; +} + +/* + * Handles invalid frame which causes connection error. + */ +static int session_handle_invalid_connection(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error_code, + const char *reason) { + if (session->callbacks.on_invalid_frame_recv_callback) { + if (session->callbacks.on_invalid_frame_recv_callback( + session, frame, lib_error_code, session->user_data) != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + return nghttp2_session_terminate_session_with_reason( + session, get_error_code_from_lib_error_code(lib_error_code), reason); +} + +static int session_inflate_handle_invalid_connection(nghttp2_session *session, + nghttp2_frame *frame, + int lib_error_code, + const char *reason) { + int rv; + rv = + session_handle_invalid_connection(session, frame, lib_error_code, reason); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_IGN_HEADER_BLOCK; +} + +/* + * Inflates header block in the memory pointed by |in| with |inlen| + * bytes. If this function returns NGHTTP2_ERR_PAUSE, the caller must + * call this function again, until it returns 0 or one of negative + * error code. If |call_header_cb| is zero, the on_header_callback + * are not invoked and the function never return NGHTTP2_ERR_PAUSE. If + * the given |in| is the last chunk of header block, the |final| must + * be nonzero. If header block is successfully processed (which is + * indicated by the return value 0, NGHTTP2_ERR_PAUSE or + * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE), the number of processed + * input bytes is assigned to the |*readlen_ptr|. + * + * This function return 0 if it succeeds, or one of the negative error + * codes: + * + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE + * The callback returns this error code, indicating that this + * stream should be RST_STREAMed. + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_PAUSE + * The callback function returned NGHTTP2_ERR_PAUSE + * NGHTTP2_ERR_HEADER_COMP + * Header decompression failed + */ +static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, + size_t *readlen_ptr, uint8_t *in, size_t inlen, + int final, int call_header_cb) { + ssize_t proclen; + int rv; + int inflate_flags; + nghttp2_hd_nv nv; + nghttp2_stream *stream; + nghttp2_stream *subject_stream; + int trailer = 0; + + *readlen_ptr = 0; + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { + subject_stream = nghttp2_session_get_stream( + session, frame->push_promise.promised_stream_id); + } else { + subject_stream = stream; + trailer = session_trailer_headers(session, stream, frame); + } + + DEBUGF("recv: decoding header block %zu bytes\n", inlen); + for (;;) { + inflate_flags = 0; + proclen = nghttp2_hd_inflate_hd_nv(&session->hd_inflater, &nv, + &inflate_flags, in, inlen, final); + if (nghttp2_is_fatal((int)proclen)) { + return (int)proclen; + } + if (proclen < 0) { + if (session->iframe.state == NGHTTP2_IB_READ_HEADER_BLOCK) { + if (subject_stream && subject_stream->state != NGHTTP2_STREAM_CLOSING) { + /* Adding RST_STREAM here is very important. It prevents + from invoking subsequent callbacks for the same stream + ID. */ + rv = nghttp2_session_add_rst_stream( + session, subject_stream->stream_id, NGHTTP2_COMPRESSION_ERROR); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + } + rv = + nghttp2_session_terminate_session(session, NGHTTP2_COMPRESSION_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return NGHTTP2_ERR_HEADER_COMP; + } + in += proclen; + inlen -= (size_t)proclen; + *readlen_ptr += (size_t)proclen; + + DEBUGF("recv: proclen=%zd\n", proclen); + + if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) { + rv = 0; + if (subject_stream && session_enforce_http_messaging(session)) { + rv = nghttp2_http_on_header(session, subject_stream, frame, &nv, + trailer); + + if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) { + /* Don't overwrite rv here */ + int rv2; + + rv2 = session_call_on_invalid_header(session, frame, &nv); + if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = NGHTTP2_ERR_HTTP_HEADER; + } else { + if (rv2 != 0) { + return rv2; + } + + /* header is ignored */ + DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + rv2 = session_call_error_callback( + session, NGHTTP2_ERR_HTTP_HEADER, + "Ignoring received invalid HTTP header field: frame type: " + "%u, stream: %d, name: [%.*s], value: [%.*s]", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + if (nghttp2_is_fatal(rv2)) { + return rv2; + } + } + } + + if (rv == NGHTTP2_ERR_HTTP_HEADER) { + DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + rv = session_call_error_callback( + session, NGHTTP2_ERR_HTTP_HEADER, + "Invalid HTTP header field was received: frame type: " + "%u, stream: %d, name: [%.*s], value: [%.*s]", + frame->hd.type, frame->hd.stream_id, (int)nv.name->len, + nv.name->base, (int)nv.value->len, nv.value->base); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = + session_handle_invalid_stream2(session, subject_stream->stream_id, + frame, NGHTTP2_ERR_HTTP_HEADER); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + } + if (rv == 0) { + rv = session_call_on_header(session, frame, &nv); + /* This handles NGHTTP2_ERR_PAUSE and + NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */ + if (rv != 0) { + return rv; + } + } + } + if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { + nghttp2_hd_inflate_end_headers(&session->hd_inflater); + break; + } + if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) { + break; + } + } + return 0; +} + +/* + * Call this function when HEADERS frame was completely received. + * + * This function returns 0 if it succeeds, or one of negative error + * codes: + * + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int session_end_stream_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream) { + int rv; + if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { + return 0; + } + + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; +} + +static int session_after_header_block_received(nghttp2_session *session) { + int rv = 0; + int call_cb = 1; + nghttp2_frame *frame = &session->iframe.frame; + nghttp2_stream *stream; + + /* We don't call on_frame_recv_callback if stream has been closed + already or being closed. */ + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) { + return 0; + } + + if (session_enforce_http_messaging(session)) { + if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { + nghttp2_stream *subject_stream; + + subject_stream = nghttp2_session_get_stream( + session, frame->push_promise.promised_stream_id); + if (subject_stream) { + rv = nghttp2_http_on_request_headers(subject_stream, frame); + } + } else { + assert(frame->hd.type == NGHTTP2_HEADERS); + switch (frame->headers.cat) { + case NGHTTP2_HCAT_REQUEST: + rv = nghttp2_http_on_request_headers(stream, frame); + break; + case NGHTTP2_HCAT_RESPONSE: + case NGHTTP2_HCAT_PUSH_RESPONSE: + rv = nghttp2_http_on_response_headers(stream); + break; + case NGHTTP2_HCAT_HEADERS: + if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) { + assert(!session->server); + rv = nghttp2_http_on_response_headers(stream); + } else { + rv = nghttp2_http_on_trailer_headers(stream, frame); + } + break; + default: + assert(0); + } + if (rv == 0 && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { + rv = nghttp2_http_on_remote_end_stream(stream); + } + } + if (rv != 0) { + int32_t stream_id; + + if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { + stream_id = frame->push_promise.promised_stream_id; + } else { + stream_id = frame->hd.stream_id; + } + + call_cb = 0; + + rv = session_handle_invalid_stream2(session, stream_id, frame, + NGHTTP2_ERR_HTTP_MESSAGING); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + } + + if (call_cb) { + rv = session_call_on_frame_received(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + if (frame->hd.type != NGHTTP2_HEADERS) { + return 0; + } + + return session_end_stream_headers_received(session, frame, stream); +} + +int nghttp2_session_on_request_headers_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv = 0; + nghttp2_stream *stream; + if (frame->hd.stream_id == 0) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0"); + } + + /* If client receives idle stream from server, it is invalid + regardless stream ID is even or odd. This is because client is + not expected to receive request from server. */ + if (!session->server) { + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "request HEADERS: client received request"); + } + + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + + assert(session->server); + + if (!session_is_new_peer_stream_id(session, frame->hd.stream_id)) { + if (frame->hd.stream_id == 0 || + nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "request HEADERS: invalid stream_id"); + } + + /* RFC 7540 says if an endpoint receives a HEADERS with invalid + * stream ID (e.g, numerically smaller than previous), it MUST + * issue connection error with error code PROTOCOL_ERROR. It is a + * bit hard to detect this, since we cannot remember all streams + * we observed so far. + * + * You might imagine this is really easy. But no. HTTP/2 is + * asynchronous protocol, and usually client and server do not + * share the complete picture of open/closed stream status. For + * example, after server sends RST_STREAM for a stream, client may + * send trailer HEADERS for that stream. If naive server detects + * that, and issued connection error, then it is a bug of server + * implementation since client is not wrong if it did not get + * RST_STREAM when it issued trailer HEADERS. + * + * At the moment, we are very conservative here. We only use + * connection error if stream ID refers idle stream, or we are + * sure that stream is half-closed(remote) or closed. Otherwise + * we just ignore HEADERS for now. + */ + stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); + if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed"); + } + + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + session->last_recv_stream_id = frame->hd.stream_id; + + if (session_is_incoming_concurrent_streams_max(session)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "request HEADERS: max concurrent streams exceeded"); + } + + if (!session_allow_incoming_new_stream(session)) { + /* We just ignore stream after GOAWAY was sent */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + + if (frame->headers.pri_spec.stream_id == frame->hd.stream_id) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: depend on itself"); + } + + if (session_is_incoming_concurrent_streams_pending_max(session)) { + return session_inflate_handle_invalid_stream(session, frame, + NGHTTP2_ERR_REFUSED_STREAM); + } + + stream = nghttp2_session_open_stream( + session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, + &frame->headers.pri_spec, NGHTTP2_STREAM_OPENING, NULL); + if (!stream) { + return NGHTTP2_ERR_NOMEM; + } + + rv = nghttp2_session_adjust_closed_stream(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session->last_proc_stream_id = session->last_recv_stream_id; + + rv = session_call_on_begin_headers(session, frame); + if (rv != 0) { + return rv; + } + return 0; +} + +int nghttp2_session_on_response_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream) { + int rv; + /* This function is only called if stream->state == + NGHTTP2_STREAM_OPENING and stream_id is local side initiated. */ + assert(stream->state == NGHTTP2_STREAM_OPENING && + nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)); + if (frame->hd.stream_id == 0) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "response HEADERS: stream_id == 0"); + } + if (stream->shut_flags & NGHTTP2_SHUT_RD) { + /* half closed (remote): from the spec: + + If an endpoint receives additional frames for a stream that is + in this state it MUST respond with a stream error (Section + 5.4.2) of type STREAM_CLOSED. + + We go further, and make it connection error. + */ + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed"); + } + stream->state = NGHTTP2_STREAM_OPENED; + rv = session_call_on_begin_headers(session, frame); + if (rv != 0) { + return rv; + } + return 0; +} + +int nghttp2_session_on_push_response_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream) { + int rv = 0; + assert(stream->state == NGHTTP2_STREAM_RESERVED); + if (frame->hd.stream_id == 0) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "push response HEADERS: stream_id == 0"); + } + + if (session->server) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "HEADERS: no HEADERS allowed from client in reserved state"); + } + + if (session_is_incoming_concurrent_streams_max(session)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "push response HEADERS: max concurrent streams exceeded"); + } + + if (!session_allow_incoming_new_stream(session)) { + /* We don't accept new stream after GOAWAY was sent. */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + + if (session_is_incoming_concurrent_streams_pending_max(session)) { + return session_inflate_handle_invalid_stream(session, frame, + NGHTTP2_ERR_REFUSED_STREAM); + } + + nghttp2_stream_promise_fulfilled(stream); + if (!nghttp2_session_is_my_stream_id(session, stream->stream_id)) { + --session->num_incoming_reserved_streams; + } + ++session->num_incoming_streams; + rv = session_call_on_begin_headers(session, frame); + if (rv != 0) { + return rv; + } + return 0; +} + +int nghttp2_session_on_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream) { + int rv = 0; + if (frame->hd.stream_id == 0) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "HEADERS: stream_id == 0"); + } + if ((stream->shut_flags & NGHTTP2_SHUT_RD)) { + /* half closed (remote): from the spec: + + If an endpoint receives additional frames for a stream that is + in this state it MUST respond with a stream error (Section + 5.4.2) of type STREAM_CLOSED. + + we go further, and make it connection error. + */ + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed"); + } + if (nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + if (stream->state == NGHTTP2_STREAM_OPENED) { + rv = session_call_on_begin_headers(session, frame); + if (rv != 0) { + return rv; + } + return 0; + } + + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + /* If this is remote peer initiated stream, it is OK unless it + has sent END_STREAM frame already. But if stream is in + NGHTTP2_STREAM_CLOSING, we discard the frame. This is a race + condition. */ + if (stream->state != NGHTTP2_STREAM_CLOSING) { + rv = session_call_on_begin_headers(session, frame); + if (rv != 0) { + return rv; + } + return 0; + } + return NGHTTP2_ERR_IGN_HEADER_BLOCK; +} + +static int session_process_headers_frame(nghttp2_session *session) { + int rv; + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + nghttp2_stream *stream; + + rv = nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos); + + if (rv != 0) { + return nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: could not unpack"); + } + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream) { + frame->headers.cat = NGHTTP2_HCAT_REQUEST; + return nghttp2_session_on_request_headers_received(session, frame); + } + + if (stream->state == NGHTTP2_STREAM_RESERVED) { + frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; + return nghttp2_session_on_push_response_headers_received(session, frame, + stream); + } + + if (stream->state == NGHTTP2_STREAM_OPENING && + nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + frame->headers.cat = NGHTTP2_HCAT_RESPONSE; + return nghttp2_session_on_response_headers_received(session, frame, stream); + } + + frame->headers.cat = NGHTTP2_HCAT_HEADERS; + return nghttp2_session_on_headers_received(session, frame, stream); +} + +int nghttp2_session_on_priority_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + nghttp2_stream *stream; + + if (frame->hd.stream_id == 0) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "PRIORITY: stream_id == 0"); + } + + if (frame->priority.pri_spec.stream_id == frame->hd.stream_id) { + return nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "depend on itself"); + } + + if (!session->server) { + /* Re-prioritization works only in server */ + return session_call_on_frame_received(session, frame); + } + + stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); + + if (!stream) { + /* PRIORITY against idle stream can create anchor node in + dependency tree. */ + if (!session_detect_idle_stream(session, frame->hd.stream_id)) { + return 0; + } + + stream = nghttp2_session_open_stream( + session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, + &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL); + + if (stream == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + rv = nghttp2_session_adjust_idle_stream(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } else { + rv = nghttp2_session_reprioritize_stream(session, stream, + &frame->priority.pri_spec); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = nghttp2_session_adjust_idle_stream(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + return session_call_on_frame_received(session, frame); +} + +static int session_process_priority_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos); + + return nghttp2_session_on_priority_received(session, frame); +} + +int nghttp2_session_on_rst_stream_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + nghttp2_stream *stream; + if (frame->hd.stream_id == 0) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "RST_STREAM: stream_id == 0"); + } + + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "RST_STREAM: stream in idle"); + } + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (stream) { + /* We may use stream->shut_flags for strict error checking. */ + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + } + + rv = session_call_on_frame_received(session, frame); + if (rv != 0) { + return rv; + } + rv = nghttp2_session_close_stream(session, frame->hd.stream_id, + frame->rst_stream.error_code); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return 0; +} + +static int session_process_rst_stream_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + nghttp2_frame_unpack_rst_stream_payload(&frame->rst_stream, iframe->sbuf.pos); + + return nghttp2_session_on_rst_stream_received(session, frame); +} + +static int update_remote_initial_window_size_func(nghttp2_map_entry *entry, + void *ptr) { + int rv; + nghttp2_update_window_size_arg *arg; + nghttp2_stream *stream; + + arg = (nghttp2_update_window_size_arg *)ptr; + stream = (nghttp2_stream *)entry; + + rv = nghttp2_stream_update_remote_initial_window_size( + stream, arg->new_window_size, arg->old_window_size); + if (rv != 0) { + return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); + } + + /* If window size gets positive, push deferred DATA frame to + outbound queue. */ + if (stream->remote_window_size > 0 && + nghttp2_stream_check_deferred_by_flow_control(stream)) { + + rv = nghttp2_stream_resume_deferred_item( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + return 0; +} + +/* + * Updates the remote initial window size of all active streams. If + * error occurs, all streams may not be updated. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int +session_update_remote_initial_window_size(nghttp2_session *session, + int32_t new_initial_window_size) { + nghttp2_update_window_size_arg arg; + + arg.session = session; + arg.new_window_size = new_initial_window_size; + arg.old_window_size = (int32_t)session->remote_settings.initial_window_size; + + return nghttp2_map_each(&session->streams, + update_remote_initial_window_size_func, &arg); +} + +static int update_local_initial_window_size_func(nghttp2_map_entry *entry, + void *ptr) { + int rv; + nghttp2_update_window_size_arg *arg; + nghttp2_stream *stream; + arg = (nghttp2_update_window_size_arg *)ptr; + stream = (nghttp2_stream *)entry; + rv = nghttp2_stream_update_local_initial_window_size( + stream, arg->new_window_size, arg->old_window_size); + if (rv != 0) { + return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); + } + if (!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) && + stream->window_update_queued == 0 && + nghttp2_should_send_window_update(stream->local_window_size, + stream->recv_window_size)) { + + rv = nghttp2_session_add_window_update(arg->session, NGHTTP2_FLAG_NONE, + stream->stream_id, + stream->recv_window_size); + if (rv != 0) { + return rv; + } + + stream->recv_window_size = 0; + } + return 0; +} + +/* + * Updates the local initial window size of all active streams. If + * error occurs, all streams may not be updated. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int +session_update_local_initial_window_size(nghttp2_session *session, + int32_t new_initial_window_size, + int32_t old_initial_window_size) { + nghttp2_update_window_size_arg arg; + arg.session = session; + arg.new_window_size = new_initial_window_size; + arg.old_window_size = old_initial_window_size; + return nghttp2_map_each(&session->streams, + update_local_initial_window_size_func, &arg); +} + +/* + * Apply SETTINGS values |iv| having |niv| elements to the local + * settings. We assumes that all values in |iv| is correct, since we + * validated them in nghttp2_session_add_settings() already. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_HEADER_COMP + * The header table size is out of range + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_session_update_local_settings(nghttp2_session *session, + nghttp2_settings_entry *iv, + size_t niv) { + int rv; + size_t i; + int32_t new_initial_window_size = -1; + uint32_t header_table_size = 0; + uint32_t min_header_table_size = UINT32_MAX; + uint8_t header_table_size_seen = 0; + /* For NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, use the value last + seen. For NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, use both minimum + value and last seen value. */ + for (i = 0; i < niv; ++i) { + switch (iv[i].settings_id) { + case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + header_table_size_seen = 1; + header_table_size = iv[i].value; + min_header_table_size = nghttp2_min(min_header_table_size, iv[i].value); + break; + case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: + new_initial_window_size = (int32_t)iv[i].value; + break; + } + } + if (header_table_size_seen) { + if (min_header_table_size < header_table_size) { + rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater, + min_header_table_size); + if (rv != 0) { + return rv; + } + } + + rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater, + header_table_size); + if (rv != 0) { + return rv; + } + } + if (new_initial_window_size != -1) { + rv = session_update_local_initial_window_size( + session, new_initial_window_size, + (int32_t)session->local_settings.initial_window_size); + if (rv != 0) { + return rv; + } + } + + for (i = 0; i < niv; ++i) { + switch (iv[i].settings_id) { + case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + session->local_settings.header_table_size = iv[i].value; + break; + case NGHTTP2_SETTINGS_ENABLE_PUSH: + session->local_settings.enable_push = iv[i].value; + break; + case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: + session->local_settings.max_concurrent_streams = iv[i].value; + break; + case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: + session->local_settings.initial_window_size = iv[i].value; + break; + case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: + session->local_settings.max_frame_size = iv[i].value; + break; + case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: + session->local_settings.max_header_list_size = iv[i].value; + break; + } + } + + return 0; +} + +int nghttp2_session_on_settings_received(nghttp2_session *session, + nghttp2_frame *frame, int noack) { + int rv; + size_t i; + nghttp2_mem *mem; + nghttp2_inflight_settings *settings; + + mem = &session->mem; + + if (frame->hd.stream_id != 0) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "SETTINGS: stream_id != 0"); + } + if (frame->hd.flags & NGHTTP2_FLAG_ACK) { + if (frame->settings.niv != 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_FRAME_SIZE_ERROR, + "SETTINGS: ACK and payload != 0"); + } + + settings = session->inflight_settings_head; + + if (!settings) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "SETTINGS: unexpected ACK"); + } + + rv = nghttp2_session_update_local_settings(session, settings->iv, + settings->niv); + + session->inflight_settings_head = settings->next; + + inflight_settings_del(settings, mem); + + if (rv != 0) { + if (nghttp2_is_fatal(rv)) { + return rv; + } + return session_handle_invalid_connection(session, frame, rv, NULL); + } + return session_call_on_frame_received(session, frame); + } + + for (i = 0; i < frame->settings.niv; ++i) { + nghttp2_settings_entry *entry = &frame->settings.iv[i]; + + switch (entry->settings_id) { + case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + + rv = nghttp2_hd_deflate_change_table_size(&session->hd_deflater, + entry->value); + if (rv != 0) { + if (nghttp2_is_fatal(rv)) { + return rv; + } else { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_HEADER_COMP, NULL); + } + } + + session->remote_settings.header_table_size = entry->value; + + break; + case NGHTTP2_SETTINGS_ENABLE_PUSH: + + if (entry->value != 0 && entry->value != 1) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "SETTINGS: invalid SETTINGS_ENBLE_PUSH"); + } + + if (!session->server && entry->value != 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "SETTINGS: server attempted to enable push"); + } + + session->remote_settings.enable_push = entry->value; + + break; + case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: + + session->remote_settings.max_concurrent_streams = entry->value; + + break; + case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: + + /* Update the initial window size of the all active streams */ + /* Check that initial_window_size < (1u << 31) */ + if (entry->value > NGHTTP2_MAX_WINDOW_SIZE) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_FLOW_CONTROL, + "SETTINGS: too large SETTINGS_INITIAL_WINDOW_SIZE"); + } + + rv = session_update_remote_initial_window_size(session, + (int32_t)entry->value); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (rv != 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_FLOW_CONTROL, NULL); + } + + session->remote_settings.initial_window_size = entry->value; + + break; + case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: + + if (entry->value < NGHTTP2_MAX_FRAME_SIZE_MIN || + entry->value > NGHTTP2_MAX_FRAME_SIZE_MAX) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "SETTINGS: invalid SETTINGS_MAX_FRAME_SIZE"); + } + + session->remote_settings.max_frame_size = entry->value; + + break; + case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: + + session->remote_settings.max_header_list_size = entry->value; + + break; + } + } + + if (!noack && !session_is_closing(session)) { + rv = nghttp2_session_add_settings(session, NGHTTP2_FLAG_ACK, NULL, 0); + + if (rv != 0) { + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return session_handle_invalid_connection(session, frame, + NGHTTP2_ERR_INTERNAL, NULL); + } + } + + return session_call_on_frame_received(session, frame); +} + +static int session_process_settings_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + size_t i; + nghttp2_settings_entry min_header_size_entry; + + if (iframe->max_niv) { + min_header_size_entry = iframe->iv[iframe->max_niv - 1]; + + if (min_header_size_entry.value < UINT32_MAX) { + /* If we have less value, then we must have + SETTINGS_HEADER_TABLE_SIZE in i < iframe->niv */ + for (i = 0; i < iframe->niv; ++i) { + if (iframe->iv[i].settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) { + break; + } + } + + assert(i < iframe->niv); + + if (min_header_size_entry.value != iframe->iv[i].value) { + iframe->iv[iframe->niv++] = iframe->iv[i]; + iframe->iv[i] = min_header_size_entry; + } + } + } + + nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv, + iframe->niv); + + iframe->iv = NULL; + iframe->niv = 0; + iframe->max_niv = 0; + + return nghttp2_session_on_settings_received(session, frame, 0 /* ACK */); +} + +int nghttp2_session_on_push_promise_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + nghttp2_stream *stream; + nghttp2_stream *promised_stream; + nghttp2_priority_spec pri_spec; + + if (frame->hd.stream_id == 0) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream_id == 0"); + } + if (session->server || session->local_settings.enable_push == 0) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: push disabled"); + } + + if (!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: invalid stream_id"); + } + + if (!session_allow_incoming_new_stream(session)) { + /* We just discard PUSH_PROMISE after GOAWAY was sent */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + + if (!session_is_new_peer_stream_id(session, + frame->push_promise.promised_stream_id)) { + /* The spec says if an endpoint receives a PUSH_PROMISE with + illegal stream ID is subject to a connection error of type + PROTOCOL_ERROR. */ + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "PUSH_PROMISE: invalid promised_stream_id"); + } + + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream in idle"); + } + + session->last_recv_stream_id = frame->push_promise.promised_stream_id; + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream || stream->state == NGHTTP2_STREAM_CLOSING || + !session->pending_enable_push || + session->num_incoming_reserved_streams >= + session->max_incoming_reserved_streams) { + /* Currently, client does not retain closed stream, so we don't + check NGHTTP2_SHUT_RD condition here. */ + + rv = nghttp2_session_add_rst_stream( + session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); + if (rv != 0) { + return rv; + } + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + + if (stream->shut_flags & NGHTTP2_SHUT_RD) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_STREAM_CLOSED, + "PUSH_PROMISE: stream closed"); + } + + nghttp2_priority_spec_init(&pri_spec, stream->stream_id, + NGHTTP2_DEFAULT_WEIGHT, 0); + + promised_stream = nghttp2_session_open_stream( + session, frame->push_promise.promised_stream_id, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec, NGHTTP2_STREAM_RESERVED, NULL); + + if (!promised_stream) { + return NGHTTP2_ERR_NOMEM; + } + + /* We don't call nghttp2_session_adjust_closed_stream(), since we + don't keep closed stream in client side */ + + session->last_proc_stream_id = session->last_recv_stream_id; + rv = session_call_on_begin_headers(session, frame); + if (rv != 0) { + return rv; + } + return 0; +} + +static int session_process_push_promise_frame(nghttp2_session *session) { + int rv; + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + rv = nghttp2_frame_unpack_push_promise_payload(&frame->push_promise, + iframe->sbuf.pos); + + if (rv != 0) { + return nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: could not unpack"); + } + + return nghttp2_session_on_push_promise_received(session, frame); +} + +int nghttp2_session_on_ping_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv = 0; + if (frame->hd.stream_id != 0) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "PING: stream_id != 0"); + } + if ((session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK) == 0 && + (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0 && + !session_is_closing(session)) { + /* Peer sent ping, so ping it back */ + rv = nghttp2_session_add_ping(session, NGHTTP2_FLAG_ACK, + frame->ping.opaque_data); + if (rv != 0) { + return rv; + } + } + return session_call_on_frame_received(session, frame); +} + +static int session_process_ping_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + nghttp2_frame_unpack_ping_payload(&frame->ping, iframe->sbuf.pos); + + return nghttp2_session_on_ping_received(session, frame); +} + +int nghttp2_session_on_goaway_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + + if (frame->hd.stream_id != 0) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "GOAWAY: stream_id != 0"); + } + /* Spec says Endpoints MUST NOT increase the value they send in the + last stream identifier. */ + if ((frame->goaway.last_stream_id > 0 && + !nghttp2_session_is_my_stream_id(session, + frame->goaway.last_stream_id)) || + session->remote_last_stream_id < frame->goaway.last_stream_id) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "GOAWAY: invalid last_stream_id"); + } + + session->goaway_flags |= NGHTTP2_GOAWAY_RECV; + + session->remote_last_stream_id = frame->goaway.last_stream_id; + + rv = session_call_on_frame_received(session, frame); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return session_close_stream_on_goaway(session, frame->goaway.last_stream_id, + 0); +} + +static int session_process_goaway_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + nghttp2_frame_unpack_goaway_payload(&frame->goaway, iframe->sbuf.pos, + iframe->lbuf.pos, + nghttp2_buf_len(&iframe->lbuf)); + + nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0); + + return nghttp2_session_on_goaway_received(session, frame); +} + +static int +session_on_connection_window_update_received(nghttp2_session *session, + nghttp2_frame *frame) { + /* Handle connection-level flow control */ + if (frame->window_update.window_size_increment == 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "WINDOW_UPDATE: window_size_increment == 0"); + } + + if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < + session->remote_window_size) { + return session_handle_invalid_connection(session, frame, + NGHTTP2_ERR_FLOW_CONTROL, NULL); + } + session->remote_window_size += frame->window_update.window_size_increment; + + return session_call_on_frame_received(session, frame); +} + +static int session_on_stream_window_update_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv; + nghttp2_stream *stream; + + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "WINDOW_UPDATE to idle stream"); + } + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream) { + return 0; + } + if (state_reserved_remote(session, stream)) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "WINDOW_UPADATE to reserved stream"); + } + if (frame->window_update.window_size_increment == 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "WINDOW_UPDATE: window_size_increment == 0"); + } + if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < + stream->remote_window_size) { + return session_handle_invalid_stream(session, frame, + NGHTTP2_ERR_FLOW_CONTROL); + } + stream->remote_window_size += frame->window_update.window_size_increment; + + if (stream->remote_window_size > 0 && + nghttp2_stream_check_deferred_by_flow_control(stream)) { + + rv = nghttp2_stream_resume_deferred_item( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + return session_call_on_frame_received(session, frame); +} + +int nghttp2_session_on_window_update_received(nghttp2_session *session, + nghttp2_frame *frame) { + if (frame->hd.stream_id == 0) { + return session_on_connection_window_update_received(session, frame); + } else { + return session_on_stream_window_update_received(session, frame); + } +} + +static int session_process_window_update_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + nghttp2_frame_unpack_window_update_payload(&frame->window_update, + iframe->sbuf.pos); + + return nghttp2_session_on_window_update_received(session, frame); +} + +int nghttp2_session_on_altsvc_received(nghttp2_session *session, + nghttp2_frame *frame) { + nghttp2_ext_altsvc *altsvc; + nghttp2_stream *stream; + + altsvc = frame->ext.payload; + + /* session->server case has been excluded */ + + if (frame->hd.stream_id == 0) { + if (altsvc->origin_len == 0) { + return session_call_on_invalid_frame_recv_callback(session, frame, + NGHTTP2_ERR_PROTO); + } + } else { + if (altsvc->origin_len > 0) { + return session_call_on_invalid_frame_recv_callback(session, frame, + NGHTTP2_ERR_PROTO); + } + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream) { + return 0; + } + + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return 0; + } + } + + if (altsvc->field_value_len == 0) { + return session_call_on_invalid_frame_recv_callback(session, frame, + NGHTTP2_ERR_PROTO); + } + + return session_call_on_frame_received(session, frame); +} + +static int session_process_altsvc_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + nghttp2_frame_unpack_altsvc_payload( + &frame->ext, nghttp2_get_uint16(iframe->sbuf.pos), iframe->lbuf.pos, + nghttp2_buf_len(&iframe->lbuf)); + + /* nghttp2_frame_unpack_altsvc_payload steals buffer from + iframe->lbuf */ + nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0); + + return nghttp2_session_on_altsvc_received(session, frame); +} + +static int session_process_extension_frame(nghttp2_session *session) { + int rv; + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + + rv = session_call_unpack_extension_callback(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + /* This handles the case where rv == NGHTTP2_ERR_CANCEL as well */ + if (rv != 0) { + return 0; + } + + return session_call_on_frame_received(session, frame); +} + +int nghttp2_session_on_data_received(nghttp2_session *session, + nghttp2_frame *frame) { + int rv = 0; + int call_cb = 1; + nghttp2_stream *stream; + + /* We don't call on_frame_recv_callback if stream has been closed + already or being closed. */ + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) { + /* This should be treated as stream error, but it results in lots + of RST_STREAM. So just ignore frame against nonexistent stream + for now. */ + return 0; + } + + if (session_enforce_http_messaging(session) && + (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { + if (nghttp2_http_on_remote_end_stream(stream) != 0) { + call_cb = 0; + rv = nghttp2_session_add_rst_stream(session, stream->stream_id, + NGHTTP2_PROTOCOL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + } + + if (call_cb) { + rv = session_call_on_frame_received(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + return 0; +} + +/* For errors, this function only returns FATAL error. */ +static int session_process_data_frame(nghttp2_session *session) { + int rv; + nghttp2_frame *public_data_frame = &session->iframe.frame; + rv = nghttp2_session_on_data_received(session, public_data_frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return 0; +} + +/* + * Now we have SETTINGS synchronization, flow control error can be + * detected strictly. If DATA frame is received with length > 0 and + * current received window size + delta length is strictly larger than + * local window size, it is subject to FLOW_CONTROL_ERROR, so return + * -1. Note that local_window_size is calculated after SETTINGS ACK is + * received from peer, so peer must honor this limit. If the resulting + * recv_window_size is strictly larger than NGHTTP2_MAX_WINDOW_SIZE, + * return -1 too. + */ +static int adjust_recv_window_size(int32_t *recv_window_size_ptr, size_t delta, + int32_t local_window_size) { + if (*recv_window_size_ptr > local_window_size - (int32_t)delta || + *recv_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - (int32_t)delta) { + return -1; + } + *recv_window_size_ptr += (int32_t)delta; + return 0; +} + +/* + * Accumulates received bytes |delta_size| for stream-level flow + * control and decides whether to send WINDOW_UPDATE to that stream. + * If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE will not + * be sent. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int session_update_recv_stream_window_size(nghttp2_session *session, + nghttp2_stream *stream, + size_t delta_size, + int send_window_update) { + int rv; + rv = adjust_recv_window_size(&stream->recv_window_size, delta_size, + stream->local_window_size); + if (rv != 0) { + return nghttp2_session_add_rst_stream(session, stream->stream_id, + NGHTTP2_FLOW_CONTROL_ERROR); + } + /* We don't have to send WINDOW_UPDATE if the data received is the + last chunk in the incoming stream. */ + /* We have to use local_settings here because it is the constraint + the remote endpoint should honor. */ + if (send_window_update && + !(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) && + stream->window_update_queued == 0 && + nghttp2_should_send_window_update(stream->local_window_size, + stream->recv_window_size)) { + rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, + stream->stream_id, + stream->recv_window_size); + if (rv != 0) { + return rv; + } + + stream->recv_window_size = 0; + } + return 0; +} + +/* + * Accumulates received bytes |delta_size| for connection-level flow + * control and decides whether to send WINDOW_UPDATE to the + * connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, + * WINDOW_UPDATE will not be sent. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int session_update_recv_connection_window_size(nghttp2_session *session, + size_t delta_size) { + int rv; + rv = adjust_recv_window_size(&session->recv_window_size, delta_size, + session->local_window_size); + if (rv != 0) { + return nghttp2_session_terminate_session(session, + NGHTTP2_FLOW_CONTROL_ERROR); + } + if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) && + session->window_update_queued == 0 && + nghttp2_should_send_window_update(session->local_window_size, + session->recv_window_size)) { + /* Use stream ID 0 to update connection-level flow control + window */ + rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, 0, + session->recv_window_size); + if (rv != 0) { + return rv; + } + + session->recv_window_size = 0; + } + return 0; +} + +static int session_update_consumed_size(nghttp2_session *session, + int32_t *consumed_size_ptr, + int32_t *recv_window_size_ptr, + uint8_t window_update_queued, + int32_t stream_id, size_t delta_size, + int32_t local_window_size) { + int32_t recv_size; + int rv; + + if ((size_t)*consumed_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta_size) { + return nghttp2_session_terminate_session(session, + NGHTTP2_FLOW_CONTROL_ERROR); + } + + *consumed_size_ptr += (int32_t)delta_size; + + if (window_update_queued == 0) { + /* recv_window_size may be smaller than consumed_size, because it + may be decreased by negative value with + nghttp2_submit_window_update(). */ + recv_size = nghttp2_min(*consumed_size_ptr, *recv_window_size_ptr); + + if (nghttp2_should_send_window_update(local_window_size, recv_size)) { + rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, + stream_id, recv_size); + + if (rv != 0) { + return rv; + } + + *recv_window_size_ptr -= recv_size; + *consumed_size_ptr -= recv_size; + } + } + + return 0; +} + +static int session_update_stream_consumed_size(nghttp2_session *session, + nghttp2_stream *stream, + size_t delta_size) { + return session_update_consumed_size( + session, &stream->consumed_size, &stream->recv_window_size, + stream->window_update_queued, stream->stream_id, delta_size, + stream->local_window_size); +} + +static int session_update_connection_consumed_size(nghttp2_session *session, + size_t delta_size) { + return session_update_consumed_size( + session, &session->consumed_size, &session->recv_window_size, + session->window_update_queued, 0, delta_size, session->local_window_size); +} + +/* + * Checks that we can receive the DATA frame for stream, which is + * indicated by |session->iframe.frame.hd.stream_id|. If it is a + * connection error situation, GOAWAY frame will be issued by this + * function. + * + * If the DATA frame is allowed, returns 0. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_IGN_PAYLOAD + * The reception of DATA frame is connection error; or should be + * ignored. + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int session_on_data_received_fail_fast(nghttp2_session *session) { + int rv; + nghttp2_stream *stream; + nghttp2_inbound_frame *iframe; + int32_t stream_id; + const char *failure_reason; + uint32_t error_code = NGHTTP2_PROTOCOL_ERROR; + + iframe = &session->iframe; + stream_id = iframe->frame.hd.stream_id; + + if (stream_id == 0) { + /* The spec says that if a DATA frame is received whose stream ID + is 0, the recipient MUST respond with a connection error of + type PROTOCOL_ERROR. */ + failure_reason = "DATA: stream_id == 0"; + goto fail; + } + + if (session_detect_idle_stream(session, stream_id)) { + failure_reason = "DATA: stream in idle"; + error_code = NGHTTP2_PROTOCOL_ERROR; + goto fail; + } + + stream = nghttp2_session_get_stream(session, stream_id); + if (!stream) { + stream = nghttp2_session_get_stream_raw(session, stream_id); + if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) { + failure_reason = "DATA: stream closed"; + error_code = NGHTTP2_STREAM_CLOSED; + goto fail; + } + + return NGHTTP2_ERR_IGN_PAYLOAD; + } + if (stream->shut_flags & NGHTTP2_SHUT_RD) { + failure_reason = "DATA: stream in half-closed(remote)"; + error_code = NGHTTP2_STREAM_CLOSED; + goto fail; + } + + if (nghttp2_session_is_my_stream_id(session, stream_id)) { + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_IGN_PAYLOAD; + } + if (stream->state != NGHTTP2_STREAM_OPENED) { + failure_reason = "DATA: stream not opened"; + goto fail; + } + return 0; + } + if (stream->state == NGHTTP2_STREAM_RESERVED) { + failure_reason = "DATA: stream in reserved"; + goto fail; + } + if (stream->state == NGHTTP2_STREAM_CLOSING) { + return NGHTTP2_ERR_IGN_PAYLOAD; + } + return 0; +fail: + rv = nghttp2_session_terminate_session_with_reason(session, error_code, + failure_reason); + if (nghttp2_is_fatal(rv)) { + return rv; + } + return NGHTTP2_ERR_IGN_PAYLOAD; +} + +static size_t inbound_frame_payload_readlen(nghttp2_inbound_frame *iframe, + const uint8_t *in, + const uint8_t *last) { + return nghttp2_min((size_t)(last - in), iframe->payloadleft); +} + +/* + * Resets iframe->sbuf and advance its mark pointer by |left| bytes. + */ +static void inbound_frame_set_mark(nghttp2_inbound_frame *iframe, size_t left) { + nghttp2_buf_reset(&iframe->sbuf); + iframe->sbuf.mark += left; +} + +static size_t inbound_frame_buf_read(nghttp2_inbound_frame *iframe, + const uint8_t *in, const uint8_t *last) { + size_t readlen; + + readlen = + nghttp2_min((size_t)(last - in), nghttp2_buf_mark_avail(&iframe->sbuf)); + + iframe->sbuf.last = nghttp2_cpymem(iframe->sbuf.last, in, readlen); + + return readlen; +} + +/* + * Unpacks SETTINGS entry in iframe->sbuf. + */ +static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) { + nghttp2_settings_entry iv; + nghttp2_settings_entry *min_header_table_size_entry; + size_t i; + + nghttp2_frame_unpack_settings_entry(&iv, iframe->sbuf.pos); + + switch (iv.settings_id) { + case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + case NGHTTP2_SETTINGS_ENABLE_PUSH: + case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: + case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: + case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: + case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: + break; + default: + DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id); + + iframe->iv[iframe->niv++] = iv; + + return; + } + + for (i = 0; i < iframe->niv; ++i) { + if (iframe->iv[i].settings_id == iv.settings_id) { + iframe->iv[i] = iv; + break; + } + } + + if (i == iframe->niv) { + iframe->iv[iframe->niv++] = iv; + } + + if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) { + /* Keep track of minimum value of SETTINGS_HEADER_TABLE_SIZE */ + min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1]; + + if (iv.value < min_header_table_size_entry->value) { + min_header_table_size_entry->value = iv.value; + } + } +} + +/* + * Checks PADDED flags and set iframe->sbuf to read them accordingly. + * If padding is set, this function returns 1. If no padding is set, + * this function returns 0. On error, returns -1. + */ +static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe, + nghttp2_frame_hd *hd) { + if (hd->flags & NGHTTP2_FLAG_PADDED) { + if (hd->length < 1) { + return -1; + } + inbound_frame_set_mark(iframe, 1); + return 1; + } + DEBUGF("recv: no padding in payload\n"); + return 0; +} + +/* + * Computes number of padding based on flags. This function returns + * the calculated length if it succeeds, or -1. + */ +static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { + size_t padlen; + + /* 1 for Pad Length field */ + padlen = (size_t)(iframe->sbuf.pos[0] + 1); + + DEBUGF("recv: padlen=%zu\n", padlen); + + /* We cannot use iframe->frame.hd.length because of CONTINUATION */ + if (padlen - 1 > iframe->payloadleft) { + return -1; + } + + iframe->padlen = padlen; + + return (ssize_t)padlen; +} + +/* + * This function returns the effective payload length in the data of + * length |readlen| when the remaning payload is |payloadleft|. The + * |payloadleft| does not include |readlen|. If padding was started + * strictly before this data chunk, this function returns -1. + */ +static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, + size_t payloadleft, + size_t readlen) { + size_t trail_padlen = + nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen); + + if (trail_padlen > payloadleft) { + size_t padlen; + padlen = trail_padlen - payloadleft; + if (readlen < padlen) { + return -1; + } + return (ssize_t)(readlen - padlen); + } + return (ssize_t)(readlen); +} + +ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + size_t inlen) { + const uint8_t *first = in, *last = in + inlen; + nghttp2_inbound_frame *iframe = &session->iframe; + size_t readlen; + ssize_t padlen; + int rv; + int busy = 0; + nghttp2_frame_hd cont_hd; + nghttp2_stream *stream; + size_t pri_fieldlen; + nghttp2_mem *mem; + + mem = &session->mem; + + /* We may have idle streams more than we expect (e.g., + nghttp2_session_change_stream_priority() or + nghttp2_session_create_idle_stream()). Adjust them here. */ + rv = nghttp2_session_adjust_idle_stream(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (!nghttp2_session_want_read(session)) { + return (ssize_t)inlen; + } + + for (;;) { + switch (iframe->state) { + case NGHTTP2_IB_READ_CLIENT_MAGIC: + readlen = nghttp2_min(inlen, iframe->payloadleft); + + if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - + iframe->payloadleft, + in, readlen) != 0) { + return NGHTTP2_ERR_BAD_CLIENT_MAGIC; + } + + iframe->payloadleft -= readlen; + in += readlen; + + if (iframe->payloadleft == 0) { + session_inbound_frame_reset(session); + iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS; + } + + break; + case NGHTTP2_IB_READ_FIRST_SETTINGS: + DEBUGF("recv: [IB_READ_FIRST_SETTINGS]\n"); + + readlen = inbound_frame_buf_read(iframe, in, last); + in += readlen; + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { + return in - first; + } + + if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS || + (iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) { + + iframe->state = NGHTTP2_IB_IGN_ALL; + + rv = session_call_error_callback( + session, NGHTTP2_ERR_SETTINGS_EXPECTED, + "Remote peer returned unexpected data while we expected " + "SETTINGS frame. Perhaps, peer does not support HTTP/2 " + "properly."); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "SETTINGS expected"); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return (ssize_t)inlen; + } + + iframe->state = NGHTTP2_IB_READ_HEAD; + + /* Fall through */ + case NGHTTP2_IB_READ_HEAD: { + int on_begin_frame_called = 0; + + DEBUGF("recv: [IB_READ_HEAD]\n"); + + readlen = inbound_frame_buf_read(iframe, in, last); + in += readlen; + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { + return in - first; + } + + nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos); + iframe->payloadleft = iframe->frame.hd.length; + + DEBUGF("recv: payloadlen=%zu, type=%u, flags=0x%02x, stream_id=%d\n", + iframe->frame.hd.length, iframe->frame.hd.type, + iframe->frame.hd.flags, iframe->frame.hd.stream_id); + + if (iframe->frame.hd.length > session->local_settings.max_frame_size) { + DEBUGF("recv: length is too large %zu > %u\n", iframe->frame.hd.length, + session->local_settings.max_frame_size); + + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size"); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + break; + } + + switch (iframe->frame.hd.type) { + case NGHTTP2_DATA: { + DEBUGF("recv: DATA\n"); + + iframe->frame.hd.flags &= + (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PADDED); + /* Check stream is open. If it is not open or closing, + ignore payload. */ + busy = 1; + + rv = session_on_data_received_fail_fast(session); + if (rv == NGHTTP2_ERR_IGN_PAYLOAD) { + DEBUGF("recv: DATA not allowed stream_id=%d\n", + iframe->frame.hd.stream_id); + iframe->state = NGHTTP2_IB_IGN_DATA; + break; + } + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd); + if (rv < 0) { + iframe->state = NGHTTP2_IB_IGN_DATA; + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, + "DATA: insufficient padding space"); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + break; + } + + if (rv == 1) { + iframe->state = NGHTTP2_IB_READ_PAD_DATA; + break; + } + + iframe->state = NGHTTP2_IB_READ_DATA; + break; + } + case NGHTTP2_HEADERS: + + DEBUGF("recv: HEADERS\n"); + + iframe->frame.hd.flags &= + (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS | + NGHTTP2_FLAG_PADDED | NGHTTP2_FLAG_PRIORITY); + + rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd); + if (rv < 0) { + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, + "HEADERS: insufficient padding space"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + break; + } + + if (rv == 1) { + iframe->state = NGHTTP2_IB_READ_NBYTE; + break; + } + + pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags); + + if (pri_fieldlen > 0) { + if (iframe->payloadleft < pri_fieldlen) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + + inbound_frame_set_mark(iframe, pri_fieldlen); + + break; + } + + /* Call on_begin_frame_callback here because + session_process_headers_frame() may call + on_begin_headers_callback */ + rv = session_call_on_begin_frame(session, &iframe->frame.hd); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + on_begin_frame_called = 1; + + rv = session_process_headers_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK; + + break; + case NGHTTP2_PRIORITY: + DEBUGF("recv: PRIORITY\n"); + + iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; + + if (iframe->payloadleft != NGHTTP2_PRIORITY_SPECLEN) { + busy = 1; + + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + + inbound_frame_set_mark(iframe, NGHTTP2_PRIORITY_SPECLEN); + + break; + case NGHTTP2_RST_STREAM: + case NGHTTP2_WINDOW_UPDATE: +#ifdef DEBUGBUILD + switch (iframe->frame.hd.type) { + case NGHTTP2_RST_STREAM: + DEBUGF("recv: RST_STREAM\n"); + break; + case NGHTTP2_WINDOW_UPDATE: + DEBUGF("recv: WINDOW_UPDATE\n"); + break; + } +#endif /* DEBUGBUILD */ + + iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; + + if (iframe->payloadleft != 4) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + + inbound_frame_set_mark(iframe, 4); + + break; + case NGHTTP2_SETTINGS: + DEBUGF("recv: SETTINGS\n"); + + iframe->frame.hd.flags &= NGHTTP2_FLAG_ACK; + + if ((iframe->frame.hd.length % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) || + ((iframe->frame.hd.flags & NGHTTP2_FLAG_ACK) && + iframe->payloadleft > 0)) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_SETTINGS; + + if (iframe->payloadleft) { + nghttp2_settings_entry *min_header_table_size_entry; + + /* We allocate iv with additional one entry, to store the + minimum header table size. */ + iframe->max_niv = + iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1; + + iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) * + iframe->max_niv); + + if (!iframe->iv) { + return NGHTTP2_ERR_NOMEM; + } + + min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1]; + min_header_table_size_entry->settings_id = + NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; + min_header_table_size_entry->value = UINT32_MAX; + + inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH); + break; + } + + busy = 1; + + inbound_frame_set_mark(iframe, 0); + + break; + case NGHTTP2_PUSH_PROMISE: + DEBUGF("recv: PUSH_PROMISE\n"); + + iframe->frame.hd.flags &= + (NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED); + + rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd); + if (rv < 0) { + busy = 1; + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, + "PUSH_PROMISE: insufficient padding space"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + break; + } + + if (rv == 1) { + iframe->state = NGHTTP2_IB_READ_NBYTE; + break; + } + + if (iframe->payloadleft < 4) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + + inbound_frame_set_mark(iframe, 4); + + break; + case NGHTTP2_PING: + DEBUGF("recv: PING\n"); + + iframe->frame.hd.flags &= NGHTTP2_FLAG_ACK; + + if (iframe->payloadleft != 8) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + inbound_frame_set_mark(iframe, 8); + + break; + case NGHTTP2_GOAWAY: + DEBUGF("recv: GOAWAY\n"); + + iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; + + if (iframe->payloadleft < 8) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + inbound_frame_set_mark(iframe, 8); + + break; + case NGHTTP2_CONTINUATION: + DEBUGF("recv: unexpected CONTINUATION\n"); + + /* Receiving CONTINUATION in this state are subject to + connection error of type PROTOCOL_ERROR */ + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "CONTINUATION: unexpected"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + default: + DEBUGF("recv: extension frame\n"); + + if (check_ext_type_set(session->user_recv_ext_types, + iframe->frame.hd.type)) { + if (!session->callbacks.unpack_extension_callback) { + /* Silently ignore unknown frame type. */ + + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + } + + busy = 1; + + iframe->state = NGHTTP2_IB_READ_EXTENSION_PAYLOAD; + + break; + } else { + switch (iframe->frame.hd.type) { + case NGHTTP2_ALTSVC: + if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == + 0) { + busy = 1; + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + break; + } + + DEBUGF("recv: ALTSVC\n"); + + iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; + iframe->frame.ext.payload = &iframe->ext_frame_payload.altsvc; + + if (session->server) { + busy = 1; + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + break; + } + + if (iframe->payloadleft < 2) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + busy = 1; + + iframe->state = NGHTTP2_IB_READ_NBYTE; + inbound_frame_set_mark(iframe, 2); + + break; + default: + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + } + } + } + + if (!on_begin_frame_called) { + switch (iframe->state) { + case NGHTTP2_IB_IGN_HEADER_BLOCK: + case NGHTTP2_IB_IGN_PAYLOAD: + case NGHTTP2_IB_FRAME_SIZE_ERROR: + case NGHTTP2_IB_IGN_DATA: + break; + default: + rv = session_call_on_begin_frame(session, &iframe->frame.hd); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + } + + break; + } + case NGHTTP2_IB_READ_NBYTE: + DEBUGF("recv: [IB_READ_NBYTE]\n"); + + readlen = inbound_frame_buf_read(iframe, in, last); + in += readlen; + iframe->payloadleft -= readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zd\n", readlen, + iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf)); + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { + return in - first; + } + + switch (iframe->frame.hd.type) { + case NGHTTP2_HEADERS: + if (iframe->padlen == 0 && + (iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) { + padlen = inbound_frame_compute_pad(iframe); + if (padlen < 0) { + busy = 1; + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + break; + } + iframe->frame.headers.padlen = (size_t)padlen; + + pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags); + + if (pri_fieldlen > 0) { + if (iframe->payloadleft < pri_fieldlen) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + iframe->state = NGHTTP2_IB_READ_NBYTE; + inbound_frame_set_mark(iframe, pri_fieldlen); + break; + } else { + /* Truncate buffers used for padding spec */ + inbound_frame_set_mark(iframe, 0); + } + } + + rv = session_process_headers_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK; + + break; + case NGHTTP2_PRIORITY: + rv = session_process_priority_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_RST_STREAM: + rv = session_process_rst_stream_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_PUSH_PROMISE: + if (iframe->padlen == 0 && + (iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) { + padlen = inbound_frame_compute_pad(iframe); + if (padlen < 0) { + busy = 1; + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, + "PUSH_PROMISE: invalid padding"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + break; + } + + iframe->frame.push_promise.padlen = (size_t)padlen; + + if (iframe->payloadleft < 4) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + iframe->state = NGHTTP2_IB_READ_NBYTE; + + inbound_frame_set_mark(iframe, 4); + + break; + } + + rv = session_process_push_promise_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.push_promise.promised_stream_id, + NGHTTP2_INTERNAL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK; + + break; + case NGHTTP2_PING: + rv = session_process_ping_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_GOAWAY: { + size_t debuglen; + + /* 8 is Last-stream-ID + Error Code */ + debuglen = iframe->frame.hd.length - 8; + + if (debuglen > 0) { + iframe->raw_lbuf = nghttp2_mem_malloc(mem, debuglen); + + if (iframe->raw_lbuf == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf, debuglen); + } + + busy = 1; + + iframe->state = NGHTTP2_IB_READ_GOAWAY_DEBUG; + + break; + } + case NGHTTP2_WINDOW_UPDATE: + rv = session_process_window_update_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_ALTSVC: { + size_t origin_len; + + origin_len = nghttp2_get_uint16(iframe->sbuf.pos); + + DEBUGF("recv: origin_len=%zu\n", origin_len); + + if (origin_len > iframe->payloadleft) { + busy = 1; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; + break; + } + + if (iframe->frame.hd.length > 2) { + iframe->raw_lbuf = + nghttp2_mem_malloc(mem, iframe->frame.hd.length - 2); + + if (iframe->raw_lbuf == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf, + iframe->frame.hd.length); + } + + busy = 1; + + iframe->state = NGHTTP2_IB_READ_ALTSVC_PAYLOAD; + + break; + } + default: + /* This is unknown frame */ + session_inbound_frame_reset(session); + + break; + } + break; + case NGHTTP2_IB_READ_HEADER_BLOCK: + case NGHTTP2_IB_IGN_HEADER_BLOCK: { + ssize_t data_readlen; + size_t trail_padlen; + int final; +#ifdef DEBUGBUILD + if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) { + DEBUGF("recv: [IB_READ_HEADER_BLOCK]\n"); + } else { + DEBUGF("recv: [IB_IGN_HEADER_BLOCK]\n"); + } +#endif /* DEBUGBUILD */ + + readlen = inbound_frame_payload_readlen(iframe, in, last); + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft - readlen); + + data_readlen = inbound_frame_effective_readlen( + iframe, iframe->payloadleft - readlen, readlen); + trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen); + + final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) && + iframe->payloadleft - (size_t)data_readlen == trail_padlen; + + if (data_readlen > 0 || (data_readlen == 0 && final)) { + size_t hd_proclen = 0; + + DEBUGF("recv: block final=%d\n", final); + + rv = + inflate_header_block(session, &iframe->frame, &hd_proclen, + (uint8_t *)in, (size_t)data_readlen, final, + iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (rv == NGHTTP2_ERR_PAUSE) { + in += hd_proclen; + iframe->payloadleft -= hd_proclen; + + return in - first; + } + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + /* The application says no more headers. We decompress the + rest of the header block but not invoke on_header_callback + and on_frame_recv_callback. */ + in += hd_proclen; + iframe->payloadleft -= hd_proclen; + + /* Use promised stream ID for PUSH_PROMISE */ + rv = nghttp2_session_add_rst_stream( + session, + iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE + ? iframe->frame.push_promise.promised_stream_id + : iframe->frame.hd.stream_id, + NGHTTP2_INTERNAL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + busy = 1; + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + break; + } + + in += readlen; + iframe->payloadleft -= readlen; + + if (rv == NGHTTP2_ERR_HEADER_COMP) { + /* GOAWAY is already issued */ + if (iframe->payloadleft == 0) { + session_inbound_frame_reset(session); + } else { + busy = 1; + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + } + break; + } + } else { + in += readlen; + iframe->payloadleft -= readlen; + } + + if (iframe->payloadleft) { + break; + } + + if ((iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) { + + inbound_frame_set_mark(iframe, NGHTTP2_FRAME_HDLEN); + + iframe->padlen = 0; + + if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) { + iframe->state = NGHTTP2_IB_EXPECT_CONTINUATION; + } else { + iframe->state = NGHTTP2_IB_IGN_CONTINUATION; + } + } else { + if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) { + rv = session_after_header_block_received(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + session_inbound_frame_reset(session); + } + break; + } + case NGHTTP2_IB_IGN_PAYLOAD: + DEBUGF("recv: [IB_IGN_PAYLOAD]\n"); + + readlen = inbound_frame_payload_readlen(iframe, in, last); + iframe->payloadleft -= readlen; + in += readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (iframe->payloadleft) { + break; + } + + switch (iframe->frame.hd.type) { + case NGHTTP2_HEADERS: + case NGHTTP2_PUSH_PROMISE: + case NGHTTP2_CONTINUATION: + /* Mark inflater bad so that we won't perform further decoding */ + session->hd_inflater.ctx.bad = 1; + break; + default: + break; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_IB_FRAME_SIZE_ERROR: + DEBUGF("recv: [IB_FRAME_SIZE_ERROR]\n"); + + rv = session_handle_frame_size_error(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + case NGHTTP2_IB_READ_SETTINGS: + DEBUGF("recv: [IB_READ_SETTINGS]\n"); + + readlen = inbound_frame_buf_read(iframe, in, last); + iframe->payloadleft -= readlen; + in += readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { + break; + } + + if (readlen > 0) { + inbound_frame_set_settings_entry(iframe); + } + if (iframe->payloadleft) { + inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH); + break; + } + + rv = session_process_settings_frame(session); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_IB_READ_GOAWAY_DEBUG: + DEBUGF("recv: [IB_READ_GOAWAY_DEBUG]\n"); + + readlen = inbound_frame_payload_readlen(iframe, in, last); + + if (readlen > 0) { + iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen); + + iframe->payloadleft -= readlen; + in += readlen; + } + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (iframe->payloadleft) { + assert(nghttp2_buf_avail(&iframe->lbuf) > 0); + + break; + } + + rv = session_process_goaway_frame(session); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_IB_EXPECT_CONTINUATION: + case NGHTTP2_IB_IGN_CONTINUATION: +#ifdef DEBUGBUILD + if (iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) { + fprintf(stderr, "recv: [IB_EXPECT_CONTINUATION]\n"); + } else { + fprintf(stderr, "recv: [IB_IGN_CONTINUATION]\n"); + } +#endif /* DEBUGBUILD */ + + readlen = inbound_frame_buf_read(iframe, in, last); + in += readlen; + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { + return in - first; + } + + nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos); + iframe->payloadleft = cont_hd.length; + + DEBUGF("recv: payloadlen=%zu, type=%u, flags=0x%02x, stream_id=%d\n", + cont_hd.length, cont_hd.type, cont_hd.flags, cont_hd.stream_id); + + if (cont_hd.type != NGHTTP2_CONTINUATION || + cont_hd.stream_id != iframe->frame.hd.stream_id) { + DEBUGF("recv: expected stream_id=%d, type=%d, but got stream_id=%d, " + "type=%u\n", + iframe->frame.hd.stream_id, NGHTTP2_CONTINUATION, + cont_hd.stream_id, cont_hd.type); + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, + "unexpected non-CONTINUATION frame or stream_id is invalid"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + } + + /* CONTINUATION won't bear NGHTTP2_PADDED flag */ + + iframe->frame.hd.flags = (uint8_t)( + iframe->frame.hd.flags | (cont_hd.flags & NGHTTP2_FLAG_END_HEADERS)); + iframe->frame.hd.length += cont_hd.length; + + busy = 1; + + if (iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) { + iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK; + + rv = session_call_on_begin_frame(session, &cont_hd); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } else { + iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; + } + + break; + case NGHTTP2_IB_READ_PAD_DATA: + DEBUGF("recv: [IB_READ_PAD_DATA]\n"); + + readlen = inbound_frame_buf_read(iframe, in, last); + in += readlen; + iframe->payloadleft -= readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen, + iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf)); + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { + return in - first; + } + + /* Pad Length field is subject to flow control */ + rv = session_update_recv_connection_window_size(session, readlen); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + /* Pad Length field is consumed immediately */ + rv = + nghttp2_session_consume(session, iframe->frame.hd.stream_id, readlen); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id); + if (stream) { + rv = session_update_recv_stream_window_size( + session, stream, readlen, + iframe->payloadleft || + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + busy = 1; + + padlen = inbound_frame_compute_pad(iframe); + if (padlen < 0) { + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "DATA: invalid padding"); + if (nghttp2_is_fatal(rv)) { + return rv; + } + iframe->state = NGHTTP2_IB_IGN_DATA; + break; + } + + iframe->frame.data.padlen = (size_t)padlen; + + iframe->state = NGHTTP2_IB_READ_DATA; + + break; + case NGHTTP2_IB_READ_DATA: + stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id); + + if (!stream) { + busy = 1; + iframe->state = NGHTTP2_IB_IGN_DATA; + break; + } + + DEBUGF("recv: [IB_READ_DATA]\n"); + + readlen = inbound_frame_payload_readlen(iframe, in, last); + iframe->payloadleft -= readlen; + in += readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (readlen > 0) { + ssize_t data_readlen; + + rv = session_update_recv_connection_window_size(session, readlen); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + rv = session_update_recv_stream_window_size( + session, stream, readlen, + iframe->payloadleft || + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + data_readlen = inbound_frame_effective_readlen( + iframe, iframe->payloadleft, readlen); + + if (data_readlen == -1) { + /* everything is padding */ + data_readlen = 0; + } + + padlen = (ssize_t)readlen - data_readlen; + + if (padlen > 0) { + /* Padding is considered as "consumed" immediately */ + rv = nghttp2_session_consume(session, iframe->frame.hd.stream_id, + (size_t)padlen); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + DEBUGF("recv: data_readlen=%zd\n", data_readlen); + + if (data_readlen > 0) { + if (session_enforce_http_messaging(session)) { + if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) { + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { + /* Consume all data for connection immediately here */ + rv = session_update_connection_consumed_size( + session, (size_t)data_readlen); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + + rv = nghttp2_session_add_rst_stream( + session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); + if (nghttp2_is_fatal(rv)) { + return rv; + } + busy = 1; + iframe->state = NGHTTP2_IB_IGN_DATA; + break; + } + } + if (session->callbacks.on_data_chunk_recv_callback) { + rv = session->callbacks.on_data_chunk_recv_callback( + session, iframe->frame.hd.flags, iframe->frame.hd.stream_id, + in - readlen, (size_t)data_readlen, session->user_data); + if (rv == NGHTTP2_ERR_PAUSE) { + return in - first; + } + + if (nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + } + } + + if (iframe->payloadleft) { + break; + } + + rv = session_process_data_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_IB_IGN_DATA: + DEBUGF("recv: [IB_IGN_DATA]\n"); + + readlen = inbound_frame_payload_readlen(iframe, in, last); + iframe->payloadleft -= readlen; + in += readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (readlen > 0) { + /* Update connection-level flow control window for ignored + DATA frame too */ + rv = session_update_recv_connection_window_size(session, readlen); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { + + /* Ignored DATA is considered as "consumed" immediately. */ + rv = session_update_connection_consumed_size(session, readlen); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + } + + if (iframe->payloadleft) { + break; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_IB_IGN_ALL: + return (ssize_t)inlen; + case NGHTTP2_IB_READ_EXTENSION_PAYLOAD: + DEBUGF("recv: [IB_READ_EXTENSION_PAYLOAD]\n"); + + readlen = inbound_frame_payload_readlen(iframe, in, last); + iframe->payloadleft -= readlen; + in += readlen; + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (readlen > 0) { + rv = session_call_on_extension_chunk_recv_callback( + session, in - readlen, readlen); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + if (rv != 0) { + busy = 1; + + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + + break; + } + } + + if (iframe->payloadleft > 0) { + break; + } + + rv = session_process_extension_frame(session); + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + case NGHTTP2_IB_READ_ALTSVC_PAYLOAD: + DEBUGF("recv: [IB_READ_ALTSVC_PAYLOAD]\n"); + + readlen = inbound_frame_payload_readlen(iframe, in, last); + + if (readlen > 0) { + iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen); + + iframe->payloadleft -= readlen; + in += readlen; + } + + DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen, + iframe->payloadleft); + + if (iframe->payloadleft) { + assert(nghttp2_buf_avail(&iframe->lbuf) > 0); + + break; + } + + rv = session_process_altsvc_frame(session); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + session_inbound_frame_reset(session); + + break; + } + + if (!busy && in == last) { + break; + } + + busy = 0; + } + + assert(in == last); + + return in - first; +} + +int nghttp2_session_recv(nghttp2_session *session) { + uint8_t buf[NGHTTP2_INBOUND_BUFFER_LENGTH]; + while (1) { + ssize_t readlen; + readlen = session_recv(session, buf, sizeof(buf)); + if (readlen > 0) { + ssize_t proclen = nghttp2_session_mem_recv(session, buf, (size_t)readlen); + if (proclen < 0) { + return (int)proclen; + } + assert(proclen == readlen); + } else if (readlen == 0 || readlen == NGHTTP2_ERR_WOULDBLOCK) { + return 0; + } else if (readlen == NGHTTP2_ERR_EOF) { + return NGHTTP2_ERR_EOF; + } else if (readlen < 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } +} + +/* + * Returns the number of active streams, which includes streams in + * reserved state. + */ +static size_t session_get_num_active_streams(nghttp2_session *session) { + return nghttp2_map_size(&session->streams) - session->num_closed_streams - + session->num_idle_streams; +} + +int nghttp2_session_want_read(nghttp2_session *session) { + size_t num_active_streams; + + /* If this flag is set, we don't want to read. The application + should drop the connection. */ + if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) { + return 0; + } + + num_active_streams = session_get_num_active_streams(session); + + /* Unless termination GOAWAY is sent or received, we always want to + read incoming frames. */ + + if (num_active_streams > 0) { + return 1; + } + + /* If there is no active streams and GOAWAY has been sent or + received, we are done with this session. */ + return (session->goaway_flags & + (NGHTTP2_GOAWAY_SENT | NGHTTP2_GOAWAY_RECV)) == 0; +} + +int nghttp2_session_want_write(nghttp2_session *session) { + /* If these flag is set, we don't want to write any data. The + application should drop the connection. */ + if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) { + return 0; + } + + /* + * Unless termination GOAWAY is sent or received, we want to write + * frames if there is pending ones. If pending frame is request/push + * response HEADERS and concurrent stream limit is reached, we don't + * want to write them. + */ + return session->aob.item || nghttp2_outbound_queue_top(&session->ob_urgent) || + nghttp2_outbound_queue_top(&session->ob_reg) || + (!nghttp2_pq_empty(&session->root.obq) && + session->remote_window_size > 0) || + (nghttp2_outbound_queue_top(&session->ob_syn) && + !session_is_outgoing_concurrent_streams_max(session)); +} + +int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags, + const uint8_t *opaque_data) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_mem *mem; + + mem = &session->mem; + + if ((flags & NGHTTP2_FLAG_ACK) && + session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) { + return NGHTTP2_ERR_FLOODED; + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + + nghttp2_frame_ping_init(&frame->ping, flags, opaque_data); + + rv = nghttp2_session_add_item(session, item); + + if (rv != 0) { + nghttp2_frame_ping_free(&frame->ping); + nghttp2_mem_free(mem, item); + return rv; + } + + if (flags & NGHTTP2_FLAG_ACK) { + ++session->obq_flood_counter_; + } + + return 0; +} + +int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id, + uint32_t error_code, const uint8_t *opaque_data, + size_t opaque_data_len, uint8_t aux_flags) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + uint8_t *opaque_data_copy = NULL; + nghttp2_goaway_aux_data *aux_data; + nghttp2_mem *mem; + + mem = &session->mem; + + if (nghttp2_session_is_my_stream_id(session, last_stream_id)) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (opaque_data_len) { + if (opaque_data_len + 8 > NGHTTP2_MAX_PAYLOADLEN) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + opaque_data_copy = nghttp2_mem_malloc(mem, opaque_data_len); + if (opaque_data_copy == NULL) { + return NGHTTP2_ERR_NOMEM; + } + memcpy(opaque_data_copy, opaque_data, opaque_data_len); + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + nghttp2_mem_free(mem, opaque_data_copy); + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + + /* last_stream_id must not be increased from the value previously + sent */ + last_stream_id = nghttp2_min(last_stream_id, session->local_last_stream_id); + + nghttp2_frame_goaway_init(&frame->goaway, last_stream_id, error_code, + opaque_data_copy, opaque_data_len); + + aux_data = &item->aux_data.goaway; + aux_data->flags = aux_flags; + + rv = nghttp2_session_add_item(session, item); + if (rv != 0) { + nghttp2_frame_goaway_free(&frame->goaway, mem); + nghttp2_mem_free(mem, item); + return rv; + } + return 0; +} + +int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + int32_t window_size_increment) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_mem *mem; + + mem = &session->mem; + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + + nghttp2_frame_window_update_init(&frame->window_update, flags, stream_id, + window_size_increment); + + rv = nghttp2_session_add_item(session, item); + + if (rv != 0) { + nghttp2_frame_window_update_free(&frame->window_update); + nghttp2_mem_free(mem, item); + return rv; + } + return 0; +} + +static void +session_append_inflight_settings(nghttp2_session *session, + nghttp2_inflight_settings *settings) { + nghttp2_inflight_settings **i; + + for (i = &session->inflight_settings_head; *i; i = &(*i)->next) + ; + + *i = settings; +} + +int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags, + const nghttp2_settings_entry *iv, size_t niv) { + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_settings_entry *iv_copy; + size_t i; + int rv; + nghttp2_mem *mem; + nghttp2_inflight_settings *inflight_settings = NULL; + + mem = &session->mem; + + if (flags & NGHTTP2_FLAG_ACK) { + if (niv != 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) { + return NGHTTP2_ERR_FLOODED; + } + } + + if (!nghttp2_iv_check(iv, niv)) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + if (niv > 0) { + iv_copy = nghttp2_frame_iv_copy(iv, niv, mem); + if (iv_copy == NULL) { + nghttp2_mem_free(mem, item); + return NGHTTP2_ERR_NOMEM; + } + } else { + iv_copy = NULL; + } + + if ((flags & NGHTTP2_FLAG_ACK) == 0) { + rv = inflight_settings_new(&inflight_settings, iv, niv, mem); + if (rv != 0) { + assert(nghttp2_is_fatal(rv)); + nghttp2_mem_free(mem, iv_copy); + nghttp2_mem_free(mem, item); + return rv; + } + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + + nghttp2_frame_settings_init(&frame->settings, flags, iv_copy, niv); + rv = nghttp2_session_add_item(session, item); + if (rv != 0) { + /* The only expected error is fatal one */ + assert(nghttp2_is_fatal(rv)); + + inflight_settings_del(inflight_settings, mem); + + nghttp2_frame_settings_free(&frame->settings, mem); + nghttp2_mem_free(mem, item); + + return rv; + } + + if (flags & NGHTTP2_FLAG_ACK) { + ++session->obq_flood_counter_; + } else { + session_append_inflight_settings(session, inflight_settings); + } + + /* Extract NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS and ENABLE_PUSH + here. We use it to refuse the incoming stream and PUSH_PROMISE + with RST_STREAM. */ + + for (i = niv; i > 0; --i) { + if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) { + session->pending_local_max_concurrent_stream = iv[i - 1].value; + break; + } + } + + for (i = niv; i > 0; --i) { + if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_PUSH) { + session->pending_enable_push = (uint8_t)iv[i - 1].value; + break; + } + } + + return 0; +} + +int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, + size_t datamax, nghttp2_frame *frame, + nghttp2_data_aux_data *aux_data, + nghttp2_stream *stream) { + int rv; + uint32_t data_flags; + ssize_t payloadlen; + ssize_t padded_payloadlen; + nghttp2_buf *buf; + size_t max_payloadlen; + + assert(bufs->head == bufs->cur); + + buf = &bufs->cur->buf; + + if (session->callbacks.read_length_callback) { + + payloadlen = session->callbacks.read_length_callback( + session, frame->hd.type, stream->stream_id, session->remote_window_size, + stream->remote_window_size, session->remote_settings.max_frame_size, + session->user_data); + + DEBUGF("send: read_length_callback=%zd\n", payloadlen); + + payloadlen = nghttp2_session_enforce_flow_control_limits(session, stream, + payloadlen); + + DEBUGF("send: read_length_callback after flow control=%zd\n", payloadlen); + + if (payloadlen <= 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + if ((size_t)payloadlen > nghttp2_buf_avail(buf)) { + /* Resize the current buffer(s). The reason why we do +1 for + buffer size is for possible padding field. */ + rv = nghttp2_bufs_realloc(&session->aob.framebufs, + (size_t)(NGHTTP2_FRAME_HDLEN + 1 + payloadlen)); + + if (rv != 0) { + DEBUGF("send: realloc buffer failed rv=%d", rv); + /* If reallocation failed, old buffers are still in tact. So + use safe limit. */ + payloadlen = (ssize_t)datamax; + + DEBUGF("send: use safe limit payloadlen=%zd", payloadlen); + } else { + assert(&session->aob.framebufs == bufs); + + buf = &bufs->cur->buf; + } + } + datamax = (size_t)payloadlen; + } + + /* Current max DATA length is less then buffer chunk size */ + assert(nghttp2_buf_avail(buf) >= datamax); + + data_flags = NGHTTP2_DATA_FLAG_NONE; + payloadlen = aux_data->data_prd.read_callback( + session, frame->hd.stream_id, buf->pos, datamax, &data_flags, + &aux_data->data_prd.source, session->user_data); + + if (payloadlen == NGHTTP2_ERR_DEFERRED || + payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE || + payloadlen == NGHTTP2_ERR_PAUSE) { + DEBUGF("send: DATA postponed due to %s\n", + nghttp2_strerror((int)payloadlen)); + + return (int)payloadlen; + } + + if (payloadlen < 0 || datamax < (size_t)payloadlen) { + /* This is the error code when callback is failed. */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + + buf->last = buf->pos + payloadlen; + buf->pos -= NGHTTP2_FRAME_HDLEN; + + /* Clear flags, because this may contain previous flags of previous + DATA */ + frame->hd.flags = NGHTTP2_FLAG_NONE; + + if (data_flags & NGHTTP2_DATA_FLAG_EOF) { + aux_data->eof = 1; + /* If NGHTTP2_DATA_FLAG_NO_END_STREAM is set, don't set + NGHTTP2_FLAG_END_STREAM */ + if ((aux_data->flags & NGHTTP2_FLAG_END_STREAM) && + (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM) == 0) { + frame->hd.flags |= NGHTTP2_FLAG_END_STREAM; + } + } + + if (data_flags & NGHTTP2_DATA_FLAG_NO_COPY) { + if (session->callbacks.send_data_callback == NULL) { + DEBUGF("NGHTTP2_DATA_FLAG_NO_COPY requires send_data_callback set\n"); + + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + aux_data->no_copy = 1; + } + + frame->hd.length = (size_t)payloadlen; + frame->data.padlen = 0; + + max_payloadlen = nghttp2_min(datamax, frame->hd.length + NGHTTP2_MAX_PADLEN); + + padded_payloadlen = + session_call_select_padding(session, frame, max_payloadlen); + + if (nghttp2_is_fatal((int)padded_payloadlen)) { + return (int)padded_payloadlen; + } + + frame->data.padlen = (size_t)(padded_payloadlen - payloadlen); + + nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); + + rv = nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen, + aux_data->no_copy); + if (rv != 0) { + return rv; + } + + reschedule_stream(stream); + + if (frame->hd.length == 0 && (data_flags & NGHTTP2_DATA_FLAG_EOF) && + (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM)) { + /* DATA payload length is 0, and DATA frame does not bear + END_STREAM. In this case, there is no point to send 0 length + DATA frame. */ + return NGHTTP2_ERR_CANCEL; + } + + return 0; +} + +void *nghttp2_session_get_stream_user_data(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + stream = nghttp2_session_get_stream(session, stream_id); + if (stream) { + return stream->stream_user_data; + } else { + return NULL; + } +} + +int nghttp2_session_set_stream_user_data(nghttp2_session *session, + int32_t stream_id, + void *stream_user_data) { + nghttp2_stream *stream; + stream = nghttp2_session_get_stream(session, stream_id); + if (!stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + stream->stream_user_data = stream_user_data; + return 0; +} + +int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) { + int rv; + nghttp2_stream *stream; + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL || !nghttp2_stream_check_deferred_item(stream)) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + rv = nghttp2_stream_resume_deferred_item(stream, + NGHTTP2_STREAM_FLAG_DEFERRED_USER); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; +} + +size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session) { + return nghttp2_outbound_queue_size(&session->ob_urgent) + + nghttp2_outbound_queue_size(&session->ob_reg) + + nghttp2_outbound_queue_size(&session->ob_syn); + /* TODO account for item attached to stream */ +} + +int32_t +nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { + return -1; + } + return stream->recv_window_size < 0 ? 0 : stream->recv_window_size; +} + +int32_t +nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { + return -1; + } + return stream->local_window_size; +} + +int32_t nghttp2_session_get_stream_local_window_size(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + int32_t size; + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { + return -1; + } + + size = stream->local_window_size - stream->recv_window_size; + + /* size could be negative if local endpoint reduced + SETTINGS_INITIAL_WINDOW_SIZE */ + if (size < 0) { + return 0; + } + + return size; +} + +int32_t +nghttp2_session_get_effective_recv_data_length(nghttp2_session *session) { + return session->recv_window_size < 0 ? 0 : session->recv_window_size; +} + +int32_t +nghttp2_session_get_effective_local_window_size(nghttp2_session *session) { + return session->local_window_size; +} + +int32_t nghttp2_session_get_local_window_size(nghttp2_session *session) { + return session->local_window_size - session->recv_window_size; +} + +int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + + stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { + return -1; + } + + /* stream->remote_window_size can be negative when + SETTINGS_INITIAL_WINDOW_SIZE is changed. */ + return nghttp2_max(0, stream->remote_window_size); +} + +int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session) { + return session->remote_window_size; +} + +uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session, + nghttp2_settings_id id) { + switch (id) { + case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + return session->remote_settings.header_table_size; + case NGHTTP2_SETTINGS_ENABLE_PUSH: + return session->remote_settings.enable_push; + case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: + return session->remote_settings.max_concurrent_streams; + case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: + return session->remote_settings.initial_window_size; + case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: + return session->remote_settings.max_frame_size; + case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: + return session->remote_settings.max_header_list_size; + } + + assert(0); + abort(); /* if NDEBUG is set */ +} + +uint32_t nghttp2_session_get_local_settings(nghttp2_session *session, + nghttp2_settings_id id) { + switch (id) { + case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + return session->local_settings.header_table_size; + case NGHTTP2_SETTINGS_ENABLE_PUSH: + return session->local_settings.enable_push; + case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: + return session->local_settings.max_concurrent_streams; + case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: + return session->local_settings.initial_window_size; + case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: + return session->local_settings.max_frame_size; + case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: + return session->local_settings.max_header_list_size; + } + + assert(0); + abort(); /* if NDEBUG is set */ +} + +static int nghttp2_session_upgrade_internal(nghttp2_session *session, + const uint8_t *settings_payload, + size_t settings_payloadlen, + void *stream_user_data) { + nghttp2_stream *stream; + nghttp2_frame frame; + nghttp2_settings_entry *iv; + size_t niv; + int rv; + nghttp2_priority_spec pri_spec; + nghttp2_mem *mem; + + mem = &session->mem; + + if ((!session->server && session->next_stream_id != 1) || + (session->server && session->last_recv_stream_id >= 1)) { + return NGHTTP2_ERR_PROTO; + } + if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload, + settings_payloadlen, mem); + if (rv != 0) { + return rv; + } + + if (session->server) { + nghttp2_frame_hd_init(&frame.hd, settings_payloadlen, NGHTTP2_SETTINGS, + NGHTTP2_FLAG_NONE, 0); + frame.settings.iv = iv; + frame.settings.niv = niv; + rv = nghttp2_session_on_settings_received(session, &frame, 1 /* No ACK */); + } else { + rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, niv); + } + nghttp2_mem_free(mem, iv); + if (rv != 0) { + return rv; + } + + nghttp2_priority_spec_default_init(&pri_spec); + + stream = nghttp2_session_open_stream( + session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_OPENING, + session->server ? NULL : stream_user_data); + if (stream == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + /* We don't call nghttp2_session_adjust_closed_stream(), since this + should be the first stream open. */ + + if (session->server) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + session->last_recv_stream_id = 1; + session->last_proc_stream_id = 1; + } else { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); + session->last_sent_stream_id = 1; + session->next_stream_id += 2; + } + return 0; +} + +int nghttp2_session_upgrade(nghttp2_session *session, + const uint8_t *settings_payload, + size_t settings_payloadlen, + void *stream_user_data) { + int rv; + nghttp2_stream *stream; + + rv = nghttp2_session_upgrade_internal(session, settings_payload, + settings_payloadlen, stream_user_data); + if (rv != 0) { + return rv; + } + + stream = nghttp2_session_get_stream(session, 1); + assert(stream); + + /* We have no information about request header fields when Upgrade + was happened. So we don't know the request method here. If + request method is HEAD, we have a trouble because we may have + nonzero content-length header field in response headers, and we + will going to check it against the actual DATA frames, but we may + get mismatch because HEAD response body must be empty. Because + of this reason, nghttp2_session_upgrade() was deprecated in favor + of nghttp2_session_upgrade2(), which has |head_request| parameter + to indicate that request method is HEAD or not. */ + stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND; + return 0; +} + +int nghttp2_session_upgrade2(nghttp2_session *session, + const uint8_t *settings_payload, + size_t settings_payloadlen, int head_request, + void *stream_user_data) { + int rv; + nghttp2_stream *stream; + + rv = nghttp2_session_upgrade_internal(session, settings_payload, + settings_payloadlen, stream_user_data); + if (rv != 0) { + return rv; + } + + stream = nghttp2_session_get_stream(session, 1); + assert(stream); + + if (head_request) { + stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; + } + + return 0; +} + +int nghttp2_session_get_stream_local_close(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + + stream = nghttp2_session_get_stream(session, stream_id); + + if (!stream) { + return -1; + } + + return (stream->shut_flags & NGHTTP2_SHUT_WR) != 0; +} + +int nghttp2_session_get_stream_remote_close(nghttp2_session *session, + int32_t stream_id) { + nghttp2_stream *stream; + + stream = nghttp2_session_get_stream(session, stream_id); + + if (!stream) { + return -1; + } + + return (stream->shut_flags & NGHTTP2_SHUT_RD) != 0; +} + +int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id, + size_t size) { + int rv; + nghttp2_stream *stream; + + if (stream_id == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { + return NGHTTP2_ERR_INVALID_STATE; + } + + rv = session_update_connection_consumed_size(session, size); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + stream = nghttp2_session_get_stream(session, stream_id); + + if (!stream) { + return 0; + } + + rv = session_update_stream_consumed_size(session, stream, size); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; +} + +int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) { + int rv; + + if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { + return NGHTTP2_ERR_INVALID_STATE; + } + + rv = session_update_connection_consumed_size(session, size); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; +} + +int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, + size_t size) { + int rv; + nghttp2_stream *stream; + + if (stream_id == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { + return NGHTTP2_ERR_INVALID_STATE; + } + + stream = nghttp2_session_get_stream(session, stream_id); + + if (!stream) { + return 0; + } + + rv = session_update_stream_consumed_size(session, stream, size); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + return 0; +} + +int nghttp2_session_set_next_stream_id(nghttp2_session *session, + int32_t next_stream_id) { + if (next_stream_id <= 0 || + session->next_stream_id > (uint32_t)next_stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (session->server) { + if (next_stream_id % 2) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + } else if (next_stream_id % 2 == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + session->next_stream_id = (uint32_t)next_stream_id; + return 0; +} + +uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) { + return session->next_stream_id; +} + +int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) { + return session->last_proc_stream_id; +} + +nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session, + int32_t stream_id) { + if (stream_id == 0) { + return &session->root; + } + + return nghttp2_session_get_stream_raw(session, stream_id); +} + +nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) { + return &session->root; +} + +int nghttp2_session_check_server_session(nghttp2_session *session) { + return session->server; +} + +int nghttp2_session_change_stream_priority( + nghttp2_session *session, int32_t stream_id, + const nghttp2_priority_spec *pri_spec) { + int rv; + nghttp2_stream *stream; + nghttp2_priority_spec pri_spec_copy; + + if (stream_id == 0 || stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + stream = nghttp2_session_get_stream_raw(session, stream_id); + if (!stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + pri_spec_copy = *pri_spec; + nghttp2_priority_spec_normalize_weight(&pri_spec_copy); + + rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec_copy); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + /* We don't intentionally call nghttp2_session_adjust_idle_stream() + so that idle stream created by this function, and existing ones + are kept for application. We will adjust number of idle stream + in nghttp2_session_mem_send or nghttp2_session_mem_recv is + called. */ + return 0; +} + +int nghttp2_session_create_idle_stream(nghttp2_session *session, + int32_t stream_id, + const nghttp2_priority_spec *pri_spec) { + nghttp2_stream *stream; + nghttp2_priority_spec pri_spec_copy; + + if (stream_id == 0 || stream_id == pri_spec->stream_id || + !session_detect_idle_stream(session, stream_id)) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + stream = nghttp2_session_get_stream_raw(session, stream_id); + if (stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + pri_spec_copy = *pri_spec; + nghttp2_priority_spec_normalize_weight(&pri_spec_copy); + + stream = + nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_copy, NGHTTP2_STREAM_IDLE, NULL); + if (!stream) { + return NGHTTP2_ERR_NOMEM; + } + + /* We don't intentionally call nghttp2_session_adjust_idle_stream() + so that idle stream created by this function, and existing ones + are kept for application. We will adjust number of idle stream + in nghttp2_session_mem_send or nghttp2_session_mem_recv is + called. */ + return 0; +} + +size_t +nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session) { + return nghttp2_hd_inflate_get_dynamic_table_size(&session->hd_inflater); +} + +size_t +nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) { + return nghttp2_hd_deflate_get_dynamic_table_size(&session->hd_deflater); +} + +void nghttp2_session_set_user_data(nghttp2_session *session, void *user_data) { + session->user_data = user_data; +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_session.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_session.h new file mode 100644 index 0000000..c67781f --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_session.h @@ -0,0 +1,860 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_SESSION_H +#define NGHTTP2_SESSION_H + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" +#include "nghttp2_map.h" +#include "nghttp2_frame.h" +#include "nghttp2_hd.h" +#include "nghttp2_stream.h" +#include "nghttp2_outbound_item.h" +#include "nghttp2_int.h" +#include "nghttp2_buf.h" +#include "nghttp2_callbacks.h" +#include "nghttp2_mem.h" + +/* The global variable for tests where we want to disable strict + preface handling. */ +extern int nghttp2_enable_strict_preface; + +/* + * Option flags. + */ +typedef enum { + NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0, + NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1, + NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2, + NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3, + NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4 +} nghttp2_optmask; + +/* + * bitmask for built-in type to enable the default handling for that + * type of the frame. + */ +typedef enum { + NGHTTP2_TYPEMASK_NONE = 0, + NGHTTP2_TYPEMASK_ALTSVC = 1 << 0 +} nghttp2_typemask; + +typedef enum { + NGHTTP2_OB_POP_ITEM, + NGHTTP2_OB_SEND_DATA, + NGHTTP2_OB_SEND_NO_COPY, + NGHTTP2_OB_SEND_CLIENT_MAGIC +} nghttp2_outbound_state; + +typedef struct { + nghttp2_outbound_item *item; + nghttp2_bufs framebufs; + nghttp2_outbound_state state; +} nghttp2_active_outbound_item; + +/* Buffer length for inbound raw byte stream used in + nghttp2_session_recv(). */ +#define NGHTTP2_INBOUND_BUFFER_LENGTH HTTP2_RECV_BUFFER_LENGHT + +/* The default maximum number of incoming reserved streams */ +#define NGHTTP2_MAX_INCOMING_RESERVED_STREAMS 200 + +/* Even if we have less SETTINGS_MAX_CONCURRENT_STREAMS than this + number, we keep NGHTTP2_MIN_IDLE_STREAMS streams in idle state */ +#define NGHTTP2_MIN_IDLE_STREAMS 16 + +/* The maximum number of items in outbound queue, which is considered + as flooding caused by peer. All frames are not considered here. + We only consider PING + ACK and SETTINGS + ACK. This is because + they both are response to the frame initiated by peer and peer can + send as many of them as they want. If peer does not read network, + response frames are stacked up, which leads to memory exhaustion. + The value selected here is arbitrary, but safe value and if we have + these frames in this number, it is considered suspicious. */ +#define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000 + +/* The default value of maximum number of concurrent streams. */ +#define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu + +/* Internal state when receiving incoming frame */ +typedef enum { + /* Receiving frame header */ + NGHTTP2_IB_READ_CLIENT_MAGIC, + NGHTTP2_IB_READ_FIRST_SETTINGS, + NGHTTP2_IB_READ_HEAD, + NGHTTP2_IB_READ_NBYTE, + NGHTTP2_IB_READ_HEADER_BLOCK, + NGHTTP2_IB_IGN_HEADER_BLOCK, + NGHTTP2_IB_IGN_PAYLOAD, + NGHTTP2_IB_FRAME_SIZE_ERROR, + NGHTTP2_IB_READ_SETTINGS, + NGHTTP2_IB_READ_GOAWAY_DEBUG, + NGHTTP2_IB_EXPECT_CONTINUATION, + NGHTTP2_IB_IGN_CONTINUATION, + NGHTTP2_IB_READ_PAD_DATA, + NGHTTP2_IB_READ_DATA, + NGHTTP2_IB_IGN_DATA, + NGHTTP2_IB_IGN_ALL, + NGHTTP2_IB_READ_ALTSVC_PAYLOAD, + NGHTTP2_IB_READ_EXTENSION_PAYLOAD +} nghttp2_inbound_state; + +typedef struct { + 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; + /* The received SETTINGS entry. For the standard settings entries, + we only keep the last seen value. For + SETTINGS_HEADER_TABLE_SIZE, we also keep minimum value in the + last index. */ + nghttp2_settings_entry *iv; + /* buffer pointers to small buffer, raw_sbuf */ + nghttp2_buf sbuf; + /* buffer pointers to large buffer, raw_lbuf */ + nghttp2_buf lbuf; + /* Large buffer, malloced on demand */ + uint8_t *raw_lbuf; + /* The number of entry filled in |iv| */ + size_t niv; + /* The number of entries |iv| can store. */ + size_t max_niv; + /* How many bytes we still need to receive for current frame */ + size_t payloadleft; + /* padding length for the current frame */ + size_t padlen; + nghttp2_inbound_state state; + /* Small buffer. Currently the largest contiguous chunk to buffer + is frame header. We buffer part of payload, but they are smaller + than frame header. */ + uint8_t raw_sbuf[NGHTTP2_FRAME_HDLEN]; +} nghttp2_inbound_frame; + +typedef struct { + uint32_t header_table_size; + uint32_t enable_push; + uint32_t max_concurrent_streams; + uint32_t initial_window_size; + uint32_t max_frame_size; + uint32_t max_header_list_size; +} nghttp2_settings_storage; + +typedef enum { + NGHTTP2_GOAWAY_NONE = 0, + /* Flag means that connection should be terminated after sending GOAWAY. */ + NGHTTP2_GOAWAY_TERM_ON_SEND = 0x1, + /* Flag means GOAWAY to terminate session has been sent */ + NGHTTP2_GOAWAY_TERM_SENT = 0x2, + /* Flag means GOAWAY was sent */ + NGHTTP2_GOAWAY_SENT = 0x4, + /* Flag means GOAWAY was received */ + NGHTTP2_GOAWAY_RECV = 0x8 +} nghttp2_goaway_flag; + +/* nghttp2_inflight_settings stores the SETTINGS entries which local + endpoint has sent to the remote endpoint, and has not received ACK + yet. */ +struct nghttp2_inflight_settings { + struct nghttp2_inflight_settings *next; + nghttp2_settings_entry *iv; + size_t niv; +}; + +typedef struct nghttp2_inflight_settings nghttp2_inflight_settings; + +struct nghttp2_session { + nghttp2_map /* */ streams; + /* root of dependency tree*/ + nghttp2_stream root; + /* Queue for outbound urgent frames (PING and SETTINGS) */ + nghttp2_outbound_queue ob_urgent; + /* Queue for non-DATA frames */ + nghttp2_outbound_queue ob_reg; + /* Queue for outbound stream-creating HEADERS (request or push + response) frame, which are subject to + SETTINGS_MAX_CONCURRENT_STREAMS limit. */ + nghttp2_outbound_queue ob_syn; + nghttp2_active_outbound_item aob; + nghttp2_inbound_frame iframe; + nghttp2_hd_deflater hd_deflater; + nghttp2_hd_inflater hd_inflater; + nghttp2_session_callbacks callbacks; + /* Memory allocator */ + nghttp2_mem mem; + /* Base value when we schedule next DATA frame write. This is + updated when one frame was written. */ + uint64_t last_cycle; + void *user_data; + /* Points to the latest incoming closed stream. NULL if there is no + closed stream. Only used when session is initialized as + server. */ + nghttp2_stream *closed_stream_head; + /* Points to the oldest incoming closed stream. NULL if there is no + closed stream. Only used when session is initialized as + server. */ + nghttp2_stream *closed_stream_tail; + /* Points to the latest idle stream. NULL if there is no idle + stream. Only used when session is initialized as server .*/ + nghttp2_stream *idle_stream_head; + /* Points to the oldest idle stream. NULL if there is no idle + stream. Only used when session is initialized as erver. */ + nghttp2_stream *idle_stream_tail; + /* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not + considered as in-flight. */ + nghttp2_inflight_settings *inflight_settings_head; + /* The number of outgoing streams. This will be capped by + remote_settings.max_concurrent_streams. */ + size_t num_outgoing_streams; + /* The number of incoming streams. This will be capped by + local_settings.max_concurrent_streams. */ + size_t num_incoming_streams; + /* The number of incoming reserved streams. This is the number of + streams in reserved (remote) state. RFC 7540 does not limit this + number. nghttp2 offers + nghttp2_option_set_max_reserved_remote_streams() to achieve this. + If it is used, num_incoming_streams is capped by + max_incoming_reserved_streams. Client application should + consider to set this because without that server can send + arbitrary number of PUSH_PROMISE, and exhaust client's memory. */ + size_t num_incoming_reserved_streams; + /* The maximum number of incoming reserved streams (reserved + (remote) state). RST_STREAM will be sent for the pushed stream + which exceeds this limit. */ + size_t max_incoming_reserved_streams; + /* The number of closed streams still kept in |streams| hash. The + closed streams can be accessed through single linked list + |closed_stream_head|. The current implementation only keeps + incoming streams and session is initialized as server. */ + size_t num_closed_streams; + /* The number of idle streams kept in |streams| hash. The idle + streams can be accessed through doubly linked list + |idle_stream_head|. The current implementation only keeps idle + streams if session is initialized as server. */ + size_t num_idle_streams; + /* The number of bytes allocated for nvbuf */ + size_t nvbuflen; + /* Counter for detecting flooding in outbound queue */ + size_t obq_flood_counter_; + /* The maximum length of header block to send. Calculated by the + same way as nghttp2_hd_deflate_bound() does. */ + size_t max_send_header_block_length; + /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */ + uint32_t next_stream_id; + /* The last stream ID this session initiated. For client session, + this is the last stream ID it has sent. For server session, it + is the last promised stream ID sent in PUSH_PROMISE. */ + int32_t last_sent_stream_id; + /* The largest stream ID received so far */ + int32_t last_recv_stream_id; + /* The largest stream ID which has been processed in some way. This + value will be used as last-stream-id when sending GOAWAY + frame. */ + int32_t last_proc_stream_id; + /* Counter of unique ID of PING. Wraps when it exceeds + NGHTTP2_MAX_UNIQUE_ID */ + uint32_t next_unique_id; + /* This is the last-stream-ID we have sent in GOAWAY */ + int32_t local_last_stream_id; + /* This is the value in GOAWAY frame received from remote endpoint. */ + int32_t remote_last_stream_id; + /* Current sender window size. This value is computed against the + current initial window size of remote endpoint. */ + int32_t remote_window_size; + /* Keep track of the number of bytes received without + WINDOW_UPDATE. This could be negative after submitting negative + value to WINDOW_UPDATE. */ + int32_t recv_window_size; + /* The number of bytes consumed by the application and now is + subject to WINDOW_UPDATE. This is only used when auto + WINDOW_UPDATE is turned off. */ + int32_t consumed_size; + /* The amount of recv_window_size cut using submitting negative + value to WINDOW_UPDATE */ + int32_t recv_reduction; + /* window size for local flow control. It is initially set to + NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE and could be + increased/decreased by submitting WINDOW_UPDATE. See + nghttp2_submit_window_update(). */ + int32_t local_window_size; + /* Settings value received from the remote endpoint. We just use ID + as index. The index = 0 is unused. */ + nghttp2_settings_storage remote_settings; + /* Settings value of the local endpoint. */ + nghttp2_settings_storage local_settings; + /* Option flags. This is bitwise-OR of 0 or more of nghttp2_optmask. */ + uint32_t opt_flags; + /* Unacked local SETTINGS_MAX_CONCURRENT_STREAMS value. We use this + to refuse the incoming stream if it exceeds this value. */ + uint32_t pending_local_max_concurrent_stream; + /* The bitwise OR of zero or more of nghttp2_typemask to indicate + that the default handling of extension frame is enabled. */ + uint32_t builtin_recv_ext_types; + /* Unacked local ENABLE_PUSH value. We use this to refuse + PUSH_PROMISE before SETTINGS ACK is received. */ + uint8_t pending_enable_push; + /* Nonzero if the session is server side. */ + uint8_t server; + /* Flags indicating GOAWAY is sent and/or received. The flags are + composed by bitwise OR-ing nghttp2_goaway_flag. */ + uint8_t goaway_flags; + /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to + this session. The nonzero does not necessarily mean + WINDOW_UPDATE is not queued. */ + uint8_t window_update_queued; + /* Bitfield of extension frame types that application is willing to + receive. To designate the bit of given frame type i, use + user_recv_ext_types[i / 8] & (1 << (i & 0x7)). First 10 frame + types are standard frame types and not used in this bitfield. If + bit is set, it indicates that incoming frame with that type is + passed to user defined callbacks, otherwise they are ignored. */ + uint8_t user_recv_ext_types[32]; +}; + +/* Struct used when updating initial window size of each active + stream. */ +typedef struct { + nghttp2_session *session; + int32_t new_window_size, old_window_size; +} nghttp2_update_window_size_arg; + +typedef struct { + nghttp2_session *session; + /* linked list of streams to close */ + nghttp2_stream *head; + int32_t last_stream_id; + /* nonzero if GOAWAY is sent to peer, which means we are going to + close incoming streams. zero if GOAWAY is received from peer and + we are going to close outgoing streams. */ + int incoming; +} nghttp2_close_stream_on_goaway_arg; + +/* TODO stream timeout etc */ + +/* + * Returns nonzero value if |stream_id| is initiated by local + * endpoint. + */ +int nghttp2_session_is_my_stream_id(nghttp2_session *session, + int32_t stream_id); + +/* + * Adds |item| to the outbound queue in |session|. When this function + * succeeds, it takes ownership of |item|. So caller must not free it + * on success. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_STREAM_CLOSED + * Stream already closed (DATA and PUSH_PROMISE frame only) + */ +int nghttp2_session_add_item(nghttp2_session *session, + nghttp2_outbound_item *item); + +/* + * Adds RST_STREAM frame for the stream |stream_id| with the error + * code |error_code|. This is a convenient function built on top of + * nghttp2_session_add_frame() to add RST_STREAM easily. + * + * This function simply returns 0 without adding RST_STREAM frame if + * given stream is in NGHTTP2_STREAM_CLOSING state, because multiple + * RST_STREAM for a stream is redundant. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id, + uint32_t error_code); + +/* + * Adds PING frame. This is a convenient functin built on top of + * nghttp2_session_add_frame() to add PING easily. + * + * If the |opaque_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. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_FLOODED + * There are too many items in outbound queue; this only happens + * if NGHTTP2_FLAG_ACK is set in |flags| + */ +int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags, + const uint8_t *opaque_data); + +/* + * Adds GOAWAY frame with the last-stream-ID |last_stream_id| and the + * error code |error_code|. This is a convenient function built on top + * of nghttp2_session_add_frame() to add GOAWAY easily. The + * |aux_flags| are bitwise-OR of one or more of + * nghttp2_goaway_aux_flag. + * + * 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 + * The |opaque_data_len| is too large. + */ +int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id, + uint32_t error_code, const uint8_t *opaque_data, + size_t opaque_data_len, uint8_t aux_flags); + +/* + * Adds WINDOW_UPDATE frame with stream ID |stream_id| and + * window-size-increment |window_size_increment|. This is a convenient + * function built on top of nghttp2_session_add_frame() to add + * WINDOW_UPDATE easily. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + int32_t window_size_increment); + +/* + * Adds SETTINGS frame. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_FLOODED + * There are too many items in outbound queue; this only happens + * if NGHTTP2_FLAG_ACK is set in |flags| + */ +int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags, + const nghttp2_settings_entry *iv, size_t niv); + +/* + * Creates new stream in |session| with stream ID |stream_id|, + * priority |pri_spec| and flags |flags|. The |flags| is bitwise OR + * of nghttp2_stream_flag. Since this function is called when initial + * HEADERS is sent or received, these flags are taken from it. The + * state of stream is set to |initial_state|. The |stream_user_data| + * is a pointer to the arbitrary user supplied data to be associated + * to this stream. + * + * If |initial_state| is NGHTTP2_STREAM_RESERVED, this function sets + * NGHTTP2_STREAM_FLAG_PUSH flag set. + * + * This function returns a pointer to created new stream object, or + * NULL. + * + * This function adjusts neither the number of closed streams or idle + * streams. The caller should manually call + * nghttp2_session_adjust_closed_stream() or + * nghttp2_session_adjust_idle_stream() respectively. + */ +nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, + int32_t stream_id, uint8_t flags, + nghttp2_priority_spec *pri_spec, + nghttp2_stream_state initial_state, + void *stream_user_data); + +/* + * Closes stream whose stream ID is |stream_id|. The reason of closure + * is indicated by the |error_code|. When closing the stream, + * on_stream_close_callback will be called. + * + * If the session is initialized as server and |stream| is incoming + * stream, stream is just marked closed and this function calls + * nghttp2_session_keep_closed_stream() with |stream|. Otherwise, + * |stream| will be deleted from memory. + * + * This function returns 0 if it succeeds, or one the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + * NGHTTP2_ERR_INVALID_ARGUMENT + * The specified stream does not exist. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, + uint32_t error_code); + +/* + * Deletes |stream| from memory. After this function returns, stream + * cannot be accessed. + * + * This function returns 0 if it succeeds, or one the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_session_destroy_stream(nghttp2_session *session, + nghttp2_stream *stream); + +/* + * Tries to keep incoming closed stream |stream|. Due to the + * limitation of maximum number of streams in memory, |stream| is not + * closed and just deleted from memory (see + * nghttp2_session_destroy_stream). + */ +void nghttp2_session_keep_closed_stream(nghttp2_session *session, + nghttp2_stream *stream); + +/* + * Appends |stream| to linked list |session->idle_stream_head|. We + * apply fixed limit for list size. To fit into that limit, one or + * more oldest streams are removed from list as necessary. + */ +void nghttp2_session_keep_idle_stream(nghttp2_session *session, + nghttp2_stream *stream); + +/* + * Detaches |stream| from idle streams linked list. + */ +void nghttp2_session_detach_idle_stream(nghttp2_session *session, + nghttp2_stream *stream); + +/* + * Deletes closed stream to ensure that number of incoming streams + * including active and closed is in the maximum number of allowed + * stream. + * + * This function returns 0 if it succeeds, or one the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_session_adjust_closed_stream(nghttp2_session *session); + +/* + * Deletes idle stream to ensure that number of idle streams is in + * certain limit. + * + * This function returns 0 if it succeeds, or one the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_session_adjust_idle_stream(nghttp2_session *session); + +/* + * If further receptions and transmissions over the stream |stream_id| + * are disallowed, close the stream with error code NGHTTP2_NO_ERROR. + * + * This function returns 0 if it + * succeeds, or one of the following negative error codes: + * + * NGHTTP2_ERR_INVALID_ARGUMENT + * The specified stream does not exist. + */ +int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session, + nghttp2_stream *stream); + +int nghttp2_session_on_request_headers_received(nghttp2_session *session, + nghttp2_frame *frame); + +int nghttp2_session_on_response_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream); + +int nghttp2_session_on_push_response_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream); + +/* + * Called when HEADERS is received, assuming |frame| is properly + * initialized. This function does first validate received frame and + * then open stream and call callback functions. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_IGN_HEADER_BLOCK + * Frame was rejected and header block must be decoded but + * result must be ignored. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The read_callback failed + */ +int nghttp2_session_on_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream); + +/* + * Called when PRIORITY is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The read_callback failed + */ +int nghttp2_session_on_priority_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when RST_STREAM is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + * NGHTTP2_ERR_CALLBACK_FAILURE + * The read_callback failed + */ +int nghttp2_session_on_rst_stream_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when SETTINGS is received, assuming |frame| is properly + * initialized. If |noack| is non-zero, SETTINGS with ACK will not be + * submitted. If |frame| has NGHTTP2_FLAG_ACK flag set, no SETTINGS + * with ACK will not be submitted regardless of |noack|. + * + * This function returns 0 if it succeeds, or one the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + * NGHTTP2_ERR_CALLBACK_FAILURE + * The read_callback failed + * NGHTTP2_ERR_FLOODED + * There are too many items in outbound queue, and this is most + * likely caused by misbehaviour of peer. + */ +int nghttp2_session_on_settings_received(nghttp2_session *session, + nghttp2_frame *frame, int noack); + +/* + * Called when PUSH_PROMISE is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_IGN_HEADER_BLOCK + * Frame was rejected and header block must be decoded but + * result must be ignored. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The read_callback failed + */ +int nghttp2_session_on_push_promise_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when PING is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + * NGHTTP2_ERR_FLOODED + * There are too many items in outbound queue, and this is most + * likely caused by misbehaviour of peer. + */ +int nghttp2_session_on_ping_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when GOAWAY is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +int nghttp2_session_on_goaway_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when WINDOW_UPDATE is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +int nghttp2_session_on_window_update_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when ALTSVC is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +int nghttp2_session_on_altsvc_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Called when DATA is received, assuming |frame| is properly + * initialized. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + */ +int nghttp2_session_on_data_received(nghttp2_session *session, + nghttp2_frame *frame); + +/* + * Returns nghttp2_stream* object whose stream ID is |stream_id|. It + * could be NULL if such stream does not exist. This function returns + * NULL if stream is marked as closed. + */ +nghttp2_stream *nghttp2_session_get_stream(nghttp2_session *session, + int32_t stream_id); + +/* + * This function behaves like nghttp2_session_get_stream(), but it + * returns stream object even if it is marked as closed or in + * NGHTTP2_STREAM_IDLE state. + */ +nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session, + int32_t stream_id); + +/* + * Packs DATA frame |frame| in wire frame format and stores it in + * |bufs|. Payload will be read using |aux_data->data_prd|. The + * length of payload is at most |datamax| bytes. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_DEFERRED + * The DATA frame is postponed. + * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE + * The read_callback failed (stream error). + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_CALLBACK_FAILURE + * The read_callback failed (session error). + */ +int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, + size_t datamax, nghttp2_frame *frame, + nghttp2_data_aux_data *aux_data, + nghttp2_stream *stream); + +/* + * Pops and returns next item to send. If there is no such item, + * returns NULL. This function takes into account max concurrent + * streams. That means if session->ob_syn has item and max concurrent + * streams is reached, the even if other queues contain items, then + * this function returns NULL. + */ +nghttp2_outbound_item * +nghttp2_session_pop_next_ob_item(nghttp2_session *session); + +/* + * Returns next item to send. If there is no such item, this function + * returns NULL. This function takes into account max concurrent + * streams. That means if session->ob_syn has item and max concurrent + * streams is reached, the even if other queues contain items, then + * this function returns NULL. + */ +nghttp2_outbound_item * +nghttp2_session_get_next_ob_item(nghttp2_session *session); + +/* + * Updates local settings with the |iv|. The number of elements in the + * array pointed by the |iv| is given by the |niv|. This function + * assumes that the all settings_id member in |iv| are in range 1 to + * NGHTTP2_SETTINGS_MAX, inclusive. + * + * 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. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_session_update_local_settings(nghttp2_session *session, + nghttp2_settings_entry *iv, + size_t niv); + +/* + * Re-prioritize |stream|. The new priority specification is + * |pri_spec|. Caller must ensure that stream->hd.stream_id != + * pri_spec->stream_id. + * + * This function does not adjust the number of idle streams. The + * caller should call nghttp2_session_adjust_idle_stream() later. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_session_reprioritize_stream(nghttp2_session *session, + nghttp2_stream *stream, + const nghttp2_priority_spec *pri_spec); + +/* + * Terminates current |session| with the |error_code|. The |reason| + * is NULL-terminated debug string. + * + * 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 + * The |reason| is too long. + */ +int nghttp2_session_terminate_session_with_reason(nghttp2_session *session, + uint32_t error_code, + const char *reason); + +#endif /* NGHTTP2_SESSION_H */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_stream.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_stream.c new file mode 100644 index 0000000..e3d2b1e --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_stream.c @@ -0,0 +1,985 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "nghttp2_stream.h" + +#include +#include + +#include "nghttp2_session.h" +#include "nghttp2_helper.h" +#include "nghttp2_debug.h" + +/* Maximum distance between any two stream's cycle in the same + prirority queue. Imagine stream A's cycle is A, and stream B's + cycle is B, and A < B. The cycle is unsigned 32 bit integer, it + may get overflow. Because of how we calculate the next cycle + value, if B - A is less than or equals to + NGHTTP2_MAX_CYCLE_DISTANCE, A and B are in the same scale, in other + words, B is really greater than or equal to A. Otherwise, A is a + result of overflow, and it is actually A > B if we consider that + fact. */ +#define NGHTTP2_MAX_CYCLE_DISTANCE (16384 * 256 + 255) + +static int stream_less(const void *lhsx, const void *rhsx) { + const nghttp2_stream *lhs, *rhs; + + lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry); + rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry); + + if (lhs->cycle == rhs->cycle) { + return lhs->seq < rhs->seq; + } + + if (lhs->cycle < rhs->cycle) { + return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE; + } + + return lhs->cycle - rhs->cycle > NGHTTP2_MAX_CYCLE_DISTANCE; +} + +void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, + uint8_t flags, nghttp2_stream_state initial_state, + int32_t weight, int32_t remote_initial_window_size, + int32_t local_initial_window_size, + void *stream_user_data, nghttp2_mem *mem) { + nghttp2_map_entry_init(&stream->map_entry, (key_type)stream_id); + nghttp2_pq_init(&stream->obq, stream_less, mem); + + stream->stream_id = stream_id; + stream->flags = flags; + stream->state = initial_state; + stream->shut_flags = NGHTTP2_SHUT_NONE; + stream->stream_user_data = stream_user_data; + stream->item = NULL; + stream->remote_window_size = remote_initial_window_size; + stream->local_window_size = local_initial_window_size; + stream->recv_window_size = 0; + stream->consumed_size = 0; + stream->recv_reduction = 0; + stream->window_update_queued = 0; + + stream->dep_prev = NULL; + stream->dep_next = NULL; + stream->sib_prev = NULL; + stream->sib_next = NULL; + + stream->closed_prev = NULL; + stream->closed_next = NULL; + + stream->weight = weight; + stream->sum_dep_weight = 0; + + stream->http_flags = NGHTTP2_HTTP_FLAG_NONE; + stream->content_length = -1; + stream->recv_content_length = 0; + stream->status_code = -1; + + stream->queued = 0; + stream->descendant_last_cycle = 0; + stream->cycle = 0; + stream->pending_penalty = 0; + stream->descendant_next_seq = 0; + stream->seq = 0; + stream->last_writelen = 0; +} + +void nghttp2_stream_free(nghttp2_stream *stream) { + nghttp2_pq_free(&stream->obq); + /* We don't free stream->item. If it is assigned to aob, then + active_outbound_item_reset() will delete it. Otherwise, + nghttp2_stream_close() or session_del() will delete it. */ +} + +void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) { + stream->shut_flags = (uint8_t)(stream->shut_flags | flag); +} + +/* + * Returns nonzero if |stream| is active. This function does not take + * into account its descendants. + */ +static int stream_active(nghttp2_stream *stream) { + return stream->item && + (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0; +} + +/* + * Returns nonzero if |stream| or one of its descendants is active + */ +static int stream_subtree_active(nghttp2_stream *stream) { + return stream_active(stream) || !nghttp2_pq_empty(&stream->obq); +} + +/* + * Returns next cycle for |stream|. + */ +static void stream_next_cycle(nghttp2_stream *stream, uint32_t last_cycle) { + uint32_t penalty; + + penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT + + stream->pending_penalty; + + stream->cycle = last_cycle + penalty / (uint32_t)stream->weight; + stream->pending_penalty = penalty % (uint32_t)stream->weight; +} + +static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) { + int rv; + + for (; dep_stream && !stream->queued; + stream = dep_stream, dep_stream = dep_stream->dep_prev) { + stream_next_cycle(stream, dep_stream->descendant_last_cycle); + stream->seq = dep_stream->descendant_next_seq++; + + DEBUGF("stream: stream=%d obq push cycle=%d\n", stream->stream_id, + stream->cycle); + + DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id, + dep_stream->stream_id); + + rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); + if (rv != 0) { + return rv; + } + stream->queued = 1; + } + + return 0; +} + +/* + * Removes |stream| from parent's obq. If removal of |stream| makes + * parent's obq empty, and parent is not active, then parent is also + * removed. This process is repeated recursively. + */ +static void stream_obq_remove(nghttp2_stream *stream) { + nghttp2_stream *dep_stream; + + dep_stream = stream->dep_prev; + + if (!stream->queued) { + return; + } + + for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) { + DEBUGF("stream: remove stream %d from stream %d\n", stream->stream_id, + dep_stream->stream_id); + + nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); + + assert(stream->queued); + + stream->queued = 0; + stream->cycle = 0; + stream->pending_penalty = 0; + stream->descendant_last_cycle = 0; + stream->last_writelen = 0; + + if (stream_subtree_active(dep_stream)) { + return; + } + } +} + +/* + * Moves |stream| from |src|'s obq to |dest|'s obq. Removal from + * |src|'s obq is just done calling nghttp2_pq_remove(), so it does + * not recursively remove |src| and ancestors, like + * stream_obq_remove(). + */ +static int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src, + nghttp2_stream *stream) { + if (!stream->queued) { + return 0; + } + + DEBUGF("stream: remove stream %d from stream %d (move)\n", stream->stream_id, + src->stream_id); + + nghttp2_pq_remove(&src->obq, &stream->pq_entry); + stream->queued = 0; + + return stream_obq_push(dest, stream); +} + +void nghttp2_stream_reschedule(nghttp2_stream *stream) { + nghttp2_stream *dep_stream; + + assert(stream->queued); + + dep_stream = stream->dep_prev; + + for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) { + nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); + + stream_next_cycle(stream, dep_stream->descendant_last_cycle); + stream->seq = dep_stream->descendant_next_seq++; + + nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); + + DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id, + stream->cycle); + + dep_stream->last_writelen = stream->last_writelen; + } +} + +void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) { + nghttp2_stream *dep_stream; + uint32_t last_cycle; + int32_t old_weight; + uint32_t wlen_penalty; + + if (stream->weight == weight) { + return; + } + + old_weight = stream->weight; + stream->weight = weight; + + dep_stream = stream->dep_prev; + + if (!dep_stream) { + return; + } + + dep_stream->sum_dep_weight += weight - old_weight; + + if (!stream->queued) { + return; + } + + nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); + + wlen_penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT; + + /* Compute old stream->pending_penalty we used to calculate + stream->cycle */ + stream->pending_penalty = + (uint32_t)((stream->pending_penalty + (uint32_t)old_weight - + (wlen_penalty % (uint32_t)old_weight)) % + (uint32_t)old_weight); + + last_cycle = stream->cycle - + (wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight; + + /* Now we have old stream->pending_penalty and new stream->weight in + place */ + stream_next_cycle(stream, last_cycle); + + if (stream->cycle < dep_stream->descendant_last_cycle && + (dep_stream->descendant_last_cycle - stream->cycle) <= + NGHTTP2_MAX_CYCLE_DISTANCE) { + stream->cycle = dep_stream->descendant_last_cycle; + } + + /* Continue to use same stream->seq */ + + nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); + + DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id, + stream->cycle); +} + +static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) { + for (; stream->sib_next; stream = stream->sib_next) + ; + + return stream; +} + +int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream, + int32_t weight) { + weight = stream->weight * weight / stream->sum_dep_weight; + + return nghttp2_max(1, weight); +} + +#ifdef STREAM_DEP_DEBUG + +static void ensure_inactive(nghttp2_stream *stream) { + nghttp2_stream *si; + + if (stream->queued) { + fprintf(stderr, "stream(%p)=%d, stream->queued = 1; want 0\n", stream, + stream->stream_id); + assert(0); + } + + if (stream_active(stream)) { + fprintf(stderr, "stream(%p)=%d, stream_active(stream) = 1; want 0\n", + stream, stream->stream_id); + assert(0); + } + + if (!nghttp2_pq_empty(&stream->obq)) { + fprintf(stderr, "stream(%p)=%d, nghttp2_pq_size() = %zu; want 0\n", stream, + stream->stream_id, nghttp2_pq_size(&stream->obq)); + assert(0); + } + + for (si = stream->dep_next; si; si = si->sib_next) { + ensure_inactive(si); + } +} + +static void check_queued(nghttp2_stream *stream) { + nghttp2_stream *si; + int queued; + + if (stream->queued) { + if (!stream_subtree_active(stream)) { + fprintf(stderr, + "stream(%p)=%d, stream->queued == 1, but " + "stream_active() == %d and nghttp2_pq_size(&stream->obq) = %zu\n", + stream, stream->stream_id, stream_active(stream), + nghttp2_pq_size(&stream->obq)); + assert(0); + } + if (!stream_active(stream)) { + queued = 0; + for (si = stream->dep_next; si; si = si->sib_next) { + if (si->queued) { + ++queued; + } + } + if (queued == 0) { + fprintf(stderr, + "stream(%p)=%d, stream->queued == 1, and " + "!stream_active(), but no descendants is queued\n", + stream, stream->stream_id); + assert(0); + } + } + + for (si = stream->dep_next; si; si = si->sib_next) { + check_queued(si); + } + } else { + if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) { + fprintf(stderr, + "stream(%p) = %d, stream->queued == 0, but " + "stream_active(stream) == %d and " + "nghttp2_pq_size(&stream->obq) = %zu\n", + stream, stream->stream_id, stream_active(stream), + nghttp2_pq_size(&stream->obq)); + assert(0); + } + for (si = stream->dep_next; si; si = si->sib_next) { + ensure_inactive(si); + } + } +} + +static void check_sum_dep(nghttp2_stream *stream) { + nghttp2_stream *si; + int32_t n = 0; + for (si = stream->dep_next; si; si = si->sib_next) { + n += si->weight; + } + if (n != stream->sum_dep_weight) { + fprintf(stderr, "stream(%p)=%d, sum_dep_weight = %d; want %d\n", stream, + stream->stream_id, n, stream->sum_dep_weight); + assert(0); + } + for (si = stream->dep_next; si; si = si->sib_next) { + check_sum_dep(si); + } +} + +static void check_dep_prev(nghttp2_stream *stream) { + nghttp2_stream *si; + for (si = stream->dep_next; si; si = si->sib_next) { + if (si->dep_prev != stream) { + fprintf(stderr, "si->dep_prev = %p; want %p\n", si->dep_prev, stream); + assert(0); + } + check_dep_prev(si); + } +} + +#endif /* STREAM_DEP_DEBUG */ + +#ifdef STREAM_DEP_DEBUG +static void validate_tree(nghttp2_stream *stream) { + nghttp2_stream *si; + + if (!stream) { + return; + } + + for (; stream->dep_prev; stream = stream->dep_prev) + ; + + assert(stream->stream_id == 0); + assert(!stream->queued); + + fprintf(stderr, "checking...\n"); + if (nghttp2_pq_empty(&stream->obq)) { + fprintf(stderr, "root obq empty\n"); + for (si = stream->dep_next; si; si = si->sib_next) { + ensure_inactive(si); + } + } else { + for (si = stream->dep_next; si; si = si->sib_next) { + check_queued(si); + } + } + + check_sum_dep(stream); + check_dep_prev(stream); +} +#else /* !STREAM_DEP_DEBUG */ +static void validate_tree(nghttp2_stream *stream) { (void)stream; } +#endif /* !STREAM_DEP_DEBUG*/ + +static int stream_update_dep_on_attach_item(nghttp2_stream *stream) { + int rv; + + rv = stream_obq_push(stream->dep_prev, stream); + if (rv != 0) { + return rv; + } + + validate_tree(stream); + return 0; +} + +static int stream_update_dep_on_detach_item(nghttp2_stream *stream) { + if (nghttp2_pq_empty(&stream->obq)) { + stream_obq_remove(stream); + } + + validate_tree(stream); + + return 0; +} + +int nghttp2_stream_attach_item(nghttp2_stream *stream, + nghttp2_outbound_item *item) { + int rv; + + assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0); + assert(stream->item == NULL); + + DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item); + + stream->item = item; + + rv = stream_update_dep_on_attach_item(stream); + if (rv != 0) { + /* This may relave stream->queued == 1, but stream->item == NULL. + But only consequence of this error is fatal one, and session + destruction. In that execution path, these inconsistency does + not matter. */ + stream->item = NULL; + return rv; + } + + return 0; +} + +int nghttp2_stream_detach_item(nghttp2_stream *stream) { + DEBUGF("stream: stream=%d detach item=%p\n", stream->stream_id, stream->item); + + stream->item = NULL; + stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL); + + return stream_update_dep_on_detach_item(stream); +} + +int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) { + assert(stream->item); + + DEBUGF("stream: stream=%d defer item=%p cause=%02x\n", stream->stream_id, + stream->item, flags); + + stream->flags |= flags; + + return stream_update_dep_on_detach_item(stream); +} + +int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) { + assert(stream->item); + + DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id, + stream->item, flags); + + stream->flags = (uint8_t)(stream->flags & ~flags); + + if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) { + return 0; + } + + return stream_update_dep_on_attach_item(stream); +} + +int nghttp2_stream_check_deferred_item(nghttp2_stream *stream) { + return stream->item && (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL); +} + +int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream) { + return stream->item && + (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); +} + +static int update_initial_window_size(int32_t *window_size_ptr, + int32_t new_initial_window_size, + int32_t old_initial_window_size) { + int64_t new_window_size = (int64_t)(*window_size_ptr) + + new_initial_window_size - old_initial_window_size; + if (INT32_MIN > new_window_size || + new_window_size > NGHTTP2_MAX_WINDOW_SIZE) { + return -1; + } + *window_size_ptr = (int32_t)new_window_size; + return 0; +} + +int nghttp2_stream_update_remote_initial_window_size( + nghttp2_stream *stream, int32_t new_initial_window_size, + int32_t old_initial_window_size) { + return update_initial_window_size(&stream->remote_window_size, + new_initial_window_size, + old_initial_window_size); +} + +int nghttp2_stream_update_local_initial_window_size( + nghttp2_stream *stream, int32_t new_initial_window_size, + int32_t old_initial_window_size) { + return update_initial_window_size(&stream->local_window_size, + new_initial_window_size, + old_initial_window_size); +} + +void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) { + stream->state = NGHTTP2_STREAM_OPENED; + stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH); +} + +int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream, + nghttp2_stream *target) { + for (; stream; stream = stream->dep_prev) { + if (stream == target) { + return 1; + } + } + return 0; +} + +int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, + nghttp2_stream *stream) { + nghttp2_stream *si; + int rv; + + DEBUGF("stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream, + dep_stream->stream_id, stream, stream->stream_id); + + stream->sum_dep_weight = dep_stream->sum_dep_weight; + dep_stream->sum_dep_weight = stream->weight; + + if (dep_stream->dep_next) { + for (si = dep_stream->dep_next; si; si = si->sib_next) { + si->dep_prev = stream; + if (si->queued) { + rv = stream_obq_move(stream, dep_stream, si); + if (rv != 0) { + return rv; + } + } + } + + if (stream_subtree_active(stream)) { + rv = stream_obq_push(dep_stream, stream); + if (rv != 0) { + return rv; + } + } + + stream->dep_next = dep_stream->dep_next; + } + + dep_stream->dep_next = stream; + stream->dep_prev = dep_stream; + + validate_tree(stream); + + return 0; +} + +static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) { + for (; stream; stream = stream->sib_next) { + stream->dep_prev = dep; + } +} + +static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) { + dep_stream->dep_next = stream; + if (stream) { + stream->dep_prev = dep_stream; + } +} + +static void link_sib(nghttp2_stream *a, nghttp2_stream *b) { + a->sib_next = b; + if (b) { + b->sib_prev = a; + } +} + +static void insert_link_dep(nghttp2_stream *dep_stream, + nghttp2_stream *stream) { + nghttp2_stream *sib_next; + + assert(stream->sib_prev == NULL); + + sib_next = dep_stream->dep_next; + + link_sib(stream, sib_next); + + link_dep(dep_stream, stream); +} + +static void unlink_sib(nghttp2_stream *stream) { + nghttp2_stream *prev, *next, *dep_next; + + prev = stream->sib_prev; + dep_next = stream->dep_next; + + assert(prev); + + if (dep_next) { + /* + * prev--stream(--sib_next--...) + * | + * dep_next + */ + + link_sib(prev, dep_next); + + set_dep_prev(dep_next, stream->dep_prev); + + if (stream->sib_next) { + link_sib(stream_last_sib(dep_next), stream->sib_next); + } + } else { + /* + * prev--stream(--sib_next--...) + */ + next = stream->sib_next; + + prev->sib_next = next; + + if (next) { + next->sib_prev = prev; + } + } +} + +static void unlink_dep(nghttp2_stream *stream) { + nghttp2_stream *prev, *next, *dep_next; + + prev = stream->dep_prev; + dep_next = stream->dep_next; + + assert(prev); + + if (dep_next) { + /* + * prev + * | + * stream(--sib_next--...) + * | + * dep_next + */ + link_dep(prev, dep_next); + + set_dep_prev(dep_next, stream->dep_prev); + + if (stream->sib_next) { + link_sib(stream_last_sib(dep_next), stream->sib_next); + } + + } else if (stream->sib_next) { + /* + * prev + * | + * stream--sib_next + */ + next = stream->sib_next; + + next->sib_prev = NULL; + + link_dep(prev, next); + } else { + prev->dep_next = NULL; + } +} + +void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, + nghttp2_stream *stream) { + DEBUGF("stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream, + dep_stream->stream_id, stream, stream->stream_id); + + dep_stream->sum_dep_weight += stream->weight; + + if (dep_stream->dep_next == NULL) { + link_dep(dep_stream, stream); + } else { + insert_link_dep(dep_stream, stream); + } + + validate_tree(stream); +} + +int nghttp2_stream_dep_remove(nghttp2_stream *stream) { + nghttp2_stream *dep_prev, *si; + int32_t sum_dep_weight_delta; + int rv; + + DEBUGF("stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id); + + /* Distribute weight of |stream| to direct descendants */ + sum_dep_weight_delta = -stream->weight; + + for (si = stream->dep_next; si; si = si->sib_next) { + si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight); + + sum_dep_weight_delta += si->weight; + + if (si->queued) { + rv = stream_obq_move(stream->dep_prev, stream, si); + if (rv != 0) { + return rv; + } + } + } + + assert(stream->dep_prev); + + dep_prev = stream->dep_prev; + + dep_prev->sum_dep_weight += sum_dep_weight_delta; + + if (stream->queued) { + stream_obq_remove(stream); + } + + if (stream->sib_prev) { + unlink_sib(stream); + } else { + unlink_dep(stream); + } + + stream->sum_dep_weight = 0; + + stream->dep_prev = NULL; + stream->dep_next = NULL; + stream->sib_prev = NULL; + stream->sib_next = NULL; + + validate_tree(dep_prev); + + return 0; +} + +int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, + nghttp2_stream *stream) { + nghttp2_stream *last_sib; + nghttp2_stream *dep_next; + nghttp2_stream *si; + int rv; + + DEBUGF("stream: dep_insert_subtree dep_stream(%p)=%d stream(%p)=%d\n", + dep_stream, dep_stream->stream_id, stream, stream->stream_id); + + stream->sum_dep_weight += dep_stream->sum_dep_weight; + dep_stream->sum_dep_weight = stream->weight; + + if (dep_stream->dep_next) { + dep_next = dep_stream->dep_next; + + link_dep(dep_stream, stream); + + if (stream->dep_next) { + last_sib = stream_last_sib(stream->dep_next); + + link_sib(last_sib, dep_next); + } else { + link_dep(stream, dep_next); + } + + for (si = dep_next; si; si = si->sib_next) { + si->dep_prev = stream; + if (si->queued) { + rv = stream_obq_move(stream, dep_stream, si); + if (rv != 0) { + return rv; + } + } + } + } else { + link_dep(dep_stream, stream); + } + + if (stream_subtree_active(stream)) { + rv = stream_obq_push(dep_stream, stream); + if (rv != 0) { + return rv; + } + } + + validate_tree(dep_stream); + + return 0; +} + +int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, + nghttp2_stream *stream) { + int rv; + + DEBUGF("stream: dep_add_subtree dep_stream(%p)=%d stream(%p)=%d\n", + dep_stream, dep_stream->stream_id, stream, stream->stream_id); + + dep_stream->sum_dep_weight += stream->weight; + + if (dep_stream->dep_next) { + insert_link_dep(dep_stream, stream); + } else { + link_dep(dep_stream, stream); + } + + if (stream_subtree_active(stream)) { + rv = stream_obq_push(dep_stream, stream); + if (rv != 0) { + return rv; + } + } + + validate_tree(dep_stream); + + return 0; +} + +void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) { + nghttp2_stream *next, *dep_prev; + + DEBUGF("stream: dep_remove_subtree stream(%p)=%d\n", stream, + stream->stream_id); + + assert(stream->dep_prev); + + dep_prev = stream->dep_prev; + + if (stream->sib_prev) { + link_sib(stream->sib_prev, stream->sib_next); + } else { + next = stream->sib_next; + + link_dep(dep_prev, next); + + if (next) { + next->sib_prev = NULL; + } + } + + dep_prev->sum_dep_weight -= stream->weight; + + if (stream->queued) { + stream_obq_remove(stream); + } + + validate_tree(dep_prev); + + stream->sib_prev = NULL; + stream->sib_next = NULL; + stream->dep_prev = NULL; +} + +int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) { + return stream->dep_prev || stream->dep_next || stream->sib_prev || + stream->sib_next; +} + +nghttp2_outbound_item * +nghttp2_stream_next_outbound_item(nghttp2_stream *stream) { + nghttp2_pq_entry *ent; + nghttp2_stream *si; + + for (;;) { + if (stream_active(stream)) { + /* Update ascendant's descendant_last_cycle here, so that we can + assure that new stream is scheduled based on it. */ + for (si = stream; si->dep_prev; si = si->dep_prev) { + si->dep_prev->descendant_last_cycle = si->cycle; + } + return stream->item; + } + ent = nghttp2_pq_top(&stream->obq); + if (!ent) { + return NULL; + } + stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry); + } +} + +nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) { + if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) { + return NGHTTP2_STREAM_STATE_CLOSED; + } + + if (stream->flags & NGHTTP2_STREAM_FLAG_PUSH) { + if (stream->shut_flags & NGHTTP2_SHUT_RD) { + return NGHTTP2_STREAM_STATE_RESERVED_LOCAL; + } + + if (stream->shut_flags & NGHTTP2_SHUT_WR) { + return NGHTTP2_STREAM_STATE_RESERVED_REMOTE; + } + } + + if (stream->shut_flags & NGHTTP2_SHUT_RD) { + return NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; + } + + if (stream->shut_flags & NGHTTP2_SHUT_WR) { + return NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL; + } + + if (stream->state == NGHTTP2_STREAM_IDLE) { + return NGHTTP2_STREAM_STATE_IDLE; + } + + return NGHTTP2_STREAM_STATE_OPEN; +} + +nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) { + return stream->dep_prev; +} + +nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) { + return stream->sib_next; +} + +nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) { + return stream->sib_prev; +} + +nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) { + return stream->dep_next; +} + +int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) { + return stream->weight; +} + +int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) { + return stream->sum_dep_weight; +} + +int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) { + return stream->stream_id; +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_stream.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_stream.h new file mode 100644 index 0000000..7ff6928 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_stream.h @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_STREAM_H +#define NGHTTP2_STREAM_H + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" +#include "nghttp2_outbound_item.h" +#include "nghttp2_map.h" +#include "nghttp2_pq.h" +#include "nghttp2_int.h" + +/* + * If local peer is stream initiator: + * NGHTTP2_STREAM_OPENING : upon sending request HEADERS + * NGHTTP2_STREAM_OPENED : upon receiving response HEADERS + * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM + * + * If remote peer is stream initiator: + * NGHTTP2_STREAM_OPENING : upon receiving request HEADERS + * NGHTTP2_STREAM_OPENED : upon sending response HEADERS + * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM + */ +typedef enum { + /* Initial state */ + NGHTTP2_STREAM_INITIAL, + /* For stream initiator: request HEADERS has been sent, but response + HEADERS has not been received yet. For receiver: request HEADERS + has been received, but it does not send response HEADERS yet. */ + NGHTTP2_STREAM_OPENING, + /* For stream initiator: response HEADERS is received. For receiver: + response HEADERS is sent. */ + NGHTTP2_STREAM_OPENED, + /* RST_STREAM is received, but somehow we need to keep stream in + memory. */ + NGHTTP2_STREAM_CLOSING, + /* PUSH_PROMISE is received or sent */ + NGHTTP2_STREAM_RESERVED, + /* Stream is created in this state if it is used as anchor in + dependency tree. */ + NGHTTP2_STREAM_IDLE +} nghttp2_stream_state; + +typedef enum { + NGHTTP2_SHUT_NONE = 0, + /* Indicates further receptions will be disallowed. */ + NGHTTP2_SHUT_RD = 0x01, + /* Indicates further transmissions will be disallowed. */ + NGHTTP2_SHUT_WR = 0x02, + /* Indicates both further receptions and transmissions will be + disallowed. */ + NGHTTP2_SHUT_RDWR = NGHTTP2_SHUT_RD | NGHTTP2_SHUT_WR +} nghttp2_shut_flag; + +typedef enum { + NGHTTP2_STREAM_FLAG_NONE = 0, + /* Indicates that this stream is pushed stream and not opened + yet. */ + NGHTTP2_STREAM_FLAG_PUSH = 0x01, + /* Indicates that this stream was closed */ + NGHTTP2_STREAM_FLAG_CLOSED = 0x02, + /* Indicates the item is deferred due to flow control. */ + NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL = 0x04, + /* Indicates the item is deferred by user callback */ + NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08, + /* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and + NGHTTP2_STREAM_FLAG_DEFERRED_USER. */ + NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c + +} nghttp2_stream_flag; + +/* HTTP related flags to enforce HTTP semantics */ +typedef enum { + NGHTTP2_HTTP_FLAG_NONE = 0, + /* header field seen so far */ + NGHTTP2_HTTP_FLAG__AUTHORITY = 1, + NGHTTP2_HTTP_FLAG__PATH = 1 << 1, + NGHTTP2_HTTP_FLAG__METHOD = 1 << 2, + NGHTTP2_HTTP_FLAG__SCHEME = 1 << 3, + /* host is not pseudo header, but we require either host or + :authority */ + NGHTTP2_HTTP_FLAG_HOST = 1 << 4, + NGHTTP2_HTTP_FLAG__STATUS = 1 << 5, + /* required header fields for HTTP request except for CONNECT + method. */ + NGHTTP2_HTTP_FLAG_REQ_HEADERS = NGHTTP2_HTTP_FLAG__METHOD | + NGHTTP2_HTTP_FLAG__PATH | + NGHTTP2_HTTP_FLAG__SCHEME, + NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED = 1 << 6, + /* HTTP method flags */ + NGHTTP2_HTTP_FLAG_METH_CONNECT = 1 << 7, + NGHTTP2_HTTP_FLAG_METH_HEAD = 1 << 8, + NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9, + NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10, + NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT | + NGHTTP2_HTTP_FLAG_METH_HEAD | + NGHTTP2_HTTP_FLAG_METH_OPTIONS | + NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND, + /* :path category */ + /* path starts with "/" */ + NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11, + /* path "*" */ + NGHTTP2_HTTP_FLAG_PATH_ASTERISK = 1 << 12, + /* scheme */ + /* "http" or "https" scheme */ + NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13, + /* set if final response is expected */ + NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14 +} nghttp2_http_flag; + +struct nghttp2_stream { + /* Intrusive Map */ + nghttp2_map_entry map_entry; + /* Entry for dep_prev->obq */ + nghttp2_pq_entry pq_entry; + /* Priority Queue storing direct descendant (nghttp2_stream). Only + streams which itself has some data to send, or has a descendant + which has some data to sent. */ + nghttp2_pq obq; + /* Content-Length of request/response body. -1 if unknown. */ + int64_t content_length; + /* Received body so far */ + int64_t recv_content_length; + /* Base last_cycle for direct descendent streams. */ + uint32_t descendant_last_cycle; + /* Next scheduled time to sent item */ + uint32_t cycle; + /* Next seq used for direct descendant streams */ + uint64_t descendant_next_seq; + /* Secondary key for prioritization to break a tie for cycle. This + value is monotonically increased for single parent stream. */ + uint64_t seq; + /* pointers to form dependency tree. If multiple streams depend on + a stream, only one stream (left most) has non-NULL dep_prev which + points to the stream it depends on. The remaining streams are + linked using sib_prev and sib_next. The stream which has + non-NULL dep_prev always NULL sib_prev. The right most stream + has NULL sib_next. If this stream is a root of dependency tree, + dep_prev and sib_prev are NULL. */ + nghttp2_stream *dep_prev, *dep_next; + nghttp2_stream *sib_prev, *sib_next; + /* When stream is kept after closure, it may be kept in doubly + linked list pointed by nghttp2_session closed_stream_head. + closed_next points to the next stream object if it is the element + of the list. */ + nghttp2_stream *closed_prev, *closed_next; + /* The arbitrary data provided by user for this stream. */ + void *stream_user_data; + /* Item to send */ + nghttp2_outbound_item *item; + /* Last written length of frame payload */ + size_t last_writelen; + /* stream ID */ + int32_t stream_id; + /* Current remote window size. This value is computed against the + current initial window size of remote endpoint. */ + int32_t remote_window_size; + /* Keep track of the number of bytes received without + WINDOW_UPDATE. This could be negative after submitting negative + value to WINDOW_UPDATE */ + int32_t recv_window_size; + /* The number of bytes consumed by the application and now is + subject to WINDOW_UPDATE. This is only used when auto + WINDOW_UPDATE is turned off. */ + int32_t consumed_size; + /* The amount of recv_window_size cut using submitting negative + value to WINDOW_UPDATE */ + int32_t recv_reduction; + /* window size for local flow control. It is initially set to + NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by + submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */ + int32_t local_window_size; + /* weight of this stream */ + int32_t weight; + /* This is unpaid penalty (offset) when calculating cycle. */ + uint32_t pending_penalty; + /* sum of weight of direct descendants */ + int32_t sum_dep_weight; + nghttp2_stream_state state; + /* status code from remote server */ + int16_t status_code; + /* Bitwise OR of zero or more nghttp2_http_flag values */ + uint16_t http_flags; + /* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */ + uint8_t flags; + /* Bitwise OR of zero or more nghttp2_shut_flag values */ + uint8_t shut_flags; + /* Nonzero if this stream has been queued to stream pointed by + dep_prev. We maintain the invariant that if a stream is queued, + then its ancestors, except for root, are also queued. This + invariant may break in fatal error condition. */ + uint8_t queued; + /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to + this stream. The nonzero does not necessarily mean WINDOW_UPDATE + is not queued. */ + uint8_t window_update_queued; +}; + +void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, + uint8_t flags, nghttp2_stream_state initial_state, + int32_t weight, int32_t remote_initial_window_size, + int32_t local_initial_window_size, + void *stream_user_data, nghttp2_mem *mem); + +void nghttp2_stream_free(nghttp2_stream *stream); + +/* + * Disallow either further receptions or transmissions, or both. + * |flag| is bitwise OR of one or more of nghttp2_shut_flag. + */ +void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag); + +/* + * Defer |stream->item|. We won't call this function in the situation + * where |stream->item| == NULL. The |flags| is bitwise OR of zero or + * more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and + * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates + * the reason of this action. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags); + +/* + * Put back deferred data in this stream to active state. The |flags| + * are one or more of bitwise OR of the following values: + * NGHTTP2_STREAM_FLAG_DEFERRED_USER and + * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are + * cleared if they are set. So even if this function is called, if + * one of flag is still set, data does not become active. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags); + +/* + * Returns nonzero if item is deferred by whatever reason. + */ +int nghttp2_stream_check_deferred_item(nghttp2_stream *stream); + +/* + * Returns nonzero if item is deferred by flow control. + */ +int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream); + +/* + * Updates the remote window size with the new value + * |new_initial_window_size|. The |old_initial_window_size| is used to + * calculate the current window size. + * + * This function returns 0 if it succeeds or -1. The failure is due to + * overflow. + */ +int nghttp2_stream_update_remote_initial_window_size( + nghttp2_stream *stream, int32_t new_initial_window_size, + int32_t old_initial_window_size); + +/* + * Updates the local window size with the new value + * |new_initial_window_size|. The |old_initial_window_size| is used to + * calculate the current window size. + * + * This function returns 0 if it succeeds or -1. The failure is due to + * overflow. + */ +int nghttp2_stream_update_local_initial_window_size( + nghttp2_stream *stream, int32_t new_initial_window_size, + int32_t old_initial_window_size); + +/* + * Call this function if promised stream |stream| is replied with + * HEADERS. This function makes the state of the |stream| to + * NGHTTP2_STREAM_OPENED. + */ +void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream); + +/* + * Returns nonzero if |target| is an ancestor of |stream|. + */ +int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream, + nghttp2_stream *target); + +/* + * Computes distributed weight of a stream of the |weight| under the + * |stream| if |stream| is removed from a dependency tree. + */ +int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream, + int32_t weight); + +/* + * Makes the |stream| depend on the |dep_stream|. This dependency is + * exclusive. All existing direct descendants of |dep_stream| become + * the descendants of the |stream|. This function assumes + * |stream->item| is NULL. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, + nghttp2_stream *stream); + +/* + * Makes the |stream| depend on the |dep_stream|. This dependency is + * not exclusive. This function assumes |stream->item| is NULL. + */ +void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream); + +/* + * Removes the |stream| from the current dependency tree. This + * function assumes |stream->item| is NULL. + */ +int nghttp2_stream_dep_remove(nghttp2_stream *stream); + +/* + * Attaches |item| to |stream|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_attach_item(nghttp2_stream *stream, + nghttp2_outbound_item *item); + +/* + * Detaches |stream->item|. This function does not free + * |stream->item|. The caller must free it. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_detach_item(nghttp2_stream *stream); + +/* + * Makes the |stream| depend on the |dep_stream|. This dependency is + * exclusive. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, + nghttp2_stream *stream); + +/* + * Makes the |stream| depend on the |dep_stream|. This dependency is + * not exclusive. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, + nghttp2_stream *stream); + +/* + * Removes subtree whose root stream is |stream|. The + * effective_weight of streams in removed subtree is not updated. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory + */ +void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream); + +/* + * Returns nonzero if |stream| is in any dependency tree. + */ +int nghttp2_stream_in_dep_tree(nghttp2_stream *stream); + +/* + * Schedules transmission of |stream|'s item, assuming stream->item is + * attached, and stream->last_writelen was updated. + */ +void nghttp2_stream_reschedule(nghttp2_stream *stream); + +/* + * Changes |stream|'s weight to |weight|. If |stream| is queued, it + * will be rescheduled based on new weight. + */ +void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight); + +/* + * Returns a stream which has highest priority, updating + * descendant_last_cycle of selected stream's ancestors. + */ +nghttp2_outbound_item * +nghttp2_stream_next_outbound_item(nghttp2_stream *stream); + +#endif /* NGHTTP2_STREAM */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_submit.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_submit.c new file mode 100644 index 0000000..dedf86e --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_submit.c @@ -0,0 +1,712 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include "nghttp2_submit.h" + +#include +#include + +#include "nghttp2_session.h" +#include "nghttp2_frame.h" +#include "nghttp2_helper.h" +#include "nghttp2_priority_spec.h" + +/* + * Detects the dependency error, that is stream attempted to depend on + * itself. If |stream_id| is -1, we use session->next_stream_id as + * stream ID. + * + * This function returns 0 if it succeeds, or one of the following + * error codes: + * + * NGHTTP2_ERR_INVALID_ARGUMENT + * Stream attempted to depend on itself. + */ +static int detect_self_dependency(nghttp2_session *session, int32_t stream_id, + const nghttp2_priority_spec *pri_spec) { + assert(pri_spec); + + if (stream_id == -1) { + if ((int32_t)session->next_stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + return 0; + } + + if (stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + return 0; +} + +/* This function takes ownership of |nva_copy|. Regardless of the + return value, the caller must not free |nva_copy| after this + function returns. */ +static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_priority_spec *pri_spec, + nghttp2_nv *nva_copy, size_t nvlen, + const nghttp2_data_provider *data_prd, + void *stream_user_data) { + int rv; + uint8_t flags_copy; + nghttp2_outbound_item *item = NULL; + nghttp2_frame *frame = NULL; + nghttp2_headers_category hcat; + nghttp2_mem *mem; + + mem = &session->mem; + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + rv = NGHTTP2_ERR_NOMEM; + goto fail; + } + + nghttp2_outbound_item_init(item); + + if (data_prd != NULL && data_prd->read_callback != NULL) { + item->aux_data.headers.data_prd = *data_prd; + } + + item->aux_data.headers.stream_user_data = stream_user_data; + + flags_copy = + (uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) | + NGHTTP2_FLAG_END_HEADERS); + + if (stream_id == -1) { + if (session->next_stream_id > INT32_MAX) { + rv = NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE; + goto fail; + } + + stream_id = (int32_t)session->next_stream_id; + session->next_stream_id += 2; + + hcat = NGHTTP2_HCAT_REQUEST; + } else { + /* More specific categorization will be done later. */ + hcat = NGHTTP2_HCAT_HEADERS; + } + + frame = &item->frame; + + nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat, + pri_spec, nva_copy, nvlen); + + rv = nghttp2_session_add_item(session, item); + + if (rv != 0) { + nghttp2_frame_headers_free(&frame->headers, mem); + goto fail2; + } + + if (hcat == NGHTTP2_HCAT_REQUEST) { + return stream_id; + } + + return 0; + +fail: + /* nghttp2_frame_headers_init() takes ownership of nva_copy. */ + nghttp2_nv_array_del(nva_copy, mem); +fail2: + nghttp2_mem_free(mem, item); + + return rv; +} + +static int32_t submit_headers_shared_nva(nghttp2_session *session, + uint8_t flags, int32_t stream_id, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd, + void *stream_user_data) { + int rv; + nghttp2_nv *nva_copy; + nghttp2_priority_spec copy_pri_spec; + nghttp2_mem *mem; + + mem = &session->mem; + + if (pri_spec) { + copy_pri_spec = *pri_spec; + nghttp2_priority_spec_normalize_weight(©_pri_spec); + } else { + nghttp2_priority_spec_default_init(©_pri_spec); + } + + rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem); + if (rv < 0) { + return rv; + } + + return submit_headers_shared(session, flags, stream_id, ©_pri_spec, + nva_copy, nvlen, data_prd, stream_user_data); +} + +int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen) { + if (stream_id <= 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + return (int)submit_headers_shared_nva(session, NGHTTP2_FLAG_END_STREAM, + stream_id, NULL, nva, nvlen, NULL, + NULL); +} + +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) { + int rv; + + if (stream_id == -1) { + if (session->server) { + return NGHTTP2_ERR_PROTO; + } + } else if (stream_id <= 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + flags &= NGHTTP2_FLAG_END_STREAM; + + if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) { + rv = detect_self_dependency(session, stream_id, pri_spec); + if (rv != 0) { + return rv; + } + + flags |= NGHTTP2_FLAG_PRIORITY; + } else { + pri_spec = NULL; + } + + return submit_headers_shared_nva(session, flags, stream_id, pri_spec, nva, + nvlen, NULL, stream_user_data); +} + +int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, + const uint8_t *opaque_data) { + flags &= NGHTTP2_FLAG_ACK; + return nghttp2_session_add_ping(session, flags, opaque_data); +} + +int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_priority_spec *pri_spec) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_priority_spec copy_pri_spec; + nghttp2_mem *mem; + (void)flags; + + mem = &session->mem; + + if (stream_id == 0 || pri_spec == NULL) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + copy_pri_spec = *pri_spec; + + nghttp2_priority_spec_normalize_weight(©_pri_spec); + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + + nghttp2_frame_priority_init(&frame->priority, stream_id, ©_pri_spec); + + rv = nghttp2_session_add_item(session, item); + + if (rv != 0) { + nghttp2_frame_priority_free(&frame->priority); + nghttp2_mem_free(mem, item); + + return rv; + } + + return 0; +} + +int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags, + int32_t stream_id, uint32_t error_code) { + (void)flags; + + if (stream_id == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + return nghttp2_session_add_rst_stream(session, stream_id, error_code); +} + +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) { + (void)flags; + + if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) { + return 0; + } + return nghttp2_session_add_goaway(session, last_stream_id, error_code, + opaque_data, opaque_data_len, + NGHTTP2_GOAWAY_AUX_NONE); +} + +int nghttp2_submit_shutdown_notice(nghttp2_session *session) { + if (!session->server) { + return NGHTTP2_ERR_INVALID_STATE; + } + if (session->goaway_flags) { + return 0; + } + return nghttp2_session_add_goaway(session, (1u << 31) - 1, NGHTTP2_NO_ERROR, + NULL, 0, + NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE); +} + +int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags, + const nghttp2_settings_entry *iv, size_t niv) { + (void)flags; + return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv); +} + +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) { + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_nv *nva_copy; + uint8_t flags_copy; + int32_t promised_stream_id; + int rv; + nghttp2_mem *mem; + (void)flags; + + mem = &session->mem; + + if (stream_id <= 0 || nghttp2_session_is_my_stream_id(session, stream_id)) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } + + /* All 32bit signed stream IDs are spent. */ + if (session->next_stream_id > INT32_MAX) { + return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE; + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + item->aux_data.headers.stream_user_data = promised_stream_user_data; + + frame = &item->frame; + + rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem); + if (rv < 0) { + nghttp2_mem_free(mem, item); + return rv; + } + + flags_copy = NGHTTP2_FLAG_END_HEADERS; + + promised_stream_id = (int32_t)session->next_stream_id; + session->next_stream_id += 2; + + nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy, stream_id, + promised_stream_id, nva_copy, nvlen); + + rv = nghttp2_session_add_item(session, item); + + if (rv != 0) { + nghttp2_frame_push_promise_free(&frame->push_promise, mem); + nghttp2_mem_free(mem, item); + + return rv; + } + + return promised_stream_id; +} + +int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + int32_t window_size_increment) { + int rv; + nghttp2_stream *stream = 0; + (void)flags; + + if (window_size_increment == 0) { + return 0; + } + if (stream_id == 0) { + rv = nghttp2_adjust_local_window_size( + &session->local_window_size, &session->recv_window_size, + &session->recv_reduction, &window_size_increment); + if (rv != 0) { + return rv; + } + } else { + stream = nghttp2_session_get_stream(session, stream_id); + if (!stream) { + return 0; + } + + rv = nghttp2_adjust_local_window_size( + &stream->local_window_size, &stream->recv_window_size, + &stream->recv_reduction, &window_size_increment); + if (rv != 0) { + return rv; + } + } + + if (window_size_increment > 0) { + if (stream_id == 0) { + session->consumed_size = + nghttp2_max(0, session->consumed_size - window_size_increment); + } else { + stream->consumed_size = + nghttp2_max(0, stream->consumed_size - window_size_increment); + } + + return nghttp2_session_add_window_update(session, 0, stream_id, + window_size_increment); + } + return 0; +} + +int nghttp2_session_set_local_window_size(nghttp2_session *session, + uint8_t flags, int32_t stream_id, + int32_t window_size) { + int32_t window_size_increment; + nghttp2_stream *stream; + int rv; + (void)flags; + + if (window_size < 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (stream_id == 0) { + window_size_increment = window_size - session->local_window_size; + + if (window_size_increment == 0) { + return 0; + } + + if (window_size_increment < 0) { + return nghttp2_adjust_local_window_size( + &session->local_window_size, &session->recv_window_size, + &session->recv_reduction, &window_size_increment); + } + + rv = nghttp2_increase_local_window_size( + &session->local_window_size, &session->recv_window_size, + &session->recv_reduction, &window_size_increment); + + if (rv != 0) { + return rv; + } + } else { + stream = nghttp2_session_get_stream(session, stream_id); + + if (stream == NULL) { + return 0; + } + + window_size_increment = window_size - stream->local_window_size; + + if (window_size_increment == 0) { + return 0; + } + + if (window_size_increment < 0) { + return nghttp2_adjust_local_window_size( + &stream->local_window_size, &stream->recv_window_size, + &stream->recv_reduction, &window_size_increment); + } + + rv = nghttp2_increase_local_window_size( + &stream->local_window_size, &stream->recv_window_size, + &stream->recv_reduction, &window_size_increment); + + if (rv != 0) { + return rv; + } + } + + if (window_size_increment > 0) { + return nghttp2_session_add_window_update(session, 0, stream_id, + window_size_increment); + } + + return 0; +} + +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) { + nghttp2_mem *mem; + uint8_t *buf, *p; + uint8_t *origin_copy; + uint8_t *field_value_copy; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_ext_altsvc *altsvc; + int rv; + (void)flags; + + mem = &session->mem; + + if (!session->server) { + return NGHTTP2_ERR_INVALID_STATE; + } + + if (2 + origin_len + field_value_len > NGHTTP2_MAX_PAYLOADLEN) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (stream_id == 0) { + if (origin_len == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + } else if (origin_len != 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + buf = nghttp2_mem_malloc(mem, origin_len + field_value_len + 2); + if (buf == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + p = buf; + + origin_copy = p; + if (origin_len) { + p = nghttp2_cpymem(p, origin, origin_len); + } + *p++ = '\0'; + + field_value_copy = p; + if (field_value_len) { + p = nghttp2_cpymem(p, field_value, field_value_len); + } + *p++ = '\0'; + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + rv = NGHTTP2_ERR_NOMEM; + goto fail_item_malloc; + } + + nghttp2_outbound_item_init(item); + + item->aux_data.ext.builtin = 1; + + altsvc = &item->ext_frame_payload.altsvc; + + frame = &item->frame; + frame->ext.payload = altsvc; + + nghttp2_frame_altsvc_init(&frame->ext, stream_id, origin_copy, origin_len, + field_value_copy, field_value_len); + + rv = nghttp2_session_add_item(session, item); + if (rv != 0) { + nghttp2_frame_altsvc_free(&frame->ext, mem); + nghttp2_mem_free(mem, item); + + return rv; + } + + return 0; + +fail_item_malloc: + nghttp2_mem_free(mem, buf); + + return rv; +} + +static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec, + const nghttp2_data_provider *data_prd) { + uint8_t flags = NGHTTP2_FLAG_NONE; + if (data_prd == NULL || data_prd->read_callback == NULL) { + flags |= NGHTTP2_FLAG_END_STREAM; + } + + if (pri_spec) { + flags |= NGHTTP2_FLAG_PRIORITY; + } + + return flags; +} + +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) { + uint8_t flags; + int rv; + + if (session->server) { + return NGHTTP2_ERR_PROTO; + } + + if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) { + rv = detect_self_dependency(session, -1, pri_spec); + if (rv != 0) { + return rv; + } + } else { + pri_spec = NULL; + } + + flags = set_request_flags(pri_spec, data_prd); + + return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen, + data_prd, stream_user_data); +} + +static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) { + uint8_t flags = NGHTTP2_FLAG_NONE; + if (data_prd == NULL || data_prd->read_callback == NULL) { + flags |= NGHTTP2_FLAG_END_STREAM; + } + return flags; +} + +int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd) { + uint8_t flags; + + if (stream_id <= 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } + + flags = set_response_flags(data_prd); + return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen, + data_prd, NULL); +} + +int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider *data_prd) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_data_aux_data *aux_data; + uint8_t nflags = flags & NGHTTP2_FLAG_END_STREAM; + nghttp2_mem *mem; + + mem = &session->mem; + + if (stream_id == 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + aux_data = &item->aux_data.data; + aux_data->data_prd = *data_prd; + aux_data->eof = 0; + aux_data->flags = nflags; + + /* flags are sent on transmission */ + nghttp2_frame_data_init(&frame->data, NGHTTP2_FLAG_NONE, stream_id); + + rv = nghttp2_session_add_item(session, item); + if (rv != 0) { + nghttp2_frame_data_free(&frame->data); + nghttp2_mem_free(mem, item); + return rv; + } + return 0; +} + +ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, + const nghttp2_settings_entry *iv, + size_t niv) { + if (!nghttp2_iv_check(iv, niv)) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (buflen < (niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH)) { + return NGHTTP2_ERR_INSUFF_BUFSIZE; + } + + return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv); +} + +int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, + uint8_t flags, int32_t stream_id, void *payload) { + int rv; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_mem *mem; + + mem = &session->mem; + + if (type <= NGHTTP2_CONTINUATION) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (!session->callbacks.pack_extension_callback) { + return NGHTTP2_ERR_INVALID_STATE; + } + + item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + nghttp2_outbound_item_init(item); + + frame = &item->frame; + nghttp2_frame_extension_init(&frame->ext, type, flags, stream_id, payload); + + rv = nghttp2_session_add_item(session, item); + if (rv != 0) { + nghttp2_frame_extension_free(&frame->ext); + nghttp2_mem_free(mem, item); + return rv; + } + + return 0; +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_submit.h b/iotkit-embedded/external_libs/nghttp2/nghttp2_submit.h new file mode 100644 index 0000000..4d35029 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_submit.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2_SUBMIT_H +#define NGHTTP2_SUBMIT_H + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" + +#endif /* NGHTTP2_SUBMIT_H */ diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2_version.c b/iotkit-embedded/external_libs/nghttp2/nghttp2_version.c new file mode 100644 index 0000000..1b21d39 --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2_version.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include "nghttp2.h" + +static nghttp2_info version = {NGHTTP2_VERSION_AGE, NGHTTP2_VERSION_NUM, + NGHTTP2_VERSION, NGHTTP2_PROTO_VERSION_ID}; + +nghttp2_info *nghttp2_version(int least_version) { + if (least_version > NGHTTP2_VERSION_NUM) + return NULL; + return &version; +} diff --git a/iotkit-embedded/external_libs/nghttp2/nghttp2ver.h b/iotkit-embedded/external_libs/nghttp2/nghttp2ver.h new file mode 100644 index 0000000..28ededc --- /dev/null +++ b/iotkit-embedded/external_libs/nghttp2/nghttp2ver.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#ifndef NGHTTP2VER_H +#define NGHTTP2VER_H + +/** + * @macro + * Version number of the nghttp2 library release + */ +#define NGHTTP2_VERSION "nghttp2" + +/** + * @macro + * Numerical representation of the version number of the nghttp2 library + * release. This is a 24 bit number with 8 bits for major number, 8 bits + * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. + */ +#define NGHTTP2_VERSION_NUM 0x013190 + +#endif /* NGHTTP2VER_H */ diff --git a/iotkit-embedded/extract.bat b/iotkit-embedded/extract.bat new file mode 100644 index 0000000..61d8cd6 --- /dev/null +++ b/iotkit-embedded/extract.bat @@ -0,0 +1,11 @@ +@echo off + +SET SHELLDIR=tools\prebuilt\windows\shell.w32-ix86 +SET SHELL=%SHELLDIR%/bash.exe +SET BASH=%SHELL% + +SET PATH=%SHELLDIR%;%PATH% + +"%SHELL%" extract.sh + +pause \ No newline at end of file diff --git a/iotkit-embedded/extract.sh b/iotkit-embedded/extract.sh new file mode 100644 index 0000000..6eea47d --- /dev/null +++ b/iotkit-embedded/extract.sh @@ -0,0 +1,387 @@ +#! /bin/bash + +# LOCK_PATTERN=bash_lock +# LOCK_FILE=${LOCK_PATTERN}.$$ + +# cleanup () +# { +# rm -f ${LOCK_FILE} +# } + +# trap cleanup EXIT + +# if [ "$(ls ${LOCK_PATTERN}.* 2>/dev/null)" = "" ];then +# echo "LOCK" > ${LOCK_FILE} +# else +# echo "Another Extract Script Is Running, Exit..." +# exit +# fi + +env_check() +{ + if [ "${OS}" = "Linux" ]; then + export PATH=tools/prebuilt/ubuntu/bin:${PATH} + fi + gawk --help > /dev/null 2>&1 + if [ "$?" != "0" ];then + echo "Please install gawk, using sudo apt-get install gawk for ubuntu 16.04" + exit + fi +} + +extract_from_cloud() +{ + OS=$(uname) + EXTRACT_ID=$(curl --connect-timeout 5 -sF "file=@make.settings" --url https://linkkit.aliyuncs.com/upload/config?pk=a1AuWIoEr4Z\&os=${OS}) + # echo ${EXTRACT_ID} + RETRY_COUNT=0 + if [ "${EXTRACT_ID}" != "" ];then + echo ". Download request sent, waiting respond ..." + sleep 2 + + while : + do + DOWNLOAD_FILE=$(curl -s --connect-timeout 5 https://linkkit.aliyuncs.com/get/linkkit?extractId=${EXTRACT_ID}) + # echo ${DOWNLOAD_FILE} + + if [ "${DOWNLOAD_FILE}" = "404" ] || [ "${DOWNLOAD_FILE}" = "" ];then + break + + elif [ "${DOWNLOAD_FILE}" = "406" ];then + echo ". Respond generating, wait longer" + + if [ "${RETRY_COUNT}" = "20" ];then + break + fi + + RETRY_COUNT=$[RETRY_COUNT+1] + + echo ". Retried ${RETRY_COUNT}/20" + sleep 2 + + else + + echo "" + curl ${DOWNLOAD_FILE} > output.zip + rm -rf output + unzip -q output.zip + rm -rf output.zip + echo "" + echo "Please pick up extracted source files in [${PWD}/${OUTPUT_DIR}]" + echo "" + # rm -rf ${LOCK_FILE} + exit + fi + done + fi +} + +OS="$(uname)" + +if [ "${OS}" = "Linux" ]; then + FIND="find -L" +else + FIND="find" +fi + +OUTPUT_DIR=output +INFRA_DIR=${OUTPUT_DIR}/eng/infra +WRAPPERS_DIR=${OUTPUT_DIR}/eng/wrappers + +XTRC_FILE_RULS=./tools/misc/xtrc_file_rules +TEMP_FILE_RULS="${PWD}/.temp_file_rule_filter" + +XTRC_WRAPPER_RULS=./tools/misc/xtrc_wrapper_rules +TEMP_WRAPPER_RULS="${PWD}/.temp_wrapper_rule_filter" +WRAPPER_DOC=./tools/misc/wrapper + +# Try Extract Linkkit From Cloud +# +if [ "$1" = "" ] || ( [ "$1" != "test" ] && [ "$1" != "local" ] ) then + extract_from_cloud +fi + +# environment check +env_check + +# Prepare Config Macro In make.settings +MACRO_LIST=$(sed -n '/#/!{/=y/p}' make.settings | sed -n 's/=y//gp' | sed -n 's/FEATURE_//gp') + +mkdir -p ${OUTPUT_DIR} ${OUTPUT_DIR}/examples +rm -rf $(${FIND} ${OUTPUT_DIR} -mindepth 1 -maxdepth 1|grep -v release) + +# Generate infra_config.h and extract necessary infra files +mkdir -p ${INFRA_DIR} +echo "#ifndef _INFRA_CONFIG_H_" > ${INFRA_DIR}/infra_config.h +echo -e "#define _INFRA_CONFIG_H_\n" >> ${INFRA_DIR}/infra_config.h +echo "${MACRO_LIST}" | sed -n 's/^/#define /p' >> ${INFRA_DIR}/infra_config.h +echo -e "\n#endif" >> ${INFRA_DIR}/infra_config.h + +${FIND} ./src -name "infra_types.h" | xargs -i cp -f {} ${INFRA_DIR} +${FIND} ./src -name "infra_defs.[ch]" | xargs -i cp -f {} ${INFRA_DIR} +${FIND} ./src -name "infra_list.h" | xargs -i cp -f {} ${INFRA_DIR} +${FIND} ./src -name "infra_compat.[ch]" | xargs -i cp -f {} ${INFRA_DIR} + +# echo -e "${MACRO_LIST}" + +cond_and_check() +{ + COND_AND_VAR=$(echo $1 | gawk -F '&' '{for(i=1;i<=NF;i++){print $i;}}') + # echo "${COND_AND_VAR}" + for item in ${COND_AND_VAR} + do + echo ${MACRO_LIST} | grep -wo ${item} > /dev/null + if [ $? -ne 0 ];then + return 1 + fi + done + return 0 +} + +cond_not_check() +{ + COND_NOT_VAR=$(echo $1 | gawk -F '&' '{for(i=1;i<=NF;i++){print $i;}}') + # echo "${COND_AND_VAR}" + for item in ${COND_NOT_VAR} + do + echo ${MACRO_LIST} | grep -wo ${item} > /dev/null + if [ $? -eq 0 ];then + return 0 + fi + done + return 1 +} + +DOTS_LINE=".................................................................." + +extract_file_by() +{ + local rule="$*" + + COND_AND=$(echo $rule | gawk -F'|' '{print $1}') + COND_NOT=$(echo $rule | gawk -F'|' '{print $2}') + SRC_DIR=$(echo $rule | gawk -F'|' '{print $3}') + DEST_DIR=$(echo $rule | gawk -F'|' '{print $4}') + + # echo "${COND_AND}" + cond_and_check "${COND_AND}" + if [ $? -ne 0 ]; then + return 1 + fi + + # echo "${COND_NOT}" + cond_not_check "${COND_NOT}" + if [ $? -eq 0 ]; then + return 1 + fi + + # echo "${SRC_DIR}" + # echo "${DEST_DIR}" + + if [ "${DEST_DIR}" != "" ];then + mkdir -p ${DEST_DIR} && ${FIND} ${SRC_DIR} -maxdepth 1 -name *.[ch] | xargs -i cp -rf {} ${DEST_DIR} + fi +} + +echo "" +echo "Analysing extract rules for sources and wrappers ..." +echo "" + +SWITCHES=$(cat make.settings | grep -v '^#' | sed '/^$/d;s:FEATURE_::g;s:=.*::g') +SWCH_PAT="$(echo ${SWITCHES}|sed 's: :\\\|:g')" +SPEC_PAT="$(echo ${SWITCHES}|sed 's:\([_A-Z]*\) :^\1||\\\|:g')" +SPEC_PAT="${SPEC_PAT}||" + +grep ${SWCH_PAT} ${XTRC_FILE_RULS} > ${TEMP_FILE_RULS} +grep ${SWCH_PAT} ${XTRC_WRAPPER_RULS} > ${TEMP_WRAPPER_RULS} + +FUNC_NAME_LIST="" +HEADER_FILE_LIST="" + +FUNC_NAME_LIST=$(grep "${SPEC_PAT}" ${TEMP_WRAPPER_RULS}|gawk -F '|' '{ print $3 }'|sort -u) +HEADER_FILE_LIST=$(grep "${SPEC_PAT}" ${TEMP_WRAPPER_RULS}|gawk -F '|' '{ print $4 }'|sort -u) + +FUNC_PAT="$(echo ${FUNC_NAME_LIST}|sed 's: :\\\|:g')" +HDER_PAT="$(echo ${HEADER_FILE_LIST}|sed 's: :\\\|:g')" + +# [ "${FUNC_PAT}" != "" ] && sed -i "/${FUNC_PAT}/d" ${TEMP_WRAPPER_RULS} +# [ "${HDER_PAT}" != "" ] && sed -i "/${HDER_PAT}/d" ${TEMP_WRAPPER_RULS} + +if [ "${FUNC_PAT}" != "" ] && [ "${HDER_PAT}" != "" ]; then + sed -i "/${FUNC_PAT}/{/${HDER_PAT}/d}" ${TEMP_WRAPPER_RULS} +fi + +printf "Interpret [%03d] sources rules" $(cat ${TEMP_FILE_RULS}|wc -l|sed 's/[[:space:]]//g') +printf " from [%03d] base\n" $(cat ${XTRC_FILE_RULS}|wc -l|sed 's/[[:space:]]//g') + +printf "Interpret [%03d] wrapper rules" $(cat ${TEMP_WRAPPER_RULS}|wc -l|sed 's/[[:space:]]//g') +printf " from [%03d] base" $(cat ${XTRC_WRAPPER_RULS}|wc -l|sed 's/[[:space:]]//g') + +echo "" + +FUNC_NAME_LIST="$(echo ${FUNC_NAME_LIST}|tr ' ' '\n')\n" +HEADER_FILE_LIST="$(echo ${HEADER_FILE_LIST}|tr ' ' '\n')\n" + +echo "" +# Read xtrc_file_rules +TOTAL_ITERATION=$(wc -l ${TEMP_FILE_RULS}|gawk '{ print $1 }') +ITER=0 + +while read rule +do + ITER=$(( ${ITER} + 1 )) + printf "\r%.40s %.2f%%" "Extract Files ${DOTS_LINE}" $(echo 100*${ITER}/${TOTAL_ITERATION}|bc -l) + TEST=$(echo $rule | gawk -F'|' '{print NF}') + if [ ${TEST} -ne 4 ];then + continue + fi + + if [ "${OS}" = "Linux" ]; then + extract_file_by ${rule} & + else + extract_file_by ${rule} + fi + +done < ${TEMP_FILE_RULS} + +[ "${OS}" = "Linux" ] && wait + +rm -f ${TEMP_FILE_RULS} +echo -e "" + +# Generate wrapper.c +mkdir -p ${WRAPPERS_DIR} +cp -f wrappers/wrappers_defs.h ${WRAPPERS_DIR}/ + +# Read xtrc_wrapper_rules +TOTAL_ITERATION=$(wc -l ${TEMP_WRAPPER_RULS}|gawk '{ print $1 }') +ITER=0 + +while read rule +do + ITER=$(( ${ITER} + 1 )) + printf "\r%.40s %.2f%%" "Extract HAL/Wrapper Functions ${DOTS_LINE}" $(echo 100*${ITER}/${TOTAL_ITERATION}|bc -l) + TEST=$(echo $rule | gawk -F'|' '{print NF}') + if [ ${TEST} -ne 4 ];then + continue + fi + + COND_AND=$(echo $rule | gawk -F'|' '{print $1}') + COND_NOT=$(echo $rule | gawk -F'|' '{print $2}') + FUNC_NAME=$(echo $rule | gawk -F'|' '{print $3}') + HEADER_FILE=$(echo $rule | gawk -F'|' '{print $4}') + + # echo "${COND_AND}" + cond_and_check "${COND_AND}" + if [ $? -ne 0 ];then + continue + fi + + # echo "${COND_NOT}" + cond_not_check "${COND_NOT}" + if [ $? -eq 0 ];then + continue + fi + + if [ "${FUNC_NAME}" != "" ];then + FUNC_NAME_LIST="${FUNC_NAME_LIST}""${FUNC_NAME}\n" + fi + if [ "${HEADER_FILE}" != "" ];then + HEADER_FILE_LIST="${HEADER_FILE_LIST}""${HEADER_FILE}\n" + fi +done < ${TEMP_WRAPPER_RULS} +rm -f ${TEMP_WRAPPER_RULS} + +echo -e "" + +FUNC_NAME_LIST=$(echo -e "${FUNC_NAME_LIST}" | sed -n '/^$/!{p}' | sort -u) +HEADER_FILE_LIST=$(echo -e "${HEADER_FILE_LIST}" | sed -n '/^$/!{p}' | sort -u) + +# For Debug +if [ "${FUNC_NAME_LIST}" != "" ];then + echo -e "\nHAL/Wrapper Function List:" && echo -e "${FUNC_NAME_LIST}" |gawk '{ printf("%03d %s\n", NR, $0); }' +fi + +if [ "${HEADER_FILE_LIST}" != "" ];then + echo -e "\nHAL/Wrapper Header File List:" && echo -e "${HEADER_FILE_LIST}" |gawk '{ printf("%03d %s\n", NR, $0); }' +fi + +# Annotation For wrapper.c +sed -n '/WRAPPER_NOTE:/{:a;N;/*\//!ba;p}' ${WRAPPER_DOC} | sed -n '1d;p' >> ${WRAPPERS_DIR}/wrapper.c + +# Output Header File Into wrapper.c +echo -e "#include \"infra_types.h\"" >> ${WRAPPERS_DIR}/wrapper.c +echo -e "#include \"infra_defs.h\"" >> ${WRAPPERS_DIR}/wrapper.c +echo -e "#include \"infra_compat.h\"" >> ${WRAPPERS_DIR}/wrapper.c +echo -e "#include \"wrappers_defs.h\"" >> ${WRAPPERS_DIR}/wrapper.c +echo -e "${HEADER_FILE_LIST}" | sed -n '/.h/{s/^/#include "/p}' | sed -n 's/$/"/p' >> ${WRAPPERS_DIR}/wrapper.c +echo -e "" >> ${WRAPPERS_DIR}/wrapper.c + +# Generate Default Implenmentation For HAL/Wrapper Function +echo "" +TOTAL_ITERATION=$(echo "${FUNC_NAME_LIST}"|wc -w|sed 's/[[:space:]]//g') +ITER=0 + +for func in $(echo "${FUNC_NAME_LIST}") +do + ITER=$(( ${ITER} + 1 )) + printf "\r%.40s %.2f%%" "Generate wrapper.c ${DOTS_LINE}" $(echo 100*${ITER}/${TOTAL_ITERATION}|bc -l) + + # echo ${func} + if [ "${func}" = "" ];then + continue + fi + + FUNC_DEC=$(${FIND} ./${OUTPUT_DIR}/eng -name *wrapper.h | xargs -i cat {}) + FUNC_DEC=$(echo "${FUNC_DEC}" | sed -n '/.*'${func}'(.*/{/.*);/ba;{:c;N;/.*);/!bc};:a;p;q}') + + DATA_TYPE=$(echo "${FUNC_DEC}" | head -1 | gawk -F' ' '{if ($1~/^DLL/ || $1~/extern/) {if ($3~/*/) {print $2"*";} else {print $2;}} else {if ($2~/*/) {print $1"*";} else {print $1;}}}'# | sed s/[[:space:]]//g) + # echo -e "\n${DATA_TYPE}" + + sed -n '/'${func}':/{:a;N;/*\//!ba;p}' ${WRAPPER_DOC} | sed -n '1d;p' >> ${WRAPPERS_DIR}/wrapper.c + + if [ "${DATA_TYPE}" = "void" ];then + echo "${FUNC_DEC}" | sed -n '/;/{s/;/\n{\n\treturn;\n}\n\n/g};p' >> ${WRAPPERS_DIR}/wrapper.c + else + echo "${FUNC_DEC}" | sed -n '/;/{s/;/\n{\n\treturn ('${DATA_TYPE}')1;\n}\n\n/g};p' >> ${WRAPPERS_DIR}/wrapper.c + fi +done + +if [ "${TOTAL_ITERATION}" = "0" ]; then + echo "Only [dev_sign] enabled, so NO function requires being implemented in [${WRAPPERS_DIR}/wrapper.c]" +else + echo "" +fi + +echo -e "#ifndef _SDK_INCLUDE_H_" > ${OUTPUT_DIR}/eng/sdk_include.h +echo -e "#define _SDK_INCLUDE_H_\n" >> ${OUTPUT_DIR}/eng/sdk_include.h +echo -e "#include \"infra_types.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h +echo -e "#include \"infra_defs.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h +echo -e "#include \"infra_compat.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h +echo -e "#include \"wrappers_defs.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h +find ${OUTPUT_DIR}/eng -name "*wrapper.h" | gawk -F'/' '{print $NF}' | sed -n 's/^/#include "/g;s/$/"/gp' >> ${OUTPUT_DIR}/eng/sdk_include.h +find ${OUTPUT_DIR}/eng -name "*api.h" | gawk -F'/' '{print $NF}' | sed -n 's/^/#include "/g;s/$/"/gp' >> ${OUTPUT_DIR}/eng/sdk_include.h +echo -e "\n#endif" >> ${OUTPUT_DIR}/eng/sdk_include.h + +# if echo "${SWITCHES}"|grep -qw "DEVICE_MODEL_ENABLED"; then +# echo "" +# bash tools/misc/compose.sh ${PWD}/output/examples/linkkit_example_auto.c +# fi + +echo "" +echo "Please pick up extracted source files in [${PWD}/${OUTPUT_DIR}]" +echo "" + +cp tools/misc/makefile.output output/Makefile +if [ "${1}" = "test" ];then + ENV_TEST=$(cat .config 2>/dev/null| sed -n '/VENDOR/{s/[[:space:]]//gp}'| gawk -F ':' '{print $2}') + if [ "${ENV_TEST}" = "ubuntu" ];then + rm -f ${WRAPPERS_DIR}/wrapper.c + cp -rf wrappers/os/ubuntu ${WRAPPERS_DIR}/ + cp -rf wrappers/tls ${WRAPPERS_DIR}/ + cp -rfl external_libs ${WRAPPERS_DIR}/ + rm -f ${WRAPPERS_DIR}/ubuntu/HAL_UART_linux.c + fi +fi + +# rm -rf ${LOCK_FILE} diff --git a/iotkit-embedded/make.settings b/iotkit-embedded/make.settings index 84c4854..b2fcb7c 100644 --- a/iotkit-embedded/make.settings +++ b/iotkit-embedded/make.settings @@ -1,11 +1,88 @@ -FEATURE_MQTT_COMM_ENABLED = y -FEATURE_MQTT_DIRECT = y -FEATURE_MQTT_DIRECT_NOTLS = n -FEATURE_MQTT_DIRECT_NOITLS = y -FEATURE_COAP_COMM_ENABLED = n -FEATURE_HTTP_COMM_ENABLED = y -FEATURE_SUBDEVICE_ENABLED = n -FEATURE_CMP_ENABLED = y -FEATURE_DM_ENABLED = y -FEATURE_SERVICE_OTA_ENABLED = y +# +# Automatically generated file; DO NOT EDIT. +# Main Menu +# +# +# Configure C-SDK for IoT Embedded Devices +# +FEATURE_PLATFORM_HAS_STDINT=y +FEATURE_PLATFORM_HAS_DYNMEM=y +# FEATURE_PLATFORM_HAS_OS is not set +FEATURE_INFRA_STRING=y +FEATURE_INFRA_NET=y +FEATURE_INFRA_LIST=y +FEATURE_INFRA_LOG_NETWORK_PAYLOAD=y +FEATURE_INFRA_LOG=y + +# +# Log Configurations +# +FEATURE_INFRA_LOG_ALL_MUTED=y +FEATURE_INFRA_LOG_MUTE_FLW=y +FEATURE_INFRA_LOG_MUTE_DBG=y +FEATURE_INFRA_LOG_MUTE_INF=y +FEATURE_INFRA_LOG_MUTE_WRN=y +FEATURE_INFRA_LOG_MUTE_ERR=y +FEATURE_INFRA_LOG_MUTE_CRT=y +# FEATURE_INFRA_MEM_STATS is not set +FEATURE_INFRA_TIMER=y +# FEATURE_INFRA_RANDOM is not set +# FEATURE_INFRA_JSON_PARSER is not set +FEATURE_INFRA_CJSON=y +# FEATURE_INFRA_MD5 is not set +# FEATURE_INFRA_SHA1 is not set +FEATURE_INFRA_SHA256=y +FEATURE_INFRA_REPORT=y +# FEATURE_INFRA_HTTPC is not set +FEATURE_INFRA_COMPAT=y +FEATURE_INFRA_CLASSIC=y +# FEATURE_INFRA_PREAUTH is not set +# FEATURE_INFRA_AES is not set +FEATURE_DEV_SIGN=y +FEATURE_MQTT_COMM_ENABLED=y + +# +# MQTT Configurations +# +FEATURE_MQTT_DEFAULT_IMPL=y +# FEATURE_MQTT_PRE_AUTH is not set +FEATURE_MQTT_DIRECT=y +# FEATURE_ASYNC_PROTOCOL_STACK is not set +# FEATURE_DYNAMIC_REGISTER is not set +FEATURE_DEVICE_MODEL_CLASSIC=y +FEATURE_LOG_REPORT_TO_CLOUD=y +FEATURE_DEVICE_MODEL_ENABLED=y + +# +# Device Model Configurations +# +# FEATURE_DEVICE_MODEL_GATEWAY is not set +# FEATURE_DEPRECATED_LINKKIT is not set +# FEATURE_DEVICE_MODEL_RAWDATA_SOLO is not set +# FEATURE_ALCS_ENABLED is not set +# FEATURE_SUB_PERSISTENCE_ENABLED is not set +# FEATURE_DEVICE_MODEL_SHADOW is not set +# FEATURE_HAL_KV is not set +# FEATURE_SUPPORT_TLS is not set +# FEATURE_HAL_CRYPTO is not set +# FEATURE_HAL_UDP is not set +# FEATURE_COAP_DTLS_SUPPORT is not set +# FEATURE_ATM_ENABLED is not set +# FEATURE_OTA_ENABLED is not set +# FEATURE_COAP_COMM_ENABLED is not set +# FEATURE_COAP_PACKET is not set +# FEATURE_COAP_CLIENT is not set +# FEATURE_COAP_SERVER is not set +# FEATURE_DEV_RESET is not set +# FEATURE_HTTP_COMM_ENABLED is not set +# FEATURE_HTTP2_COMM_ENABLED is not set +# FEATURE_FS_ENABLED is not set +# FEATURE_AWSS_SUPPORT_APLIST is not set +# FEATURE_AWSS_DISABLE_ENROLLEE is not set +# FEATURE_AWSS_DISABLE_REGISTRAR is not set +# FEATURE_AWSS_SUPPORT_ADHA is not set +# FEATURE_AWSS_FRAMEWORKS is not set +# FEATURE_WIFI_PROVISION_ENABLED is not set +# FEATURE_AWSS_SUPPORT_SMARTCONFIG_WPS is not set +# FEATURE_DEV_BIND_ENABLED is not set diff --git a/iotkit-embedded/makefile b/iotkit-embedded/makefile index ccadb5d..00c5c08 100644 --- a/iotkit-embedded/makefile +++ b/iotkit-embedded/makefile @@ -1,34 +1,37 @@ -include project.mk +include tools/project.mk include make.settings -include src/configs/default_settings.mk -include src/scripts/parse_make_settings.mk +include tools/default_settings.mk +include tools/parse_make_settings.mk +include $(RULE_DIR)/funcs.mk -# CFLAGS += -DTEST_MQTT_DAILY -# CFLAGS += -DTEST_HTTP_DAILY -# CFLAGS += -DTEST_COAP_DAILY -# CFLAGS += -DTEST_OTA_PRE # CFLAGS += -DINSPECT_MQTT_FLOW -include src/scripts/mock_build_options.mk - COMP_LIB := libiot_sdk.a COMP_LIB_COMPONENTS := \ - src/utils \ - src/log \ - src/system \ + src/infra \ + src/dev_sign \ + +$(call CompLib_Map, FEATURE_MQTT_COMM_ENABLED, src/mqtt) +$(call CompLib_Map, FEATURE_COAP_CLIENT, src/coap) +$(call CompLib_Map, FEATURE_COAP_SERVER, src/coap) +$(call CompLib_Map, FEATURE_SUPPORT_TLS, certs) +$(call CompLib_Map, FEATURE_COAP_DTLS_SUPPORT, certs) +$(call CompLib_Map, FEATURE_DYNAMIC_REGISTER, src/dynamic_register) +$(call CompLib_Map, FEATURE_ATM_ENABLED, src/atm) +$(call CompLib_Map, FEATURE_DEV_RESET, src/dev_reset) +$(call CompLib_Map, FEATURE_OTA_ENABLED, src/ota) +$(call CompLib_Map, FEATURE_DEVICE_MODEL_ENABLED, src/dev_model) +$(call CompLib_Map, FEATURE_HTTP_COMM_ENABLED, src/http) +$(call CompLib_Map, FEATURE_DEV_BIND_ENABLED, src/dev_bind) +$(call CompLib_Map, FEATURE_WIFI_PROVISION_ENABLED, src/wifi_provision) +$(call CompLib_Map, FEATURE_HTTP2_COMM_ENABLED, src/http2) + +SUBDIRS += wrappers +SUBDIRS += external_libs/mbedtls +SUBDIRS += tests + +$(call Append_Conditional, SUBDIRS, external_libs/nghttp2, HTTP2_COMM_ENABLED) -$(call CompLib_Map, MQTT_COMM_ENABLED, \ - src/mqtt \ -) -$(call CompLib_Map, OTA_ENABLED, src/ota) -$(call CompLib_Map, MQTT_SHADOW, src/shadow) -$(call CompLib_Map, COAP_COMM_ENABLED, src/coap) -$(call CompLib_Map, MQTT_ID2_AUTH, src/tfs) -$(call CompLib_Map, HTTP_COMM_ENABLED, src/http) -$(call CompLib_Map, SUBDEVICE_ENABLED, src/subdev) -$(call CompLib_Map, CLOUD_CONN_ENABLED, src/cloud_conn) -$(call CompLib_Map, CMP_ENABLED, src/cmp) -$(call CompLib_Map, DM_ENABLED, src/dm) -$(call CompLib_Map, SERVICE_OTA_ENABLED, src/fota) -$(call CompLib_Map, SERVICE_OTA_ENABLED, src/cota) include $(RULE_DIR)/rules.mk +include tools/mock_build_options.mk + diff --git a/iotkit-embedded/model.json b/iotkit-embedded/model.json new file mode 100644 index 0000000..9989387 --- /dev/null +++ b/iotkit-embedded/model.json @@ -0,0 +1,222 @@ +{ + "schema":"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json", + "profile":{ + "productKey":"a1h88DsZIaY" + }, + "services":[ + { + "outputData":[ + + ], + "identifier":"set", + "inputData":[ + { + "identifier":"LightStatus", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"打开" + }, + "type":"bool" + }, + "name":"工作状态" + }, + { + "identifier":"LightAdjustLevel", + "dataType":{ + "specs":{ + "unit":"%", + "min":"0", + "max":"100", + "step":"1" + }, + "type":"int" + }, + "name":"调光等级" + }, + { + "identifier":"LightAlias", + "dataType":{ + "specs":{ + "length":"32" + }, + "type":"text" + }, + "name":"别名" + } + ], + "method":"thing.service.property.set", + "name":"set", + "required":true, + "callType":"async", + "desc":"属性设置" + }, + { + "outputData":[ + { + "identifier":"LightStatus", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"打开" + }, + "type":"bool" + }, + "name":"工作状态" + }, + { + "identifier":"LightAdjustLevel", + "dataType":{ + "specs":{ + "unit":"%", + "min":"0", + "max":"100", + "step":"1" + }, + "type":"int" + }, + "name":"调光等级" + }, + { + "identifier":"LightAlias", + "dataType":{ + "specs":{ + "length":"32" + }, + "type":"text" + }, + "name":"别名" + } + ], + "identifier":"get", + "inputData":[ + "LightStatus", + "LightAdjustLevel", + "LightAlias" + ], + "method":"thing.service.property.get", + "name":"get", + "required":true, + "callType":"async", + "desc":"属性获取" + } + ], + "properties":[ + { + "identifier":"LightStatus", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"打开" + }, + "type":"bool" + }, + "name":"工作状态", + "accessMode":"rw", + "required":false + }, + { + "identifier":"LightAdjustLevel", + "dataType":{ + "specs":{ + "unit":"%", + "min":"0", + "max":"100", + "step":"1" + }, + "type":"int" + }, + "name":"调光等级", + "accessMode":"rw", + "required":false, + "desc":"调光等级采用百分比表示" + }, + { + "identifier":"LightAlias", + "dataType":{ + "specs":{ + "length":"32" + }, + "type":"text" + }, + "name":"别名", + "accessMode":"rw", + "required":false + } + ], + "events":[ + { + "outputData":[ + { + "identifier":"LightStatus", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"打开" + }, + "type":"bool" + }, + "name":"工作状态" + }, + { + "identifier":"LightAdjustLevel", + "dataType":{ + "specs":{ + "unit":"%", + "min":"0", + "max":"100", + "step":"1" + }, + "type":"int" + }, + "name":"调光等级" + }, + { + "identifier":"LightAlias", + "dataType":{ + "specs":{ + "length":"32" + }, + "type":"text" + }, + "name":"别名" + } + ], + "identifier":"post", + "method":"thing.event.property.post", + "name":"post", + "type":"info", + "required":true, + "desc":"属性上报" + }, + { + "outputData":[ + { + "identifier":"ErrorCode", + "dataType":{ + "specs":{ + "0":"恢复正常" + }, + "type":"enum" + }, + "name":"故障代码" + } + ], + "identifier":"Error", + "method":"thing.event.Error.post", + "name":"故障上报", + "type":"alert", + "required":false + }, + { + "outputData":[ + + ], + "identifier":"TamperAlarm", + "method":"thing.event.TamperAlarm.post", + "name":"防撬报警", + "type":"alert", + "required":false + } + ] +} diff --git a/iotkit-embedded/project.mk b/iotkit-embedded/project.mk deleted file mode 100644 index c45c066..0000000 --- a/iotkit-embedded/project.mk +++ /dev/null @@ -1,17 +0,0 @@ -# Settings of input directory -# -TOP_DIR := $(CURDIR) -RULE_DIR := $(TOP_DIR)/build-rules -CONFIG_DIR := $(TOP_DIR)/src/configs -SCRIPT_DIR := $(TOP_DIR)/src/scripts -PACKAGE_DIR := $(TOP_DIR)/src/packages -IMPORT_DIR := $(TOP_DIR)/src/import - -# Settings of output directory -# -DIST_DIR := $(TOP_DIR)/output -FINAL_DIR := $(DIST_DIR)/release - -# Settings of project info -PRJ_NAME := iotkit-embedded -PRJ_VERSION := V2.02 diff --git a/iotkit-embedded/sample/CMakeLists.txt b/iotkit-embedded/sample/CMakeLists.txt deleted file mode 100644 index 6007937..0000000 --- a/iotkit-embedded/sample/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -add_subdirectory(http) -add_subdirectory(mqtt) -add_subdirectory(ota) -add_subdirectory(device-shadow) -if(FEATURE_SUBDEVICE_ENABLED) - add_subdirectory(subdev) -endif(FEATURE_SUBDEVICE_ENABLED) -if(FEATURE_CMP_ENABLED) - add_subdirectory(cmp) - if(FEATURE_DM_ENABLED) - add_subdirectory(linkkit) - endif(FEATURE_DM_ENABLED) -endif(FEATURE_CMP_ENABLED) -if(NOT WIN32) - add_subdirectory(coap) -endif(NOT WIN32) diff --git a/iotkit-embedded/sample/cmp/CMakeLists.txt b/iotkit-embedded/sample/cmp/CMakeLists.txt deleted file mode 100644 index 25102f2..0000000 --- a/iotkit-embedded/sample/cmp/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_executable(cmp-example cmp-example.c) -target_link_libraries(cmp-example iot_sdk) diff --git a/iotkit-embedded/sample/cmp/cmp-example.c b/iotkit-embedded/sample/cmp/cmp-example.c deleted file mode 100644 index cc6b9b7..0000000 --- a/iotkit-embedded/sample/cmp/cmp-example.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include - -#include "lite-utils.h" - -#include "iot_import.h" -#include "iot_export.h" - -#ifdef ON_DAILY -#define IOTX_PRODUCT_KEY "gsYfsxQJgeD" -#define IOTX_DEVICE_NAME "DailyEnvDN" -#define IOTX_DEVICE_SECRET "y1vzFkEgcuXnvkAfm627pwarx4HRNikX" -#define IOTX_PRODUCT_SECRET "" -#define IOTX_DEVICE_ID "IoTxHttpTestDev_001" -#else -#define IOTX_PRODUCT_KEY "a1grYGVCPWl" -#define IOTX_DEVICE_NAME "0402_09" -#define IOTX_DEVICE_SECRET "DocxiD5wS6x9HNZrbC2CAoi9UnYP74Xt" -#define IOTX_PRODUCT_SECRET "" -#define IOTX_DEVICE_ID "IoTxHttpTestDev_001" -#endif - - -/* These are pre-defined topics */ -#define TOPIC_UPDATE "/"IOTX_PRODUCT_KEY"/"IOTX_DEVICE_NAME"/update" -#define TOPIC_DATA "/"IOTX_PRODUCT_KEY"/"IOTX_DEVICE_NAME"/data" - - -#define MQTT_MSGLEN (1024) - -#define EXAMPLE_TRACE(fmt, ...) \ - do { \ - HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ - HAL_Printf(fmt, ##__VA_ARGS__); \ - HAL_Printf("%s", "\r\n"); \ - } while(0) - - -static void _register_func(iotx_cmp_send_peer_pt source, iotx_cmp_message_info_pt msg, void *user_data) -{ - printf("source %s:%s\n", source->product_key, source->device_name); - - printf("type %d\n", msg->message_type); - printf("URI %s\n", msg->URI); - printf("URI_type %d\n", msg->URI_type); - printf("code %d\n", msg->code); - printf("id %d\n", msg->id); - printf("method %s\n", msg->method); - printf("parameter %s\n", (char*)msg->parameter); -} - - -static void _event_handle(void *pcontext, iotx_cmp_event_msg_pt msg, void *user_data) -{ - printf("event %d\n", msg->event_id); - - if (IOTX_CMP_EVENT_REGISTER_RESULT == msg->event_id) { - iotx_cmp_event_result_pt result = (iotx_cmp_event_result_pt)msg->msg; - - printf("register result\n"); - printf("result %d\n", result->result); - printf("URI %s\n", result->URI); - printf("URI_type %d\n", result->URI_type); - } else if (IOTX_CMP_EVENT_UNREGISTER_RESULT == msg->event_id) { - iotx_cmp_event_result_pt result = (iotx_cmp_event_result_pt)msg->msg; - - printf("unregister result\n"); - printf("result %d\n", result->result); - printf("URI %s\n", result->URI); - printf("URI_type %d\n", result->URI_type); - } else if (IOTX_CMP_EVENT_NEW_DATA_RECEIVED == msg->event_id) { - iotx_cmp_new_data_pt new_data = (iotx_cmp_new_data_pt)msg->msg; - _register_func(new_data->peer, new_data->message_info, user_data); - } -} - - - -int cmp_client() -{ - int rc = -1; - int user_data = 10; - iotx_cmp_init_param_t param = {0}; - iotx_cmp_register_param_t register_param = {0}; - iotx_cmp_send_peer_t cloud_peer; - iotx_cmp_message_info_t message_info = {0}; - iotx_cmp_unregister_param_t unregister_param = {0}; - - param.domain_type = IOTX_CMP_CLOUD_DOMAIN_SH; - - param.event_func = _event_handle; - param.user_data = &user_data; -#ifdef SUPPORT_PRODUCT_SECRET - param.secret_type = IOTX_CMP_DEVICE_SECRET_PRODUCT; -#else - param.secret_type = IOTX_CMP_DEVICE_SECRET_DEVICE; -#endif /* SUPPORT_PRODUCT_SECRET */ - printf("init\n"); - rc = IOT_CMP_Init(¶m, NULL); - - if (FAIL_RETURN == rc) { - printf("init fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } - - printf("register\n"); - register_param.URI_type = IOTX_CMP_URI_UNDEFINE; - register_param.URI = TOPIC_DATA; - register_param.message_type = IOTX_CMP_MESSAGE_REQUEST; - register_param.register_func = _register_func; - register_param.user_data = &user_data; - rc = IOT_CMP_Register(®ister_param, NULL); - - if (FAIL_RETURN == rc) { - printf("register fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } - - printf("register success \n"); - -#ifndef CMP_SUPPORT_MULTI_THREAD - rc = IOT_CMP_Yield(200, NULL); - if (FAIL_RETURN == rc) { - printf("yield fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } -#else - HAL_SleepMs(2000); -#endif - - printf("send\n"); - memset(&cloud_peer, 0x0, sizeof(iotx_cmp_send_peer_t)); - strncpy(cloud_peer.product_key, IOTX_PRODUCT_KEY, strlen(IOTX_PRODUCT_KEY)); - strncpy(cloud_peer.device_name, IOTX_DEVICE_NAME, strlen(IOTX_DEVICE_NAME)); - - message_info.id = 0; - message_info.message_type = IOTX_CMP_MESSAGE_REQUEST; - message_info.URI = LITE_malloc(strlen(TOPIC_DATA) + 1); - memset(message_info.URI, 0x0, strlen(TOPIC_DATA) + 1); - strncpy(message_info.URI, TOPIC_DATA, strlen(TOPIC_DATA)); - message_info.URI_type = IOTX_CMP_URI_UNDEFINE; - message_info.method = LITE_malloc(strlen("thing.data") + 1); - memset(message_info.method, 0x0, strlen("thing.data") + 1); - strncpy(message_info.method, "thing.data", strlen("thing.data")); - message_info.parameter = LITE_malloc(strlen("{hello world!}") + 1); - memset(message_info.parameter, 0x0, strlen("{hello world!}") + 1); - strncpy(message_info.parameter, "{hello world!}", strlen("{hello world!}")); - message_info.parameter_length = strlen(message_info.parameter); - - rc = IOT_CMP_Send(&cloud_peer, &message_info, NULL); - - LITE_free(message_info.URI); - LITE_free(message_info.method); - LITE_free(message_info.parameter); - - if (FAIL_RETURN == rc) { - printf("send fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } - -#ifndef CMP_SUPPORT_MULTI_THREAD - rc = IOT_CMP_Yield(200, NULL); - if (FAIL_RETURN == rc) { - printf("register fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } -#else - HAL_SleepMs(2000); -#endif - - - printf("unregister\n"); - unregister_param.URI_type = IOTX_CMP_URI_UNDEFINE; - unregister_param.URI = TOPIC_DATA; - rc = IOT_CMP_Unregister(&unregister_param, NULL); - if (FAIL_RETURN == rc) { - printf("unregister fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } - -#ifndef CMP_SUPPORT_MULTI_THREAD - rc = IOT_CMP_Yield(200, NULL); - if (FAIL_RETURN == rc) { - printf("register fail\n"); - IOT_CMP_Deinit(NULL); - return FAIL_RETURN; - } -#else - HAL_SleepMs(2000); -#endif - - IOT_CMP_Deinit(NULL); - - return SUCCESS_RETURN; -} - - -int main(int argc, char **argv) -{ - IOT_OpenLog("cmp\n"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - /**< set device info*/ - HAL_SetProductKey(IOTX_PRODUCT_KEY); - HAL_SetDeviceName(IOTX_DEVICE_NAME); -#ifndef SUPPORT_PRODUCT_SECRET - HAL_SetDeviceSecret(IOTX_DEVICE_SECRET); -#else - HAL_SetProductSecret(IOTX_PRODUCT_SECRET); -#endif /**< SUPPORT_PRODUCT_SECRET*/ - /**< end*/ - EXAMPLE_TRACE("start!\n"); - - cmp_client(); - - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - EXAMPLE_TRACE("out of sample!\n"); - - return 0; -} - diff --git a/iotkit-embedded/sample/coap/CMakeLists.txt b/iotkit-embedded/sample/coap/CMakeLists.txt deleted file mode 100644 index b63342e..0000000 --- a/iotkit-embedded/sample/coap/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -include_directories(${PROJECT_SOURCE_DIR}/src/sdk-impl) - -file(GLOB C_SOURCES "*.c") -add_executable(coap-example ${C_SOURCES}) -target_link_libraries(coap-example iot_sdk) diff --git a/iotkit-embedded/sample/coap/coap-example.c b/iotkit-embedded/sample/coap/coap-example.c deleted file mode 100644 index 8631581..0000000 --- a/iotkit-embedded/sample/coap/coap-example.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" - -#define IOTX_DAILY_DTLS_SERVER_URI "coaps://iot-as-coap.alibaba.net:5684" -#define IOTX_PRE_DTLS_SERVER_URI "coaps://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5684" -#define IOTX_PRE_NOSEC_SERVER_URI "coap://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5683" - -#define IOTX_ONLINE_DTLS_SERVER_URL "coaps://%s.iot-as-coap.cn-shanghai.aliyuncs.com:5684" - -char m_coap_client_running = 0; - -static void iotx_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); - HAL_Printf("[APPL]: Message response code: 0x%x\r\n", resp_code); - HAL_Printf("[APPL]: Len: %d, Payload: %s, \r\n", len, p_payload); -} - -#ifdef TEST_COAP_DAILY - #define IOTX_PRODUCT_KEY "zPygj0yP3UF" - #define IOTX_DEVICE_NAME "device_2" - #define IOTX_DEVICE_SECRET "5FQbVOPWNwhEuCvnVcP1Mvyjmvt8ECQi" - #define IOTX_DEVICE_ID "device_2" -#else - #define IOTX_PRODUCT_KEY "vtkkbrpmxmF" - #define IOTX_DEVICE_NAME "IoTxCoAPTestDev" - #define IOTX_DEVICE_SECRET "Stk4IUErQUBc1tWRWEKWb5ACra4hFDYF" - #define IOTX_DEVICE_ID "IoTxCoAPTestDev.1" -#endif - -int iotx_set_devinfo(iotx_deviceinfo_t *p_devinfo) -{ - if (NULL == p_devinfo) { - return IOTX_ERR_INVALID_PARAM; - } - - memset(p_devinfo, 0x00, sizeof(iotx_deviceinfo_t)); - - /**< get device info*/ - HAL_GetProductKey(p_devinfo->product_key); - HAL_GetDeviceName(p_devinfo->device_name); - HAL_GetDeviceSecret(p_devinfo->device_secret); - HAL_GetDeviceID(p_devinfo->device_id); - /**< end*/ - - fprintf(stderr, "*****The Product Key : %s *****\r\n", p_devinfo->product_key); - fprintf(stderr, "*****The Device Name : %s *****\r\n", p_devinfo->device_name); - //fprintf(stderr, "*****The Device Secret: %s *****\r\n", p_devinfo->device_secret); - fprintf(stderr, "*****The Device ID : %s *****\r\n", p_devinfo->device_id); - return IOTX_SUCCESS; -} - -static void iotx_post_data_to_server(void *param) -{ - char path[IOTX_URI_MAX_LEN + 1] = {0}; - iotx_message_t message; - iotx_deviceinfo_t devinfo; - message.p_payload = (unsigned char *)"{\"name\":\"hello world\"}"; - message.payload_len = strlen("{\"name\":\"hello world\"}"); - message.resp_callback = iotx_response_handler; - message.msg_type = IOTX_MESSAGE_CON; - message.content_type = IOTX_CONTENT_TYPE_JSON; - iotx_coap_context_t *p_ctx = (iotx_coap_context_t *)param; - - iotx_set_devinfo(&devinfo); - snprintf(path, IOTX_URI_MAX_LEN, "/topic/%s/%s/update/", (char *)devinfo.product_key, - (char *)devinfo.device_name); - - IOT_CoAP_SendMessage(p_ctx, path, &message); -} - -int main(int argc, char **argv) -{ - int count = 0; - char secur[32] = {0}; - char env[32] = {0}; - int opt; - iotx_coap_config_t config; - iotx_deviceinfo_t deviceinfo; - - /**< set device info*/ - HAL_SetProductKey(IOTX_PRODUCT_KEY); - HAL_SetDeviceName(IOTX_DEVICE_NAME); - HAL_SetDeviceSecret(IOTX_DEVICE_SECRET); - /**< end*/ - IOT_OpenLog("coap"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - - HAL_Printf("[COAP-Client]: Enter Coap Client\r\n"); - while ((opt = getopt(argc, argv, "e:s:lh")) != -1) { - switch (opt) { - case 's': - strncpy(secur, optarg, strlen(optarg)); - break; - case 'e': - strncpy(env, optarg, strlen(optarg)); - break; - case 'l': - m_coap_client_running = 1; - break; - case 'h': - /* TODO: */ - break; - default: - break; - } - } - - memset(&config, 0x00, sizeof(iotx_coap_config_t)); - if (0 == strncmp(env, "pre", strlen("pre"))) { - if (0 == strncmp(secur, "dtls", strlen("dtls"))) { - config.p_url = IOTX_PRE_DTLS_SERVER_URI; - } else { - config.p_url = IOTX_PRE_NOSEC_SERVER_URI; - } - } else if (0 == strncmp(env, "online", strlen("online"))) { - if (0 == strncmp(secur, "dtls", strlen("dtls"))) { - char url[256] = {0}; - snprintf(url, sizeof(url), IOTX_ONLINE_DTLS_SERVER_URL, IOTX_PRODUCT_KEY); - config.p_url = url; - } else { - HAL_Printf("Online environment must access with DTLS\r\n"); - IOT_CloseLog(); - return -1; - } - } - -#ifdef TEST_COAP_DAILY - config.p_url = IOTX_DAILY_DTLS_SERVER_URI; -#endif - - iotx_set_devinfo(&deviceinfo); - config.p_devinfo = (iotx_device_info_t*)&deviceinfo; - config.wait_time_ms = 3000; - - iotx_coap_context_t *p_ctx = NULL; - p_ctx = IOT_CoAP_Init(&config); - if (NULL != p_ctx) { - IOT_CoAP_DeviceNameAuth(p_ctx); - do { - count ++; - if (count == 11) { - iotx_post_data_to_server((void *)p_ctx); - count = 1; - } - IOT_CoAP_Yield(p_ctx); - } while (m_coap_client_running); - - IOT_CoAP_Deinit(&p_ctx); - } else { - HAL_Printf("IoTx CoAP init failed\r\n"); - } - - IOT_CloseLog(); - return 0; -} - diff --git a/iotkit-embedded/sample/device-shadow/CMakeLists.txt b/iotkit-embedded/sample/device-shadow/CMakeLists.txt deleted file mode 100644 index 799d716..0000000 --- a/iotkit-embedded/sample/device-shadow/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_executable(shadow-example shadow-example.c) -target_link_libraries(shadow-example iot_sdk) diff --git a/iotkit-embedded/sample/device-shadow/shadow-example.c b/iotkit-embedded/sample/device-shadow/shadow-example.c deleted file mode 100644 index f95d388..0000000 --- a/iotkit-embedded/sample/device-shadow/shadow-example.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" - -#define PRODUCT_KEY "yfTuLfBJTiL" -#define DEVICE_NAME "TestDeviceForDemo" -#define DEVICE_SECRET "fSCl9Ns5YPnYN8Ocg0VEel1kXFnRlV6c" - -#define SHADOW_MQTT_MSGLEN (1024) - -char g_product_key[PRODUCT_KEY_LEN + 1]; -char g_product_secret[PRODUCT_SECRET_LEN + 1]; -char g_device_name[DEVICE_NAME_LEN + 1]; -char g_device_secret[DEVICE_SECRET_LEN + 1]; - -#define SHADOW_TRACE(fmt, ...) \ - do { \ - HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ - HAL_Printf(fmt, ##__VA_ARGS__); \ - HAL_Printf("%s", "\r\n"); \ - } while(0) - -/** - * @brief This is a callback function when a control value coming from server. - * - * @param [in] pattr: attribute structure pointer - * @return none - * @see none. - * @note none. - */ -static void _device_shadow_cb_light(iotx_shadow_attr_pt pattr) -{ - - /* - * ****** Your Code ****** - */ - - SHADOW_TRACE("----"); - SHADOW_TRACE("Attrbute Name: '%s'", pattr->pattr_name); - SHADOW_TRACE("Attrbute Value: %d", *(int32_t *)pattr->pattr_data); - SHADOW_TRACE("----"); -} - - -/* Device shadow demo entry */ -int demo_device_shadow(char *msg_buf, char *msg_readbuf) -{ - char buf[1024]; - iotx_err_t rc; - iotx_conn_info_pt puser_info; - void *h_shadow; - iotx_shadow_para_t shadow_para; - - /**< get device info*/ - HAL_GetProductKey(g_product_key); - HAL_GetDeviceName(g_device_name); - HAL_GetDeviceSecret(g_device_secret); - /**< end*/ - /* Device AUTH */ -// rc = IOT_SetupConnInfo(PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, (void **)&puser_info); - rc = IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&puser_info); - if (SUCCESS_RETURN != rc) { - SHADOW_TRACE("rc = IOT_SetupConnInfo() = %d", rc); - return rc; - } - - /* Construct a device shadow */ - memset(&shadow_para, 0, sizeof(iotx_shadow_para_t)); - - shadow_para.mqtt.port = puser_info->port; - shadow_para.mqtt.host = puser_info->host_name; - shadow_para.mqtt.client_id = puser_info->client_id; - shadow_para.mqtt.username = puser_info->username; - shadow_para.mqtt.password = puser_info->password; - shadow_para.mqtt.pub_key = puser_info->pub_key; - - shadow_para.mqtt.request_timeout_ms = 2000; - shadow_para.mqtt.clean_session = 0; - shadow_para.mqtt.keepalive_interval_ms = 60000; - shadow_para.mqtt.pread_buf = msg_readbuf; - shadow_para.mqtt.read_buf_size = SHADOW_MQTT_MSGLEN; - shadow_para.mqtt.pwrite_buf = msg_buf; - shadow_para.mqtt.write_buf_size = SHADOW_MQTT_MSGLEN; - - shadow_para.mqtt.handle_event.h_fp = NULL; - shadow_para.mqtt.handle_event.pcontext = NULL; - - h_shadow = IOT_Shadow_Construct(&shadow_para); - if (NULL == h_shadow) { - SHADOW_TRACE("construct device shadow failed!"); - return rc; - } - - - /* Define and add two attribute */ - - int32_t light = 1000, temperature = 1001; - iotx_shadow_attr_t attr_light, attr_temperature; - - memset(&attr_light, 0, sizeof(iotx_shadow_attr_t)); - memset(&attr_temperature, 0, sizeof(iotx_shadow_attr_t)); - - /* Initialize the @light attribute */ - attr_light.attr_type = IOTX_SHADOW_INT32; - attr_light.mode = IOTX_SHADOW_RW; - attr_light.pattr_name = "switch"; - attr_light.pattr_data = &light; - attr_light.callback = _device_shadow_cb_light; - - /* Initialize the @temperature attribute */ - attr_temperature.attr_type = IOTX_SHADOW_INT32; - attr_temperature.mode = IOTX_SHADOW_READONLY; - attr_temperature.pattr_name = "temperature"; - attr_temperature.pattr_data = &temperature; - attr_temperature.callback = NULL; - - - /* Register the attribute */ - /* Note that you must register the attribute you want to synchronize with cloud - * before calling IOT_Shadow_Pull() */ - IOT_Shadow_RegisterAttribute(h_shadow, &attr_light); - IOT_Shadow_RegisterAttribute(h_shadow, &attr_temperature); - - - /* synchronize the device shadow with device shadow cloud */ - IOT_Shadow_Pull(h_shadow); - - do { - format_data_t format; - - /* Format the attribute data */ - IOT_Shadow_PushFormat_Init(h_shadow, &format, buf, 1024); - IOT_Shadow_PushFormat_Add(h_shadow, &format, &attr_temperature); - IOT_Shadow_PushFormat_Add(h_shadow, &format, &attr_light); - IOT_Shadow_PushFormat_Finalize(h_shadow, &format); - - /* Update attribute data */ - IOT_Shadow_Push(h_shadow, format.buf, format.offset, 10); - - /* Sleep 1000 ms */ - HAL_SleepMs(1000); - } while (0); - - - /* Delete the two attributes */ - IOT_Shadow_DeleteAttribute(h_shadow, &attr_temperature); - IOT_Shadow_DeleteAttribute(h_shadow, &attr_light); - - IOT_Shadow_Destroy(h_shadow); - - return 0; -} - - -int main() -{ - IOT_OpenLog("shadow"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - /**< set device info*/ - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - /**< end*/ - char *msg_buf = (char *)HAL_Malloc(SHADOW_MQTT_MSGLEN); - char *msg_readbuf = (char *)HAL_Malloc(SHADOW_MQTT_MSGLEN); - - demo_device_shadow(msg_buf, msg_readbuf); - - HAL_Free(msg_buf); - HAL_Free(msg_readbuf); - - SHADOW_TRACE("out of demo!"); - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - return 0; -} - diff --git a/iotkit-embedded/sample/http/CMakeLists.txt b/iotkit-embedded/sample/http/CMakeLists.txt deleted file mode 100644 index 417814e..0000000 --- a/iotkit-embedded/sample/http/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_executable(http-example ${C_SOURCES}) -target_link_libraries(http-example iot_sdk) diff --git a/iotkit-embedded/sample/http/http-example.c b/iotkit-embedded/sample/http/http-example.c deleted file mode 100644 index b05f079..0000000 --- a/iotkit-embedded/sample/http/http-example.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#if (!WIN32) -#include -#endif - -#include "iot_import.h" -#include "iot_export.h" - -#if defined(TEST_HTTP_DAILY) - - /* Daily Environment */ - #define IOTX_PRODUCT_KEY "zPygj0yP3UF" - #define IOTX_DEVICE_NAME "device_3" - #define IOTX_DEVICE_SECRET "dTWyCJgBYOGVDcr93ukArCa5cndX3s4D" - #define IOTX_DEVICE_ID "device_3" - -#else - /* Pre-Online or Online Environment */ - #define IOTX_PRODUCT_KEY "yfTuLfBJTiL" - #define IOTX_DEVICE_NAME "TestDeviceForDemo" - #define IOTX_DEVICE_SECRET "fSCl9Ns5YPnYN8Ocg0VEel1kXFnRlV6c" - #define IOTX_DEVICE_ID "IoTxHttpTestDev_001" -#endif - -#define DEFAULT_TIMEOUT_MS 5000 - -static int iotx_post_data_to_server(void *handle) -{ - int ret = -1; - char path[IOTX_URI_MAX_LEN + 1] = {0}; - char rsp_buf[1024]; - iotx_http_t *iotx_http_context = (iotx_http_t *)handle; - iotx_device_info_t *p_devinfo = iotx_http_context->p_devinfo; - - iotx_http_message_param_t msg_param; - msg_param.request_payload = (char *)"{\"name\":\"hello world\"}"; - msg_param.response_payload = rsp_buf; - msg_param.timeout_ms = iotx_http_context->timeout_ms; - msg_param.request_payload_len = strlen(msg_param.request_payload) + 1; - msg_param.response_payload_len = 1024; - msg_param.topic_path = path; - - HAL_Snprintf(msg_param.topic_path, IOTX_URI_MAX_LEN, "/topic/%s/%s/update", - p_devinfo->product_key, p_devinfo->device_name); - - if (0 == (ret = IOT_HTTP_SendMessage(iotx_http_context, &msg_param))) { - HAL_Printf("message response is %s\r\n", msg_param.response_payload); - } else { - HAL_Printf("error\r\n"); - } - - return ret; -} - -int main(int argc, char **argv) -{ - iotx_device_info_t device_info; - iotx_http_param_t http_param; -#if (!WIN32) - int opt; -#endif - void *handle = NULL; - - IOT_OpenLog("http"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - /**< set device info*/ - HAL_SetProductKey(IOTX_PRODUCT_KEY); - HAL_SetDeviceName(IOTX_DEVICE_NAME); - HAL_SetDeviceSecret(IOTX_DEVICE_SECRET); - /**< end*/ - memset(&device_info, 0, sizeof(device_info)); - memset(&http_param, 0, sizeof(http_param)); - - /**< get device info*/ - HAL_GetProductKey(device_info.product_key); - HAL_GetDeviceName(device_info.device_name); - HAL_GetDeviceSecret(device_info.device_secret); - HAL_GetDeviceID(device_info.device_id); - /**< end*/ - -#if (!WIN32) - HAL_Printf("[HTTP-Client]: Enter HTTP Client\r\n"); - while ((opt = getopt(argc, argv, "lh")) != -1) { - switch (opt) { - case 'l': - http_param.keep_alive = 1; - break; - case 'h': - /* TODO: */ - break; - default: - break; - } - } -#endif - HAL_Printf("[HTTP-Client]: keep_alive=%d\r\n", http_param.keep_alive); - http_param.device_info = &device_info; - http_param.timeout_ms = DEFAULT_TIMEOUT_MS; - - handle = IOT_HTTP_Init(&http_param); - if (NULL != handle) { - IOT_HTTP_DeviceNameAuth(handle); - iotx_post_data_to_server(handle); - HAL_Printf("IoTx HTTP Message Sent\r\n"); - } else { - HAL_Printf("IoTx HTTP init failed\r\n"); - - return 0; - } - - IOT_HTTP_Disconnect(handle); - - IOT_HTTP_DeInit(&handle); - - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - return 0; -} - diff --git a/iotkit-embedded/sample/iot.mk b/iotkit-embedded/sample/iot.mk deleted file mode 100644 index 6504424..0000000 --- a/iotkit-embedded/sample/iot.mk +++ /dev/null @@ -1,92 +0,0 @@ -DEPENDS := src/platform -HDR_REFS += src/sdk-impl src/utils src/log src/packages/LITE-utils -LDFLAGS := -liot_sdk -LDFLAGS += -liot_platform -ifneq (,$(filter -DIOTX_WITHOUT_ITLS,$(CFLAGS))) -LDFLAGS += -Bstatic -liot_tls -endif -CFLAGS := $(filter-out -ansi,$(CFLAGS)) - -ifneq (,$(filter -D_PLATFORM_IS_WINDOWS_,$(CFLAGS))) -LDFLAGS += -lws2_32 -CFLAGS := $(filter-out -DCOAP_COMM_ENABLED,$(CFLAGS)) -endif - -ifneq (,$(filter -DMQTT_COMM_ENABLED,$(CFLAGS))) -TARGET += mqtt-example mqtt_rrpc-example mqtt_multi_thread-example -SRCS_mqtt-example := mqtt/mqtt-example.c -SRCS_mqtt_rrpc-example := mqtt/mqtt_rrpc-example.c -SRCS_mqtt_multi_thread-example := mqtt/mqtt_multi_thread-example.c - - ifneq (,$(filter -DOTA_ENABLED,$(CFLAGS))) - ifneq (,$(filter -DOTA_SIGNAL_CHANNEL=1,$(CFLAGS))) - TARGET += ota_mqtt-example - SRCS_ota_mqtt-example := ota/ota_mqtt-example.c - endif - endif - - ifneq (,$(filter -DMQTT_SHADOW,$(CFLAGS))) - TARGET += shadow-example - SRCS_shadow-example := device-shadow/shadow-example.c - endif - - ifneq (,$(filter -DMQTT_ID2_AUTH,$(CFLAGS))) - ifneq (,$(filter -DON_DAILY,$(CFLAGS))) - LDFLAGS += -ltfs - else - LDFLAGS += -ltfs_online - endif - ifeq (,$(filter -DIOTX_WITHOUT_ITLS,$(CFLAGS))) - LDFLAGS += -litls - endif - ifeq (,$(filter -DIOTX_WITHOUT_TLS,$(CFLAGS))) - LDFLAGS += -liot_tls - endif - endif - LDFLAGS += -liot_sdk - -endif - -ifneq (,$(filter -DCOAP_COMM_ENABLED,$(CFLAGS))) -TARGET += coap-example - -SRCS_coap-example := coap/coap-example.c -SRCS += coap/coap-example.c - - ifneq (,$(filter -DOTA_ENABLED,$(CFLAGS))) - ifneq (,$(filter -DOTA_SIGNAL_CHANNEL=2,$(CFLAGS))) - TARGET += ota_coap-example - SRCS_ota_coap-example := ota/ota_coap-example.c - endif - endif -endif - -ifneq (,$(filter -DHTTP_COMM_ENABLED,$(CFLAGS))) -TARGET += http-example -SRCS_http-example := http/http-example.c -endif - -ifneq (,$(filter -DSUBDEVICE_ENABLED,$(CFLAGS))) -TARGET += subdev-example -SRCS_subdev-example += subdev/subdev-example.c \ - subdev/subdev_example_api.c -endif - -ifneq (,$(filter -DCLOUD_CONN_ENABLED,$(CFLAGS))) -TARGET += cloud_conn-example -SRCS_cloud_conn-example := cloud-conn/cloud_conn-example.c -endif - -ifneq (,$(filter -DCMP_ENABLED,$(CFLAGS))) -TARGET += cmp-example -SRCS_cmp-example := cmp/cmp-example.c -endif - - -ifneq (,$(filter -DDM_ENABLED,$(CFLAGS))) -TARGET += linkkit-example -SRCS_linkkit-example := linkkit/src/linkkit_export.c \ - linkkit/src/lite_queue.c \ - linkkit/samples/linkkit_sample.c -endif - diff --git a/iotkit-embedded/sample/linkkit/CMakeLists.txt b/iotkit-embedded/sample/linkkit/CMakeLists.txt deleted file mode 100644 index f74a22e..0000000 --- a/iotkit-embedded/sample/linkkit/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -include_directories(${PROJECT_SOURCE_DIR}/sample/linkkit/include) - -set(LINKKIT_C_SOURCES src/linkkit_export.c src/lite_queue.c) -add_library(linkkit STATIC ${LINKKIT_C_SOURCES}) -target_link_libraries(linkkit dm) -if(FEATURE_SERVICE_OTA_ENABLED) - target_link_libraries(linkkit fota cota) -endif(FEATURE_SERVICE_OTA_ENABLED) - -set(LINKKIT_SAMPLE_C_SOURCES samples/linkkit_sample.c ) -add_executable(linkkit-example ${LINKKIT_SAMPLE_C_SOURCES}) -target_link_libraries(linkkit-example linkkit) diff --git a/iotkit-embedded/sample/linkkit/include/linkkit_export.h b/iotkit-embedded/sample/linkkit/include/linkkit_export.h deleted file mode 100644 index 6d7c3c0..0000000 --- a/iotkit-embedded/sample/linkkit/include/linkkit_export.h +++ /dev/null @@ -1,271 +0,0 @@ -#ifndef LINKKIT_EXPORT_H -#define LINKKIT_EXPORT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "iot_export_fota.h" -#include "iot_export_dm.h" -#include "lite_queue.h" - -#ifdef SERVICE_OTA_ENABLED -#include "iot_export_fota.h" -#include "iot_export_cota.h" -#endif /* SERVICE_OTA_ENABLED */ - -typedef struct _linkkit_ops { - int (*on_connect)(void *ctx); - int (*on_disconnect)(void *ctx); - - int (*raw_data_arrived)(void *thing_id, void *data, int len, void *ctx); - - int (*thing_create)(void *thing_id, void *ctx); - - int (*thing_enable)(void *thing_id, void *ctx); - int (*thing_disable)(void *thing_id, void *ctx); -#ifdef RRPC_ENABLED - int (*thing_call_service)(void *thing_id, char *service, int request_id, int rrpc, void *ctx); -#else - int (*thing_call_service)(void *thing_id, char *service, int request_id, void *ctx); -#endif /* RRPC_ENABLED */ - int (*thing_prop_changed)(void *thing_id, char *property, 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 { - /* iot-as-mqtt.cn-shanghai.aliyuncs.com */ - linkkit_cloud_domain_sh, - /* USA */ - linkkit_cloud_domain_usa, - - linkkit_cloud_domain_max, -} linkkit_cloud_domain_type_t; - -/* device info related operation */ -typedef enum { - linkkit_deviceinfo_operate_update, - linkkit_deviceinfo_operate_delete, - - linkkit_deviceinfo_operate_max, -} linkkit_deviceinfo_operate_t; - -/** - * @brief dispatch message of queue for further process. - * - * @return int, 0 when success, -1 when fail. - */ -int linkkit_dispatch(void); - -/** - * @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. - */ -int 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); - -#ifdef SERVICE_OTA_ENABLED -/** - * @brief init fota service routines, and install callback funstions. - * - * @param callback_fp, callback function to be installed. - * - * @return int, 0 when success, -1 when fail. - */ -int linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp); -#ifdef SERVICE_COTA_ENABLED -int linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp); -#endif /**< SERVICE_COTA_ENABLED*/ -#endif /* SERVICE_OTA_ENABLED */ - -/** - * @brief stop linkkit routines. - * - * - * @return 0 when success, -1 when fail. - */ -int linkkit_end(); - -/** - * @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. - */ -extern 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, value to set.(input int* if target value is int type or enum or bool, float* if float type, - * long long* if date type, char* if text type). - * @param value_str, value to set in string format if value is null. - * - * @return 0 when success, -1 when fail. - */ -extern int 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, value to get(input int* if target value is int type or enum or bool, float* if float type, - * long long* if date type, char* if text type). - * @param value_str, value to get in string format. DO NOT modify this when function returns, - * user should copy to user's own buffer for further process. - * user should NOT free the memory. - * - * @return 0 when success, -1 when fail. - */ -extern int 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. - * @param rrpc, specify rrpc service call or not. - * - * @return 0 when success, -1 when fail. - */ -#ifdef RRPC_ENABLED -extern int linkkit_answer_service(const void* thing_id, const char* service_identifier, int response_id, int code, int rrpc); -#else -extern int linkkit_answer_service(const void* thing_id, const char* service_identifier, int response_id, int code); -#endif /* RRPC_ENABLED */ - -/** - * @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. - */ -extern int linkkit_invoke_raw_service(const void* thing_id, int is_up_raw, void* raw_data, int raw_data_length); - -#ifdef SERVICE_OTA_ENABLED -/** - * @brief perform ota service when "new version detected" reported. - * - * @param is_up_raw, specify up raw(not 0) or down raw reply(0). - * @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. - */ -extern int linkkit_invoke_fota_service(void* data_buf, int data_buf_length); -#ifdef SERVICE_COTA_ENABLED -extern int linkkit_invoke_cota_service(void* data_buf, int data_buf_length); -extern int linkkit_invoke_cota_get_config(const char* config_scope, const char* get_type, const char* attribute_Keys, void* option); -#endif /**< SERVICE_COTA_ENABLED*/ -#endif /* SERVICE_OTA_ENABLED */ - -#ifdef DEVICEINFO_ENABLED -/** - * @brief trigger deviceinfo update procedure. - * - * @param thing_id, pointer to thing object. - * @param params, json type string that user to send to cloud. - * @param linkkit_deviceinfo_operation, specify update type or delete type. - * - * @return 0 when success, -1 when fail. - */ - -int linkkit_trigger_deviceinfo_operate(const void* thing_id, const char* params, linkkit_deviceinfo_operate_t linkkit_deviceinfo_operation); -#endif - -/** - * @brief trigger a event to post to cloud. - * - * @param thing_id, pointer to thing object. - * @param event_identifier, event identifier to trigger. - * @param property_identifier, used when trigger event with method "event.property.post", if set, post specified property, if NULL, post all. - * - * @return 0 when success, -1 when fail. - */ -extern int linkkit_trigger_event(const void* thing_id, const char* event_identifier, const char* property_identifier); - -#ifndef CMP_SUPPORT_MULTI_THREAD -/** - * @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. - */ -extern int linkkit_yield(int timeout_ms); -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LINKKIT_EXPORT_H */ diff --git a/iotkit-embedded/sample/linkkit/include/lite_queue.h b/iotkit-embedded/sample/linkkit/include/lite_queue.h deleted file mode 100644 index e962028..0000000 --- a/iotkit-embedded/sample/linkkit/include/lite_queue.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LITE_QUEUE_H -#define LITE_QUEUE_H - -#include -#include - -typedef struct _lite_queue_t -{ - void* lite_queue_array; - void* lite_queue_mutex; - size_t queue_size; - size_t queue_array_size; - size_t front; - size_t rear; -} lite_queue_t; - -typedef void (*handle_queue_item_fp_t)(void* queue_item, va_list* params); - -lite_queue_t* lite_queue_create(int queue_size, int synchronized); -void lite_queue_destroy(lite_queue_t* _lite_queue); -int lite_queue_insert(lite_queue_t* _lite_queue, void *data); -void* lite_queue_delete(lite_queue_t* _lite_queue); -void* lite_queue_first(lite_queue_t* _lite_queue); -int lite_queue_is_empty(lite_queue_t* _lite_queue); -int lite_queue_is_full(lite_queue_t* _lite_queue); -void lite_queue_iterator(lite_queue_t* _lite_queue, handle_queue_item_fp_t handle_fn, ...); - -#endif /* LITE_QUEUE_H */ diff --git a/iotkit-embedded/sample/linkkit/samples/linkkit_sample.c b/iotkit-embedded/sample/linkkit/samples/linkkit_sample.c deleted file mode 100644 index ddf8df5..0000000 --- a/iotkit-embedded/sample/linkkit/samples/linkkit_sample.c +++ /dev/null @@ -1,524 +0,0 @@ -/** USER NOTIFICATION - * this sample code is only used for evaluation or test of the iLop project. - * Users should modify this sample code freely according to the product/device TSL, like - * property/event/service identifiers, and the item value type(type, length, etc...). - * Create user's own execution logic for specific products. - */ - -#include -#include -#include -#include -#include -#if !(WIN32) -#include -#endif - -#include "linkkit_export.h" - -#include "iot_import.h" - -/* - * example for product "鐏�-Demo" - */ - - -#ifdef ON_DAILY -#define DM_PRODUCT_KEY_1 "a1nmfrdo3MI" -#define DM_DEVICE_NAME_1 "light_demo_for_ilop_device_test" -#define DM_DEVICE_SECRET_1 "kobN5zg08IwlgbqSUeaxo0vbEsOiEI7b" -#else -#define DM_PRODUCT_KEY_1 "a1grYGVCPWl" -#define DM_DEVICE_NAME_1 "0402_09" -#define DM_DEVICE_SECRET_1 "DocxiD5wS6x9HNZrbC2CAoi9UnYP74Xt" -#endif -#define DM_DEVICE_ID_1 "IoTxHttpTestDev_001" - - -#define LINKKIT_PRINTF(...) \ - do { \ - printf("\e[0;32m%s@line%d\t:", __FUNCTION__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\e[0m"); \ - } while (0) - -/* identifier of property/service/event, users should modify this macros according to your own product TSL. */ -#define EVENT_PROPERTY_POST_IDENTIFIER "post" -#define EVENT_ERROR_IDENTIFIER "Error" -#define EVENT_ERROR_OUTPUT_INFO_IDENTIFIER "ErrorCode" -#define EVENT_CUSTOM_IDENTIFIER "Custom" - -/* specify ota buffer size for ota service, ota service will use this buffer for bin download. */ -#define OTA_BUFFER_SIZE (512+1) -/* PLEASE set RIGHT tsl string according to your product. */ -#if !(WIN32) -const char TSL_STRING[] = "{\"schema\":\"http://aliyun/iot/thing/desc/schema\",\"profile\":{\"productKey\":\"a1saiXev7Q9\",\"deviceName\":\"q0LP4t1AWGnbp3uwF6Md\"},\"services\":[{\"outputData\":[],\"identifier\":\"set\",\"inputData\":[{\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":\"2700\",\"unitName\":\"开尔文\",\"max\":\"6500\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":\"Brightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明暗度\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":\"HSL调色\"},{\"identifier\":\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":\"HSV调色\"},{\"identifier\":\"PropertyTime\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间\"},{\"identifier\":\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"},\"type\":\"double\"},\"name\":\"浮点型\"},{\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"字符串\"}],\"method\":\"thing.service.property.set\",\"name\":\"set\",\"required\":true,\"callType\":\"sync\",\"desc\":\"属性设置\"},{\"outputData\":[{\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":\"2700\",\"unitName\":\"开尔文\",\"max\":\"6500\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":\"Brightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明暗度\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":\"HSL调色\"},{\"identifier\":\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":\"HSV调色\"},{\"identifier\":\"PropertyTime\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间\"},{\"identifier\":\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"},\"type\":\"double\"},\"name\":\"浮点型\"},{\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"字符串\"}],\"identifier\":\"get\",\"inputData\":[\"LightSwitch\",\"RGBColor\",\"NightLightSwitch\",\"WorkMode\",\"ColorTemperature\",\"Brightness\",\"HSLColor\",\"HSVColor\",\"PropertyTime\",\"Propertypoint\",\"PropertyCharacter\"],\"method\":\"thing.service.property.get\",\"name\":\"get\",\"required\":true,\"callType\":\"sync\",\"desc\":\"属性获取\"},{\"outputData\":[{\"identifier\":\"Contrastratio\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"对比度\"}],\"identifier\":\"Custom\",\"inputData\":[{\"identifier\":\"transparency\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"透明度\"}],\"method\":\"thing.service.Custom\",\"name\":\"自定义服务\",\"required\":false,\"callType\":\"async\"}],\"properties\":[{\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\",\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\" },\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":\"RGB调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":\"2700\",\"unitName\":\"开尔文\",\"max\":\"6500\"},\"type\":\"int\"},\"name\":\"冷暖色温\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"Brightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明暗度\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":\"HSL调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":\"HSV调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"PropertyTime\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"},\"type\":\"double\"},\"name\":\"浮点型\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"字符串\",\"accessMode\":\"rw\",\"required\":false}],\"events\":[{\"outputData\":[{\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":\"2700\",\"unitName\":\"开尔文\",\"max\":\"6500\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":\"Brightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明暗度\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":\"HSL调色\"},{\"identifier\":\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\"},\"type\":\"int\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":\"HSV调色\"},{\"identifier\":\"PropertyTime\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间\"},{\"identifier\":\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"},\"type\":\"double\"},\"name\":\"浮点型\"},{\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"字符串\"}],\"identifier\":\"post\",\"method\":\"thing.event.property.post\",\"name\":\"post\",\"type\":\"info\",\"required\":true,\"desc\":\"属性上报\"},{\"outputData\":[{\"identifier\":\"ErrorCode\",\"dataType\":{\"specs\":{\"0\":\"恢复正常\"},\"type\":\"enum\"},\"name\":\"故障代码\"}],\"identifier\":\"Error\",\"method\":\"thing.event.Error.post\",\"name\":\"故障上报\",\"type\":\"info\",\"required\":true}]}"; -#else -const char TSL_STRING[] = "add tsl in there"; -#endif - -/* user sample context struct. */ -typedef struct _sample_context { - void* thing; - - int cloud_connected; - int thing_enabled; - - int service_custom_input_transparency; - int service_custom_output_contrastratio; -#ifdef SERVICE_OTA_ENABLED - char ota_buffer[OTA_BUFFER_SIZE]; -#endif /* SERVICE_OTA_ENABLED */ -} sample_context_t; - -sample_context_t g_sample_context; - -#ifdef SERVICE_OTA_ENABLED -#ifndef SERVICE_COTA_ENABLED -/* callback function for fota service. */ -static void fota_callback(service_fota_callback_type_t callback_type, const char* version) -{ - sample_context_t* sample; - - assert(callback_type < service_fota_callback_type_number); - - sample = &g_sample_context; - - /* temporarily disable thing when ota service invoked */ - sample->thing_enabled = 0; - - linkkit_invoke_fota_service(sample->ota_buffer, OTA_BUFFER_SIZE); - - sample->thing_enabled = 1; - - /* reboot the device... */ -} - -#else /* SERVICE_COTA_ENABLED */ -static void cota_callback(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) -{ - sample_context_t* sample; - - assert(callback_type < service_cota_callback_type_number); - - sample = &g_sample_context; - - /* temporarily disable thing when ota service invoked */ - sample->thing_enabled = 0; - - linkkit_invoke_cota_service(sample->ota_buffer, OTA_BUFFER_SIZE); - - sample->thing_enabled = 1; - - /* update config... */ -} -#endif /* SERVICE_COTA_ENABLED */ -#endif /* SERVICE_OTA_ENABLED */ - -static int on_connect(void* ctx) -{ - sample_context_t* sample = ctx; - - sample->cloud_connected = 1; - - LINKKIT_PRINTF("cloud is connected\n"); - - return 0; -} - -static int on_disconnect(void* ctx) -{ - sample_context_t* sample = ctx; - - sample->cloud_connected = 0; - - LINKKIT_PRINTF("cloud is disconnect\n"); - - return 0; -} - -static int raw_data_arrived(void* thing_id, void* data, int len, void* ctx) -{ - char raw_data[128] = {0}; - - LINKKIT_PRINTF("raw data arrived,len:%d\n", len); - - /* do user's raw data process logical here. */ - - /* ............................... */ - - /* user's raw data process logical complete */ - - snprintf(raw_data, sizeof(raw_data), "test down raw reply data %lld", (long long)HAL_UptimeMs()); - - linkkit_invoke_raw_service(thing_id, 0, raw_data, strlen(raw_data)); - - return 0; -} - -static int thing_create(void* thing_id, void* ctx) -{ - sample_context_t* sample = ctx; - - LINKKIT_PRINTF("new thing@%p created.\n", thing_id); - - sample->thing = thing_id; - - return 0; -} - -static int thing_enable(void* thing_id, void* ctx) -{ - sample_context_t* sample = ctx; - - sample->thing_enabled = 1; - - return 0; -} - -static int thing_disable(void* thing, void* ctx) -{ - sample_context_t* sample = ctx; - - sample->thing_enabled = 0; - - return 0; -} -#ifdef RRPC_ENABLED -static int handle_service_custom(sample_context_t* sample, void* thing, char* service_identifier, int request_id, int rrpc) -#else -static int handle_service_custom(sample_context_t* sample, void* thing, char* service_identifier, int request_id) -#endif /* RRPC_ENABLED */ -{ - char identifier[128] = {0}; - - /* - * get iutput value. - */ - snprintf(identifier, sizeof(identifier), "%s.%s", service_identifier, "transparency"); - linkkit_get_value(linkkit_method_get_service_input_value, thing, identifier, &sample->service_custom_input_transparency, NULL); - - /* - * set output value according to user's process result. - */ - - snprintf(identifier, sizeof(identifier), "%s.%s", service_identifier, "Contrastratio"); - - sample->service_custom_output_contrastratio = sample->service_custom_input_transparency >= 0 ? sample->service_custom_input_transparency : sample->service_custom_input_transparency * -1; - - linkkit_set_value(linkkit_method_set_service_output_value, thing, identifier, &sample->service_custom_output_contrastratio, NULL); -#ifdef RRPC_ENABLED - linkkit_answer_service(thing, service_identifier, request_id, 200, rrpc); -#else - linkkit_answer_service(thing, service_identifier, request_id, 200); -#endif /* RRPC_ENABLED */ - - return 0; -} -#ifdef RRPC_ENABLED -static int thing_call_service(void* thing_id, char* service, int request_id, int rrpc, void* ctx) -#else -static int thing_call_service(void* thing_id, char* service, int request_id, void* ctx) -#endif /* RRPC_ENABLED */ -{ - sample_context_t* sample = ctx; - - LINKKIT_PRINTF("service(%s) requested, id: thing@%p, request id:%d\n", - service ? service : "NULL", thing_id, request_id); - - if (strcmp(service, "Custom") == 0) { -#ifdef RRPC_ENABLED - handle_service_custom(sample, thing_id, service, request_id, rrpc); -#else - handle_service_custom(sample, thing_id, service, request_id); -#endif /* RRPC_ENABLED */ - } - - return 0; -} - -static int thing_prop_changed(void* thing_id, char* property, void* ctx) -{ - char* value_str = NULL; - char property_buf[64] = {0}; - - /* get new property value */ - if (strstr(property, "HSVColor") != 0) { - int hue, saturation, value; - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Hue"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &hue, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Saturation"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &saturation, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Value"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &value, &value_str); - - LINKKIT_PRINTF("property(%s), Hue:%d, Saturation:%d, Value:%d\n", property, hue, saturation, value); - - /* XXX: do user's process logical here. */ - } else if (strstr(property, "HSLColor") != 0) { - int hue, saturation, lightness; - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Hue"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &hue, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Saturation"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &saturation, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Lightness"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &lightness, &value_str); - - LINKKIT_PRINTF("property(%s), Hue:%d, Saturation:%d, Lightness:%d\n", property, hue, saturation, lightness); - /* XXX: do user's process logical here. */ - } else if (strstr(property, "RGBColor") != 0) { - int red, green, blue; - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Red"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &red, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Green"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &green, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Blue"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &blue, &value_str); - - LINKKIT_PRINTF("property(%s), Red:%d, Green:%d, Blue:%d\n", property, red, green, blue); - /* XXX: do user's process logical here. */ - } else if (strstr(property, "structProperty") != 0) { - int childINTName = 0; - int childFLOATName = 0; - int childDATEName = 0; - int childTEXTName = 0; - int childBOOLName = 0; - int childENUMName = 0; - int childDOUBLEName = 0; - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildINTd1e197e"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childINTName, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildFLOATcdef1f2"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childFLOATName, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildDATE228857b"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childDATEName, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildTEXT5ad129f"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childTEXTName, &value_str); - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildBOOLea5c7ba"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childBOOLName, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildENUMf600fe3"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childENUMName, &value_str); - - snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "structchildDOUBLEff6bba6"); - linkkit_get_value(linkkit_method_get_property_value, thing_id, property_buf, &childDOUBLEName, &value_str); - - LINKKIT_PRINTF("property(%s), childINTName:%d, childFLOATName:%d, childDATEName:%d, childTEXTName:%d, childBOOLName:%d, childENUMName:%d, childDOUBLEName:%d\n",\ - property, childINTName, childFLOATName, childDATEName, childTEXTName, childBOOLName, childENUMName, childDOUBLEName); - - } else { - linkkit_get_value(linkkit_method_get_property_value, thing_id, property, NULL, &value_str); - - LINKKIT_PRINTF("#### property(%s) new value set: %s ####\n", property ? property : "NULL", value_str ? value_str : "NULL"); - } - - /* do user's process logical here. */ - linkkit_trigger_event(thing_id, EVENT_PROPERTY_POST_IDENTIFIER, property); - - return 0; -} - -static linkkit_ops_t alinkops = { - .on_connect = on_connect, - .on_disconnect = on_disconnect, - .raw_data_arrived = raw_data_arrived, - .thing_create = thing_create, - .thing_enable = thing_enable, - .thing_disable = thing_disable, - .thing_call_service = thing_call_service, - .thing_prop_changed = thing_prop_changed, -}; - -static unsigned long long uptime_sec(void) -{ - static unsigned long long start_time = 0; - - if (start_time == 0) { - start_time = HAL_UptimeMs(); - } - - return (HAL_UptimeMs() - start_time) / 1000; -} -#if 1 -static int post_all_prop(sample_context_t* sample) -{ - return linkkit_trigger_event(sample->thing, EVENT_PROPERTY_POST_IDENTIFIER, NULL); -} -#endif -static int post_event_error(sample_context_t* sample) -{ - char event_output_identifier[64]; - snprintf(event_output_identifier, sizeof(event_output_identifier), "%s.%s", EVENT_ERROR_IDENTIFIER, EVENT_ERROR_OUTPUT_INFO_IDENTIFIER); - - int errorCode = 0; - linkkit_set_value(linkkit_method_set_event_output_value, - sample->thing, - event_output_identifier, - &errorCode, NULL); - - return linkkit_trigger_event(sample->thing, EVENT_ERROR_IDENTIFIER, NULL); -} - -#if 0 -static int post_event_fault_alert(sample_context_t* sample) -{ - char event_output_identifier[64]; - snprintf(event_output_identifier, sizeof(event_output_identifier), "%s.%s", EVENT_ERROR_IDENTIFIER, EVENT_ERROR_OUTPUT_INFO_IDENTIFIER); - - int errorCode = 0; - linkkit_set_value(linkkit_method_set_event_output_value, - sample->thing, - event_output_identifier, - &errorCode, NULL); - - return linkkit_trigger_event(sample->thing, EVENT_ERROR_IDENTIFIER, NULL); -} - -static int upload_raw_data(sample_context_t* sample) -{ - char raw_data[128] = {0}; - - snprintf(raw_data, sizeof(raw_data), "test up raw data %lld", HAL_UptimeMs()); - - return linkkit_invoke_raw_service(sample->thing, 1, raw_data, strlen(raw_data)); -} -#endif - -static int is_active(sample_context_t* sample) -{ - return sample->cloud_connected && sample->thing_enabled; -} - - -#ifdef MQTT_ID2_AUTH -#include "tfs.h" -#endif - -int main(int argc, char* argv[]) -{ - sample_context_t* sample_ctx = &g_sample_context; - int execution_time = 0; - int get_tsl_from_cloud = 0; - int exit = 0; - - unsigned long long now = 0; - unsigned long long prev_sec = 0; - - HAL_SetProductKey(DM_PRODUCT_KEY_1); - -#ifdef MQTT_ID2_AUTH - char __device_id2[TFS_ID2_LEN + 1]; - HAL_GetID2(__device_id2); - HAL_SetDeviceName(__device_id2); -#else - HAL_SetDeviceName(DM_DEVICE_NAME_1); -#endif - - HAL_SetDeviceSecret(DM_DEVICE_SECRET_1); - -#if !(WIN32) - int opt; - while ((opt = getopt(argc, argv, "t:g:h")) != -1) { - switch (opt) { - case 't': - execution_time = atoi(optarg); - break; - case 'g': - get_tsl_from_cloud = atoi(optarg); - break; - case 'h': - LINKKIT_PRINTF("-t to specify sample execution time period(minutes); -g to specify if get tsl from cloud(0: not, !0: yes).\n"); - return 0; - break; - default: - break; - } - } -#endif - - execution_time = execution_time < 1 ? 1 : execution_time; - LINKKIT_PRINTF("sample execution time: %d minutes\n", execution_time); - LINKKIT_PRINTF("%s tsl from cloud\n", get_tsl_from_cloud == 0 ? "Not get" : "get"); - - memset(sample_ctx, 0, sizeof(sample_context_t)); - sample_ctx->thing_enabled = 1; - - linkkit_start(8, get_tsl_from_cloud, linkkit_loglevel_debug, &alinkops, linkkit_cloud_domain_sh, sample_ctx); - if (!get_tsl_from_cloud) { - linkkit_set_tsl(TSL_STRING, strlen(TSL_STRING)); - } -#ifdef SERVICE_OTA_ENABLED -#ifndef SERVICE_COTA_ENABLED - LINKKIT_PRINTF("FOTA start\n"); - linkkit_fota_init(fota_callback); -#else /* SERVICE_COTA_ENABLED */ - LINKKIT_PRINTF("COTA_start\n"); - linkkit_cota_init(cota_callback); - linkkit_invoke_cota_get_config("product","file","",NULL); -#endif /* SERVICE_COTA_ENABLED */ -#endif /* SERVICE_OTA_ENABLED */ - while (1) { - linkkit_dispatch(); - - now = uptime_sec(); - if (prev_sec == now) { -#ifdef CMP_SUPPORT_MULTI_THREAD - HAL_SleepMs(100); -#else - linkkit_yield(100); -#endif - continue; - } - - /* about 30 seconds, assume trigger post property event about every 30s. */ - if (now % 30 == 0 && is_active(sample_ctx)) { - post_all_prop(sample_ctx); - } -#if 0 - - /* about 31 seconds, assume invoke raw up service about every 31s. */ - if (now % 31 == 0 && is_active(sample_ctx)) { - upload_raw_data(sample_ctx); - } - - /* about 60 seconds, assume trigger event about every 60s. */ - if (now % 60 == 0 && is_active(sample_ctx)) { - post_event_fault_alert(sample_ctx); - } -#endif - /* about 60 seconds, assume trigger event about every 60s. */ - if (now % 60 == 0 && is_active(sample_ctx)) { - post_event_error(sample_ctx); - } - - if (exit) break; - - /* after all, this is an sample, give a chance to return... */ - /* modify this value for this sample executaion time period */ - if (now > 60 * execution_time) exit = 1; - - prev_sec = now; - } - - linkkit_end(); - - return 0; -} diff --git a/iotkit-embedded/sample/linkkit/src/linkkit_export.c b/iotkit-embedded/sample/linkkit/src/linkkit_export.c deleted file mode 100644 index 5ab98d7..0000000 --- a/iotkit-embedded/sample/linkkit/src/linkkit_export.c +++ /dev/null @@ -1,392 +0,0 @@ -#include -#include -#include - -#include "linkkit_export.h" -#include "class_interface.h" - -#define LINKKIT_EXPORT_PRINTF printf - -/* used for packing up all parameters from dm callback. */ -typedef struct { - void* thing_id; - char property_service_version_identifier[64]; - int request_id; - void* raw_data; - int raw_data_length; - dm_callback_type_t callback_type; -} dm_msg_t; - -static linkkit_ops_t* g_linkkit_ops = NULL; -static lite_queue_t* g_message_queue = NULL; -static void* user_ctx = NULL; -static void* dm_object = NULL; -#ifdef SERVICE_OTA_ENABLED -static void* fota_object = NULL; -#ifdef SERVICE_COTA_ENABLED -static void* cota_object = NULL; -#endif /* SERVICE_COTA_ENABLED */ -#endif /* SERVICE_OTA_ENABLED */ -/* callback function for dm. pack up all parameters and send to queue. this callback should be processed as fast as possible. */ -static void dm_callback(dm_callback_type_t callback_type, - void* thing_id, const char* property_service_identifier, - int request_id, void* raw_data, int raw_data_length) -{ - linkkit_ops_t* linkkit_ops = g_linkkit_ops; - void* context = user_ctx; - dm_msg_t* msg = NULL; - - if (!linkkit_ops || ! context) return; - - if (callback_type == dm_callback_type_raw_data_arrived) { - if (linkkit_ops->raw_data_arrived) { - linkkit_ops->raw_data_arrived(thing_id, raw_data, raw_data_length, context); - } - return; - } - - msg = calloc(1, sizeof(dm_msg_t)); - if (!msg) return; - - msg->callback_type = callback_type; - msg->thing_id = thing_id; - - if (property_service_identifier) { - strcpy(msg->property_service_version_identifier, property_service_identifier); - } - - msg->request_id = request_id; - msg->raw_data = raw_data; - msg->raw_data_length = raw_data_length; - - lite_queue_insert(g_message_queue, msg); - - LINKKIT_EXPORT_PRINTF("\n---------------\nsubmit an item to queue @%p.\n---------------\n", msg); -} - -static void handle_request(dm_msg_t* msg, void* ctx) -{ - linkkit_ops_t* linkkit_ops = g_linkkit_ops; - void* context = ctx; -#ifdef RRPC_ENABLED - int rrpc = 0; -#endif /* RRPC_ENABLED */ - if (!linkkit_ops || !context) return; - - switch (msg->callback_type) { - case dm_callback_type_cloud_connected: - if (linkkit_ops->on_connect) linkkit_ops->on_connect(context); - break; - case dm_callback_type_cloud_disconnected: - if (linkkit_ops->on_disconnect) linkkit_ops->on_disconnect(context); - break; - case dm_callback_type_property_value_set: - if (linkkit_ops->thing_prop_changed) { - linkkit_ops->thing_prop_changed(msg->thing_id, - msg->property_service_version_identifier, - context); - } - break; - case dm_callback_type_new_thing_created: - if (linkkit_ops->thing_create) linkkit_ops->thing_create(msg->thing_id, context); - break; -#ifdef RRPC_ENABLED - case dm_callback_type_rrpc_requested: - rrpc = 1; -#endif /* RRPC_ENABLED */ - case dm_callback_type_service_requested: - if (linkkit_ops->thing_call_service) { - linkkit_ops->thing_call_service(msg->thing_id, - msg->property_service_version_identifier, - msg->request_id, -#ifdef RRPC_ENABLED - rrpc, -#endif /* RRPC_ENABLED */ - context); - } - break; - case dm_callback_type_raw_data_arrived: - /* will be handled in dm_callback() */ - break; - case dm_callback_type_thing_enabled: - if (linkkit_ops->thing_enable) linkkit_ops->thing_enable(msg->thing_id, context); - break; - case dm_callback_type_thing_disabled: - if (linkkit_ops->thing_disable) linkkit_ops->thing_disable(msg->thing_id, context); - break; - default: - break; - } -} - -int linkkit_dispatch(void) -{ - if (!g_message_queue || !user_ctx) { - LINKKIT_EXPORT_PRINTF("linkkit unitialized"); - return -1; - } - - while (1) { - dm_msg_t* msg = lite_queue_delete(g_message_queue); - if (!msg) break; - handle_request(msg, user_ctx); - free(msg); - } - - return 0; -} - -/* async type */ -static int linkkit_start_routine(handle_dm_callback_fp_t callback_fp, int get_tsl_from_cloud, linkkit_loglevel_t log_level, linkkit_cloud_domain_type_t domain_type) -{ - int ret = -1; - - if (dm_object) return ret; - - if (callback_fp == NULL) return ret; - - dm_object = new_object(DM_IMPL_CLASS, "dm obj", get_tsl_from_cloud, log_level, callback_fp, domain_type); - - ret = dm_object ? 0 : -1; - - return ret; -} - -int 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 ret = -1; - - if (!ops || !user_context || max_buffered_msg <= 0) return ret; - - g_message_queue = lite_queue_create(max_buffered_msg, 0); - if (!g_message_queue) return ret; - - g_linkkit_ops = ops; - user_ctx = user_context; - - ret = linkkit_start_routine(dm_callback, get_tsl_from_cloud, log_level, domain_type); - - return ret; -} -#ifdef SERVICE_OTA_ENABLED -int linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp) -{ - fota_t** ota; - int ret = -1; - - if (fota_object) return 0; - - if (callback_fp == NULL) return -1; - - fota_object = new_object(SERVICE_FOTA_CLASS, "fota obj"); - - ota = fota_object; - - if (ota && *ota && (*ota)->install_callback_function) { - (*ota)->install_callback_function(ota, callback_fp); - ret = 0; - } - - return ret; -} -#ifdef SERVICE_COTA_ENABLED -int linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp) -{ - cota_t** ota; - int ret = -1; - - if (cota_object) return 0; - - if (callback_fp == NULL) return -1; - - cota_object = new_object(SERVICE_COTA_CLASS, "cota obj"); - - ota = cota_object; - - if (ota && *ota && (*ota)->install_callback_function) { - (*ota)->install_callback_function(ota, callback_fp); - ret = 0; - } - - return ret; -} -#endif /* SERVICE_COTA_ENABLED*/ -#endif /* SERVICE_OTA_ENABLED */ -int linkkit_end() -{ - if (g_message_queue) lite_queue_destroy(g_message_queue); -#ifdef SERVICE_OTA_ENABLED - if (fota_object) delete_object(fota_object); -#ifdef SERVICE_COTA_ENABLED - if (cota_object) delete_object(cota_object); -#endif /* SERVICE_COTA_ENABLED*/ -#endif /* SERVICE_OTA_ENABLED */ - if (dm_object) delete_object(dm_object); - - g_message_queue = NULL; - dm_object = NULL; -#ifdef SERVICE_OTA_ENABLED - fota_object = NULL; -#endif /* SERVICE_OTA_ENABLED */ - return 0; -} - -void* linkkit_set_tsl(const char* tsl, int tsl_len) -{ - void* thing = NULL; - const dm_t** dm = dm_object; - - if (dm && *dm && tsl && tsl_len > 0 && *tsl == '{' && *(tsl + tsl_len - 1) == '}') { - thing = (*dm)->generate_new_thing(dm, tsl, tsl_len); - } - - return thing; -} - -int linkkit_set_value(linkkit_method_set_t method_set, const void* thing_id, const char* identifier, const void* value, const char* value_str) -{ - dm_t** dm = dm_object; - int ret = -1; - - if (dm == NULL || *dm == NULL || thing_id == NULL || identifier == NULL || method_set >= linkkit_method_set_number || (value == NULL && value_str == NULL)) return -1; - - if (method_set == linkkit_method_set_property_value) { - ret = (*dm)->set_property_value(dm, thing_id, identifier, value, value_str); - } else if (method_set == linkkit_method_set_event_output_value) { - ret = (*dm)->set_event_output_value(dm, thing_id, identifier, value, value_str); - } else if (method_set == linkkit_method_set_service_output_value) { - ret = (*dm)->set_service_output_value(dm, thing_id, identifier, value, value_str); - } - - return ret; -} - -int linkkit_get_value(linkkit_method_get_t method_get, const void* thing_id, const char* identifier, void* value, char** value_str) -{ - dm_t** dm = dm_object; - int ret = -1; - - if (dm == NULL || *dm == NULL || thing_id == NULL || identifier == NULL || method_get >= linkkit_method_get_number || (value == NULL && value_str == NULL)) return -1; - - if (method_get == linkkit_method_get_property_value) { - ret = (*dm)->get_property_value(dm, thing_id, identifier, value, value_str); - } else if (method_get == linkkit_method_get_event_output_value) { - ret = (*dm)->get_event_output_value(dm, thing_id, identifier, value, value_str); - } else if (method_get == linkkit_method_get_service_output_value) { - ret = (*dm)->get_service_output_value(dm, thing_id, identifier, value, value_str); - } else if (method_get == linkkit_method_get_service_input_value) { - ret = (*dm)->get_service_input_value(dm, thing_id, identifier, value, value_str); - } - - return ret; -} -#ifdef RRPC_ENABLED -int linkkit_answer_service(const void* thing_id, const char* service_identifier, int response_id, int code, int rrpc) -#else -int linkkit_answer_service(const void* thing_id, const char* service_identifier, int response_id, int code) -#endif /* RRPC_ENABLED */ -{ - dm_t** dm = dm_object; - - if (dm == NULL || *dm == NULL || thing_id == NULL || service_identifier == NULL) return -1; - -#ifdef RRPC_ENABLED - return (*dm)->answer_service(dm, thing_id, service_identifier, response_id, code, rrpc); -#else - return (*dm)->answer_service(dm, thing_id, service_identifier, response_id, code); -#endif /* RRPC_ENABLED */ -} - -int linkkit_invoke_raw_service(const void* thing_id, int is_up_raw, void* raw_data, int raw_data_length) -{ - dm_t** dm = dm_object; - int ret; - - if (dm == NULL || *dm == NULL || thing_id == NULL || raw_data == NULL || raw_data_length == 0) return -1; - - if (is_up_raw) { - ret = (*dm)->invoke_raw_service(dm, thing_id, raw_data, raw_data_length); - } else { - ret = (*dm)->answer_raw_service(dm, thing_id, raw_data, raw_data_length); - } - - return ret; -} -#ifdef SERVICE_OTA_ENABLED -int linkkit_invoke_fota_service(void* data_buf, int data_buf_length) -{ - fota_t** ota = fota_object; - int ret; - - if (ota == NULL || *ota == NULL || (*ota)->perform_ota_service == NULL || data_buf == NULL || data_buf_length <= 0) return -1; - - ret = (*ota)->perform_ota_service(ota, data_buf, data_buf_length); - - return ret; -} -#ifdef SERVICE_COTA_ENABLED -int linkkit_invoke_cota_service(void* data_buf, int data_buf_length) -{ - cota_t** ota = cota_object; - int ret; - - if (ota == NULL || *ota == NULL || (*ota)->perform_ota_service == NULL || data_buf == NULL || data_buf_length <= 0) return -1; - - ret = (*ota)->perform_ota_service(ota, data_buf, data_buf_length); - - return ret; -} -int linkkit_invoke_cota_get_config(const char* config_scope, const char* get_type, const char* attribute_Keys, void* option) -{ - cota_t** ota = cota_object; - int ret; - - if (ota == NULL || *ota == NULL || (*ota)->get == NULL) return -1; - - ret = (*ota)->get(ota,config_scope,get_type,attribute_Keys,option); - - return ret; -} -#endif /* SERVICE_COTA_ENABLED*/ -#endif /* SERVICE_OTA_ENABLED */ - -#ifdef DEVICEINFO_ENABLED -int linkkit_trigger_deviceinfo_operate(const void* thing_id, const char* params, linkkit_deviceinfo_operate_t linkkit_deviceinfo_operation) -{ - dm_t** dm = dm_object; - - if (linkkit_deviceinfo_operation == linkkit_deviceinfo_operate_update) { - if (dm == NULL || *dm == NULL || (*dm)->trigger_deviceinfo_update == NULL || thing_id == NULL) return -1; - - return (*dm)->trigger_deviceinfo_update(dm, thing_id, params); - } else if (linkkit_deviceinfo_operation == linkkit_deviceinfo_operate_delete) { - if (dm == NULL || *dm == NULL || (*dm)->trigger_deviceinfo_delete == NULL || thing_id == NULL) return -1; - - return (*dm)->trigger_deviceinfo_delete(dm, thing_id, params); - } - - return -1; -} -#endif - -int linkkit_trigger_event(const void* thing_id, const char* event_identifier, const char* property_identifier) -{ - dm_t** dm = dm_object; - - if (dm == NULL || *dm == NULL || (*dm)->trigger_event == NULL || thing_id == NULL || event_identifier == NULL) return -1; - - return (*dm)->trigger_event(dm, thing_id, event_identifier, property_identifier); -} - -#ifndef CMP_SUPPORT_MULTI_THREAD -int linkkit_yield(int timeout_ms) -{ - dm_t** dm = dm_object; - - if (dm && *dm && (*dm)->yield) { - return (*dm)->yield(dm, timeout_ms); - } - - return -1; -} -#endif diff --git a/iotkit-embedded/sample/linkkit/src/lite_queue.c b/iotkit-embedded/sample/linkkit/src/lite_queue.c deleted file mode 100644 index 16dc416..0000000 --- a/iotkit-embedded/sample/linkkit/src/lite_queue.c +++ /dev/null @@ -1,187 +0,0 @@ -#include - -#include "iot_import.h" -#include "lite_queue.h" - -lite_queue_t* lite_queue_create(int queue_size, int synchronized) -{ - lite_queue_t* lite_queue; - - if (queue_size <= 0) return NULL; - - lite_queue = calloc(1, sizeof(lite_queue_t)); - - if (lite_queue == NULL) goto err_handler; - - lite_queue->queue_size = queue_size; - lite_queue->queue_array_size = queue_size + 1; - - lite_queue->lite_queue_array = calloc(lite_queue->queue_array_size, sizeof(void*)); - - if (lite_queue->lite_queue_array == NULL) goto err_handler; - - if (synchronized) { - lite_queue->lite_queue_mutex = HAL_MutexCreate(); - - if (lite_queue->lite_queue_mutex == NULL) { - goto err_handler; - } - } - - lite_queue->front = 1; - lite_queue->rear = 0; - - return lite_queue; - -err_handler: - if (lite_queue && lite_queue->lite_queue_array) free(lite_queue->lite_queue_array); - - if (lite_queue && lite_queue->lite_queue_mutex) { - HAL_MutexDestroy(lite_queue->lite_queue_mutex); - lite_queue->lite_queue_mutex = NULL; - } - - if (lite_queue) free(lite_queue); - - return lite_queue; -} - -void lite_queue_destroy(lite_queue_t* _lite_queue) -{ - lite_queue_t* lite_queue = _lite_queue; - - if(!_lite_queue) return; - - if (lite_queue && lite_queue->lite_queue_array) { - free(lite_queue->lite_queue_array); - } - - if (lite_queue->lite_queue_mutex) { - HAL_MutexDestroy(lite_queue->lite_queue_mutex); - lite_queue->lite_queue_mutex = NULL; - } - - if (lite_queue) free(lite_queue); -} - -int lite_queue_insert(lite_queue_t* _lite_queue, void* data) -{ - lite_queue_t* lite_queue = _lite_queue; - - if(!_lite_queue) return -1; - - if (lite_queue_is_full(lite_queue)) return -1; - - if (lite_queue->lite_queue_mutex) HAL_MutexLock(lite_queue->lite_queue_mutex); - - lite_queue->rear = (lite_queue->rear + 1) % lite_queue->queue_array_size; - - *(void**)((char*)lite_queue->lite_queue_array + lite_queue->rear * sizeof(void*)) = data; - - if (lite_queue->lite_queue_mutex) HAL_MutexUnlock(lite_queue->lite_queue_mutex); - - return 0; -} - -void* lite_queue_delete(lite_queue_t* _lite_queue) -{ - lite_queue_t* lite_queue = _lite_queue; - void* data; - - if (!_lite_queue || lite_queue_is_empty(lite_queue)) return NULL; - - if (lite_queue->lite_queue_mutex) HAL_MutexLock(lite_queue->lite_queue_mutex); - - data = *(void**)((char*)lite_queue->lite_queue_array + lite_queue->front * (sizeof(void*))); - - lite_queue->front = (lite_queue->front + 1) % lite_queue->queue_array_size; - - if (lite_queue->lite_queue_mutex) HAL_MutexUnlock(lite_queue->lite_queue_mutex); - - return data; -} - -void* lite_queue_first(lite_queue_t* _lite_queue) -{ - lite_queue_t* lite_queue = _lite_queue; - void* data; - - if(!_lite_queue) return NULL; - - if (lite_queue_is_empty(lite_queue)) return NULL; - - if (lite_queue->lite_queue_mutex) HAL_MutexLock(lite_queue->lite_queue_mutex); - - data = *(void**)((char*)lite_queue->lite_queue_array + lite_queue->front * (sizeof(void*))); - - if (lite_queue->lite_queue_mutex) HAL_MutexUnlock(lite_queue->lite_queue_mutex); - - return data; -} - -int lite_queue_is_empty(lite_queue_t* _lite_queue) -{ - lite_queue_t* lite_queue = _lite_queue; - int is_empty; - - if(!_lite_queue) return -1; - - if (lite_queue->lite_queue_mutex) HAL_MutexLock(lite_queue->lite_queue_mutex); - is_empty = (lite_queue->rear + 1) % lite_queue->queue_array_size == lite_queue->front; - if (lite_queue->lite_queue_mutex) HAL_MutexUnlock(lite_queue->lite_queue_mutex); - - return is_empty; -} - -int lite_queue_is_full(lite_queue_t* _lite_queue) -{ - lite_queue_t* lite_queue = _lite_queue; - int is_full; - - if(!_lite_queue) return -1; - - if (lite_queue->lite_queue_mutex) HAL_MutexLock(lite_queue->lite_queue_mutex); - is_full = (lite_queue->rear + 2) % lite_queue->queue_array_size == lite_queue->front; - if (lite_queue->lite_queue_mutex) HAL_MutexUnlock(lite_queue->lite_queue_mutex); - - return is_full; -} - -static void _lite_queue_iterator(lite_queue_t* _lite_queue, handle_queue_item_fp_t handle_fn, va_list* params) -{ - lite_queue_t* lite_queue = _lite_queue; - void* data; - size_t index; - - if(!_lite_queue) return; - - if (lite_queue->lite_queue_mutex) HAL_MutexLock(lite_queue->lite_queue_mutex); - - for (index = lite_queue->front; index <= lite_queue->rear + (lite_queue->front <= lite_queue->rear ? 0 : lite_queue->queue_array_size); ++index) { - data = *(void**)((char*)lite_queue->lite_queue_array + index % lite_queue->queue_array_size * (sizeof(void*))); - - va_list args; - va_copy(args, *params); - - handle_fn(data, &args); - - va_end(args); - } - - if (lite_queue->lite_queue_mutex) HAL_MutexUnlock(lite_queue->lite_queue_mutex); -} - -void lite_queue_iterator(lite_queue_t* _lite_queue, handle_queue_item_fp_t handle_fn, ...) -{ - lite_queue_t* lite_queue = _lite_queue; - - if(!lite_queue || !handle_fn || lite_queue_is_empty(lite_queue)) return; - - va_list params; - - va_start(params, handle_fn); - - _lite_queue_iterator(lite_queue, handle_fn, ¶ms); - - va_end(params); -} diff --git a/iotkit-embedded/sample/mqtt/CMakeLists.txt b/iotkit-embedded/sample/mqtt/CMakeLists.txt deleted file mode 100644 index 0629f9f..0000000 --- a/iotkit-embedded/sample/mqtt/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -include_directories(${PROJECT_SOURCE_DIR}/src/sdk-impl) - -add_executable(mqtt-example mqtt-example.c) -target_link_libraries(mqtt-example iot_sdk) - -add_executable(mqtt_rrpc-example mqtt_rrpc-example.c) -target_link_libraries(mqtt_rrpc-example iot_sdk) diff --git a/iotkit-embedded/sample/mqtt/mqtt-example.c b/iotkit-embedded/sample/mqtt/mqtt-example.c deleted file mode 100644 index 1fbdea7..0000000 --- a/iotkit-embedded/sample/mqtt/mqtt-example.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" - -#if defined(MQTT_ID2_AUTH) && defined(ON_DAILY) - #define PRODUCT_KEY "9rx2yMNV5l0" - #define DEVICE_NAME "sh_online_sample_mqtt" - #define DEVICE_SECRET "v9mqGzepKEphLhXmAoiaUIR2HZ7XwTky" -#elif defined(ON_DAILY) - #define PRODUCT_KEY "gsYfsxQJgeD" - #define DEVICE_NAME "DailyEnvDN" - #define DEVICE_SECRET "y1vzFkEgcuXnvkAfm627pwarx4HRNikX" -#elif defined(MQTT_ID2_AUTH) - #define PRODUCT_KEY "micKUvuzOps" - #define DEVICE_NAME "00AAAAAABBBBBB4B645F5800" - #define DEVICE_SECRET "v9mqGzepKEphLhXmAoiaUIR2HZ7XwTky" -#else - #define PRODUCT_KEY "yfTuLfBJTiL" - #define DEVICE_NAME "TestDeviceForDemo" - #define DEVICE_SECRET "fSCl9Ns5YPnYN8Ocg0VEel1kXFnRlV6c" -#endif - -char __product_key[PRODUCT_KEY_LEN + 1]; -char __device_name[DEVICE_NAME_LEN + 1]; -char __device_secret[DEVICE_SECRET_LEN + 1]; - -/* These are pre-defined topics */ -#define TOPIC_UPDATE "/"PRODUCT_KEY"/"DEVICE_NAME"/update" -#define TOPIC_ERROR "/"PRODUCT_KEY"/"DEVICE_NAME"/update/error" -#define TOPIC_GET "/"PRODUCT_KEY"/"DEVICE_NAME"/get" -#define TOPIC_DATA "/"PRODUCT_KEY"/"DEVICE_NAME"/data" - -/* These are pre-defined topics format*/ -#define TOPIC_UPDATE_FMT "/%s/%s/update" -#define TOPIC_ERROR_FMT "/%s/%s/update/error" -#define TOPIC_GET_FMT "/%s/%s/get" -#define TOPIC_DATA_FMT "/%s/%s/data" - -#define MQTT_MSGLEN (1024) - -#define EXAMPLE_TRACE(fmt, ...) \ - do { \ - HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ - HAL_Printf(fmt, ##__VA_ARGS__); \ - HAL_Printf("%s", "\r\n"); \ - } while(0) - -static int user_argc; -static char **user_argv; - -void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_UNDEF: - EXAMPLE_TRACE("undefined event occur."); - break; - - case IOTX_MQTT_EVENT_DISCONNECT: - EXAMPLE_TRACE("MQTT disconnect."); - break; - - case IOTX_MQTT_EVENT_RECONNECT: - EXAMPLE_TRACE("MQTT reconnect."); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - EXAMPLE_TRACE("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - EXAMPLE_TRACE("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - EXAMPLE_TRACE("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: - EXAMPLE_TRACE("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - EXAMPLE_TRACE("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK: - EXAMPLE_TRACE("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: - EXAMPLE_TRACE("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: - EXAMPLE_TRACE("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_NACK: - EXAMPLE_TRACE("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - EXAMPLE_TRACE("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - - case IOTX_MQTT_EVENT_BUFFER_OVERFLOW: - EXAMPLE_TRACE("buffer overflow, %s", msg->msg); - break; - - default: - EXAMPLE_TRACE("Should NOT arrive here."); - break; - } -} - -static void _demo_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg; - - /* print topic name and topic message */ - EXAMPLE_TRACE("----"); - EXAMPLE_TRACE("packetId: %d", ptopic_info->packet_id); - EXAMPLE_TRACE("Topic: '%.*s' (Length: %d)", - ptopic_info->topic_len, - ptopic_info->ptopic, - ptopic_info->topic_len); - EXAMPLE_TRACE("Payload: '%.*s' (Length: %d)", - ptopic_info->payload_len, - ptopic_info->payload, - ptopic_info->payload_len); - EXAMPLE_TRACE("----"); -} - -#ifndef MQTT_ID2_AUTH -int mqtt_client(void) -{ - int rc = 0, msg_len, cnt = 0; - void *pclient; - iotx_conn_info_pt pconn_info; - iotx_mqtt_param_t mqtt_params; - iotx_mqtt_topic_info_t topic_msg; - char msg_pub[128]; - char *msg_buf = NULL, *msg_readbuf = NULL; - - if (NULL == (msg_buf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - if (NULL == (msg_readbuf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - HAL_GetProductKey(__product_key); - HAL_GetDeviceName(__device_name); - HAL_GetDeviceSecret(__device_secret); - - /* Device AUTH */ - if (0 != IOT_SetupConnInfo(__product_key, __device_name, __device_secret, (void **)&pconn_info)) { - EXAMPLE_TRACE("AUTH request failed!"); - rc = -1; - goto do_exit; - } - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = msg_readbuf; - mqtt_params.read_buf_size = MQTT_MSGLEN; - mqtt_params.pwrite_buf = msg_buf; - mqtt_params.write_buf_size = MQTT_MSGLEN; - - mqtt_params.handle_event.h_fp = event_handle; - mqtt_params.handle_event.pcontext = NULL; - - - /* Construct a MQTT client with specify parameter */ - pclient = IOT_MQTT_Construct(&mqtt_params); - if (NULL == pclient) { - EXAMPLE_TRACE("MQTT construct failed"); - rc = -1; - goto do_exit; - } - - /* Initialize topic information */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - strcpy(msg_pub, "update: hello! start!"); - - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - rc = IOT_MQTT_Publish(pclient, TOPIC_UPDATE, &topic_msg); - if (rc < 0) { - IOT_MQTT_Destroy(&pclient); - EXAMPLE_TRACE("error occur when publish"); - rc = -1; - goto do_exit; - } - - EXAMPLE_TRACE("\n publish message: \n topic: %s\n payload: \%s\n rc = %d", TOPIC_UPDATE, topic_msg.payload, rc); - - /* Subscribe the specific topic */ - rc = IOT_MQTT_Subscribe(pclient, TOPIC_DATA, IOTX_MQTT_QOS1, _demo_message_arrive, NULL); - if (rc < 0) { - IOT_MQTT_Destroy(&pclient); - EXAMPLE_TRACE("IOT_MQTT_Subscribe() failed, rc = %d", rc); - rc = -1; - goto do_exit; - } - - /* Initialize topic information */ - memset(msg_pub, 0x0, 128); - strcpy(msg_pub, "data: hello! start!"); - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - rc = IOT_MQTT_Publish(pclient, TOPIC_DATA, &topic_msg); - EXAMPLE_TRACE("\n publish message: \n topic: %s\n payload: \%s\n rc = %d", TOPIC_DATA, topic_msg.payload, rc); - - IOT_MQTT_Yield(pclient, 200); - - do { - /* Generate topic message */ - cnt++; - msg_len = snprintf(msg_pub, sizeof(msg_pub), "{\"attr_name\":\"temperature\", \"attr_value\":\"%d\"}", cnt); - if (msg_len < 0) { - EXAMPLE_TRACE("Error occur! Exit program"); - rc = -1; - break; - } - - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = msg_len; - - rc = IOT_MQTT_Publish(pclient, TOPIC_DATA, &topic_msg); - if (rc < 0) { - EXAMPLE_TRACE("error occur when publish"); - rc = -1; - break; - } -#ifdef MQTT_ID2_CRYPTO - EXAMPLE_TRACE("packet-id=%u, publish topic msg='0x%02x%02x%02x%02x'...", - (uint32_t)rc, - msg_pub[0], msg_pub[1], msg_pub[2], msg_pub[3] - ); -#else - EXAMPLE_TRACE("packet-id=%u, publish topic msg=%s", (uint32_t)rc, msg_pub); -#endif - - /* handle the MQTT packet received from TCP or SSL connection */ - IOT_MQTT_Yield(pclient, 200); - - /* infinite loop if running with 'loop' argument */ - if (user_argc >= 2 && !strcmp("loop", user_argv[1])) { - HAL_SleepMs(2000); - cnt = 0; - } - - } while (cnt < 1); - - IOT_MQTT_Yield(pclient, 200); - - IOT_MQTT_Unsubscribe(pclient, TOPIC_DATA); - - IOT_MQTT_Yield(pclient, 200); - - IOT_MQTT_Destroy(&pclient); - -do_exit: - if (NULL != msg_buf) { - HAL_Free(msg_buf); - } - - if (NULL != msg_readbuf) { - HAL_Free(msg_readbuf); - } - - return rc; -} -#endif /* MQTT_ID2_AUTH */ - -#ifdef MQTT_ID2_AUTH -#include "tfs.h" -char __device_id2[TFS_ID2_LEN + 1]; -int mqtt_client_secure() -{ - int rc = 0, msg_len, cnt = 0; - void *pclient; - iotx_conn_info_pt pconn_info; - iotx_mqtt_param_t mqtt_params; - iotx_mqtt_topic_info_t topic_msg; - char msg_pub[128]; - char *msg_buf = NULL, *msg_readbuf = NULL; - char topic_update[IOTX_URI_MAX_LEN] = {0}; - char topic_error[IOTX_URI_MAX_LEN] = {0}; - char topic_get[IOTX_URI_MAX_LEN] = {0}; - char topic_data[IOTX_URI_MAX_LEN] = {0}; - - if (NULL == (msg_buf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - if (NULL == (msg_readbuf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - HAL_GetProductKey(__product_key); - HAL_GetID2(__device_id2); - - /* Device AUTH */ - rc = IOT_SetupConnInfoSecure(__product_key, __device_id2, __device_id2, (void **)&pconn_info); - if (rc != 0) { - EXAMPLE_TRACE("AUTH request failed!"); - goto do_exit; - } - - HAL_Snprintf(topic_update,IOTX_URI_MAX_LEN,TOPIC_UPDATE_FMT,__product_key,__device_id2); - HAL_Snprintf(topic_error,IOTX_URI_MAX_LEN,TOPIC_ERROR_FMT,__product_key,__device_id2); - HAL_Snprintf(topic_get,IOTX_URI_MAX_LEN,TOPIC_GET_FMT,__product_key,__device_id2); - HAL_Snprintf(topic_data,IOTX_URI_MAX_LEN,TOPIC_DATA_FMT,__product_key,__device_id2); - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = msg_readbuf; - mqtt_params.read_buf_size = MQTT_MSGLEN; - mqtt_params.pwrite_buf = msg_buf; - mqtt_params.write_buf_size = MQTT_MSGLEN; - - mqtt_params.handle_event.h_fp = event_handle; - mqtt_params.handle_event.pcontext = NULL; - - /* Construct a MQTT client with specify parameter */ - pclient = IOT_MQTT_ConstructSecure(&mqtt_params); - if (NULL == pclient) { - EXAMPLE_TRACE("MQTT construct failed"); - rc = -1; - goto do_exit; - } - - /* Subscribe the specific topic */ - rc = IOT_MQTT_Subscribe(pclient, topic_data, IOTX_MQTT_QOS1, _demo_message_arrive, NULL); - if (rc < 0) { - IOT_MQTT_Destroy(&pclient); - EXAMPLE_TRACE("IOT_MQTT_Subscribe() failed, rc = %d", rc); - rc = -1; - goto do_exit; - } - - HAL_SleepMs(1000); - - /* Initialize topic information */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - strcpy(msg_pub, "message: hello! start!"); - - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - rc = IOT_MQTT_Publish(pclient, topic_data, &topic_msg); - EXAMPLE_TRACE("rc = IOT_MQTT_Publish() = %d", rc); - - do { - /* Generate topic message */ - cnt++; - msg_len = snprintf(msg_pub, sizeof(msg_pub), "{\"attr_name\":\"temperature\", \"attr_value\":\"%d\"}", cnt); - if (msg_len < 0) { - EXAMPLE_TRACE("Error occur! Exit program"); - rc = -1; - break; - } - - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = msg_len; - - rc = IOT_MQTT_Publish(pclient, topic_data, &topic_msg); - if (rc < 0) { - EXAMPLE_TRACE("error occur when publish"); - rc = -1; - break; - } - EXAMPLE_TRACE("packet-id=%u, publish topic msg='0x%02x%02x%02x%02x'...", - (uint32_t)rc, - msg_pub[0], msg_pub[1], msg_pub[2], msg_pub[3] - ); - - /* handle the MQTT packet received from TCP or SSL connection */ - IOT_MQTT_Yield(pclient, 200); - - /* infinite loop if running with 'loop' argument */ - if (user_argc >= 2 && !strcmp("loop", user_argv[1])) { - HAL_SleepMs(2000); - cnt = 0; - } - - } while (cnt < 1); - - IOT_MQTT_Unsubscribe(pclient, TOPIC_DATA); - - HAL_SleepMs(200); - - IOT_MQTT_Destroy(&pclient); - -do_exit: - if (NULL != msg_buf) { - HAL_Free(msg_buf); - } - - if (NULL != msg_readbuf) { - HAL_Free(msg_readbuf); - } - - return rc; - -} -#endif /* MQTT_ID2_AUTH*/ - -int main(int argc, char **argv) -{ - IOT_OpenLog("mqtt"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - - user_argc = argc; - user_argv = argv; - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - -#ifndef MQTT_ID2_AUTH - mqtt_client(); -#else - mqtt_client_secure(); -#endif - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - EXAMPLE_TRACE("out of sample!"); - - return 0; -} - diff --git a/iotkit-embedded/sample/mqtt/mqtt_multi_region-example.c b/iotkit-embedded/sample/mqtt/mqtt_multi_region-example.c deleted file mode 100644 index e1e1b97..0000000 --- a/iotkit-embedded/sample/mqtt/mqtt_multi_region-example.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" -#include "exports/iot_export_cmp.h" - - -/* Singapore Domain */ -#define PRODUCT_KEY_SG "a1eYfJ2QGei" -#define DEVICE_NAME_SG "Test1" -#define DEVICE_SECRET_SG "teVDZgu2T3qnDQ2MeUVqGoBZ3qxKPYHL" - -/* Japan Domain */ -#define PRODUCT_KEY_JP "a1R9GUtrTPd" -#define DEVICE_NAME_JP "Test1" -#define DEVICE_SECRET_JP "cVhDbPYGoSBIpfnFXjJYKXBtVXa19rRY" - -/* America Domain */ -#define PRODUCT_KEY_US "a1FGqgmMbcg" -#define DEVICE_NAME_US "Test1" -#define DEVICE_SECRET_US "5jGnXkBY7HeHChZPDZzEHcqIeYdnvPkl" - -/* Germany Domain */ -#define PRODUCT_KEY_GER "a1jKEbfQ7at" -#define DEVICE_NAME_GER "Test1" -#define DEVICE_SECRET_GER "818ExRExkfDGF8p3ElX3DzSFNBzKnE8F" - -/* Shanghai Domain */ -#if defined(ON_DAILY) - #define PRODUCT_KEY "gsYfsxQJgeD" - #define DEVICE_NAME "DailyEnvDN" - #define DEVICE_SECRET "y1vzFkEgcuXnvkAfm627pwarx4HRNikX" -#else - #define PRODUCT_KEY "a1IfbZi3oDt" - #define DEVICE_NAME "Test1" - #define DEVICE_SECRET "kuzVoswkUIdb9uXm4T8ykIJushFym8RL" -#endif - -char __product_key[PRODUCT_KEY_LEN + 1]; -char __device_name[DEVICE_NAME_LEN + 1]; -char __device_secret[DEVICE_SECRET_LEN + 1]; - -/* These are pre-defined topics */ -#define TOPIC_UPDATE "/"PRODUCT_KEY"/"DEVICE_NAME"/update" -#define TOPIC_ERROR "/"PRODUCT_KEY"/"DEVICE_NAME"/update/error" -#define TOPIC_GET "/"PRODUCT_KEY"/"DEVICE_NAME"/get" -#define TOPIC_DATA "/"PRODUCT_KEY"/"DEVICE_NAME"/data" - -/* These are pre-defined topics format*/ -#define TOPIC_UPDATE_FMT "/%s/%s/update" -#define TOPIC_ERROR_FMT "/%s/%s/update/error" -#define TOPIC_GET_FMT "/%s/%s/get" -#define TOPIC_DATA_FMT "/%s/%s/data" - -#define MQTT_MSGLEN (1024) - -#define EXAMPLE_TRACE(fmt, ...) \ - do { \ - HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ - HAL_Printf(fmt, ##__VA_ARGS__); \ - HAL_Printf("%s", "\r\n"); \ - } while(0) - -static int user_argc; -static char **user_argv; - -void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_UNDEF: - EXAMPLE_TRACE("undefined event occur."); - break; - - case IOTX_MQTT_EVENT_DISCONNECT: - EXAMPLE_TRACE("MQTT disconnect."); - break; - - case IOTX_MQTT_EVENT_RECONNECT: - EXAMPLE_TRACE("MQTT reconnect."); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - EXAMPLE_TRACE("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - EXAMPLE_TRACE("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - EXAMPLE_TRACE("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: - EXAMPLE_TRACE("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - EXAMPLE_TRACE("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK: - EXAMPLE_TRACE("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: - EXAMPLE_TRACE("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: - EXAMPLE_TRACE("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_NACK: - EXAMPLE_TRACE("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - EXAMPLE_TRACE("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - - case IOTX_MQTT_EVENT_BUFFER_OVERFLOW: - EXAMPLE_TRACE("buffer overflow, %s", msg->msg); - break; - - default: - EXAMPLE_TRACE("Should NOT arrive here."); - break; - } -} - -static void _demo_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg; - - /* print topic name and topic message */ - EXAMPLE_TRACE("----"); - EXAMPLE_TRACE("packetId: %d", ptopic_info->packet_id); - EXAMPLE_TRACE("Topic: '%.*s' (Length: %d)", - ptopic_info->topic_len, - ptopic_info->ptopic, - ptopic_info->topic_len); - EXAMPLE_TRACE("Payload: '%.*s' (Length: %d)", - ptopic_info->payload_len, - ptopic_info->payload, - ptopic_info->payload_len); - EXAMPLE_TRACE("----"); -} - - -int mqtt_client(void) -{ - int rc = 0, msg_len, cnt = 0; - void *pclient; - iotx_conn_info_pt pconn_info; - iotx_mqtt_param_t mqtt_params; - iotx_mqtt_topic_info_t topic_msg; - char msg_pub[128]; - char *msg_buf = NULL, *msg_readbuf = NULL; - char topic_update[IOTX_URI_MAX_LEN] = {0}; - char topic_error[IOTX_URI_MAX_LEN] = {0}; - char topic_get[IOTX_URI_MAX_LEN] = {0}; - char topic_data[IOTX_URI_MAX_LEN] = {0}; - - if (NULL == (msg_buf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - if (NULL == (msg_readbuf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - HAL_GetProductKey(__product_key); - HAL_GetDeviceName(__device_name); - HAL_GetDeviceSecret(__device_secret); - - /* Device AUTH */ - if (0 != IOT_SetupConnInfo(__product_key, __device_name, __device_secret, (void **)&pconn_info)) { - EXAMPLE_TRACE("AUTH request failed!"); - rc = -1; - goto do_exit; - } - - HAL_Snprintf(topic_update,IOTX_URI_MAX_LEN,TOPIC_UPDATE_FMT,__product_key,__device_name); - HAL_Snprintf(topic_error,IOTX_URI_MAX_LEN,TOPIC_ERROR_FMT,__product_key,__device_name); - HAL_Snprintf(topic_get,IOTX_URI_MAX_LEN,TOPIC_GET_FMT,__product_key,__device_name); - HAL_Snprintf(topic_data,IOTX_URI_MAX_LEN,TOPIC_DATA_FMT,__product_key,__device_name); - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = msg_readbuf; - mqtt_params.read_buf_size = MQTT_MSGLEN; - mqtt_params.pwrite_buf = msg_buf; - mqtt_params.write_buf_size = MQTT_MSGLEN; - - mqtt_params.handle_event.h_fp = event_handle; - mqtt_params.handle_event.pcontext = NULL; - - - /* Construct a MQTT client with specify parameter */ - pclient = IOT_MQTT_Construct(&mqtt_params); - if (NULL == pclient) { - EXAMPLE_TRACE("MQTT construct failed"); - rc = -1; - goto do_exit; - } - - /* Initialize topic information */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - strcpy(msg_pub, "update: hello! start!"); - - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - rc = IOT_MQTT_Publish(pclient, topic_update, &topic_msg); - if (rc < 0) { - IOT_MQTT_Destroy(&pclient); - EXAMPLE_TRACE("error occur when publish"); - rc = -1; - goto do_exit; - } - - EXAMPLE_TRACE("\n publish message: \n topic: %s\n payload: \%s\n rc = %d", topic_update, topic_msg.payload, rc); - - /* Subscribe the specific topic */ - rc = IOT_MQTT_Subscribe(pclient, topic_data, IOTX_MQTT_QOS1, _demo_message_arrive, NULL); - if (rc < 0) { - IOT_MQTT_Destroy(&pclient); - EXAMPLE_TRACE("IOT_MQTT_Subscribe() failed, rc = %d", rc); - rc = -1; - goto do_exit; - } - - /* Initialize topic information */ - memset(msg_pub, 0x0, 128); - strcpy(msg_pub, "data: hello! start!"); - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - rc = IOT_MQTT_Publish(pclient, topic_data, &topic_msg); - EXAMPLE_TRACE("\n publish message: \n topic: %s\n payload: \%s\n rc = %d", topic_data, topic_msg.payload, rc); - - IOT_MQTT_Yield(pclient, 200); - - do { - /* Generate topic message */ - cnt++; - msg_len = snprintf(msg_pub, sizeof(msg_pub), "{\"attr_name\":\"temperature\", \"attr_value\":\"%d\"}", cnt); - if (msg_len < 0) { - EXAMPLE_TRACE("Error occur! Exit program"); - rc = -1; - break; - } - - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = msg_len; - - rc = IOT_MQTT_Publish(pclient, topic_data, &topic_msg); - if (rc < 0) { - EXAMPLE_TRACE("error occur when publish"); - rc = -1; - break; - } -#ifdef MQTT_ID2_CRYPTO - EXAMPLE_TRACE("packet-id=%u, publish topic msg='0x%02x%02x%02x%02x'...", - (uint32_t)rc, - msg_pub[0], msg_pub[1], msg_pub[2], msg_pub[3] - ); -#else - EXAMPLE_TRACE("packet-id=%u, publish topic msg=%s", (uint32_t)rc, msg_pub); -#endif - - /* handle the MQTT packet received from TCP or SSL connection */ - IOT_MQTT_Yield(pclient, 200); - - /* infinite loop if running with 'loop' argument */ - if (user_argc >= 2 && !strcmp("loop", user_argv[1])) { - HAL_SleepMs(2000); - cnt = 0; - } - - } while (cnt < 1); - - IOT_MQTT_Yield(pclient, 200); - - IOT_MQTT_Unsubscribe(pclient, topic_data); - - IOT_MQTT_Yield(pclient, 200); - - IOT_MQTT_Destroy(&pclient); - -do_exit: - if (NULL != msg_buf) { - HAL_Free(msg_buf); - } - - if (NULL != msg_readbuf) { - HAL_Free(msg_readbuf); - } - - return rc; -} - -int ali_mqtt_region_test(int argc, char **argv) -{ - int opt; - char region[5]; - int domain_type; - - while ((opt = getopt(argc, argv, "r:")) != -1) - { - if ('r' == opt) - { - strncpy(region, optarg, (strlen(optarg)>5)?5:strlen(optarg)); - } - else - { - HAL_Printf("usage: mqtt_multi_region-example -r [PARAMTER]\r\n"); - HAL_Printf("\t-r sh \t\tSelect Shanghai demain.\r\n"); - HAL_Printf("\t-r sg \t\tSelect Singapore demain.\r\n"); - HAL_Printf("\t-r jp \t\tSelect Japan demain.\r\n"); - HAL_Printf("\t-r us \t\tSelect America demain.\r\n"); - HAL_Printf("\t-r ger\t\tSelect Germany demain.\r\n"); - return 1; - } - } - - if (0 == strncmp(region, "sg", strlen("sg"))) - { - domain_type = IOTX_CLOUD_DOMAIN_SG; - HAL_SetProductKey(PRODUCT_KEY_SG); - HAL_SetDeviceName(DEVICE_NAME_SG); - HAL_SetDeviceSecret(DEVICE_SECRET_SG); - - EXAMPLE_TRACE("Singapore Domain selected"); - } - else if (0 == strncmp(region, "jp", strlen("jp"))) - { - domain_type = IOTX_CLOUD_DOMAIN_JP; - HAL_SetProductKey(PRODUCT_KEY_JP); - HAL_SetDeviceName(DEVICE_NAME_JP); - HAL_SetDeviceSecret(DEVICE_SECRET_JP); - - EXAMPLE_TRACE("Japan Domain selected"); - } - else if (0 == strncmp(region, "us", strlen("us"))) - { - domain_type = IOTX_CLOUD_DOMAIN_US; - HAL_SetProductKey(PRODUCT_KEY_US); - HAL_SetDeviceName(DEVICE_NAME_US); - HAL_SetDeviceSecret(DEVICE_SECRET_US); - - EXAMPLE_TRACE("America Domain selected"); - } - else if (0 == strncmp(region, "ger", strlen("ger"))) - { - domain_type = IOTX_CLOUD_DOMAIN_GER; - HAL_SetProductKey(PRODUCT_KEY_GER); - HAL_SetDeviceName(DEVICE_NAME_GER); - HAL_SetDeviceSecret(DEVICE_SECRET_GER); - - EXAMPLE_TRACE("Germany Domain selected"); - } - else - { - domain_type = IOTX_CLOUD_DOMAIN_SH; - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - - EXAMPLE_TRACE("Shanghai Domain selected"); - } - - IOT_OpenLog("mqtt"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - IOT_SetupDomain(domain_type); - - mqtt_client(); - - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - EXAMPLE_TRACE("out of sample!"); - - return 0; -} - diff --git a/iotkit-embedded/sample/mqtt/mqtt_multi_thread-example.c b/iotkit-embedded/sample/mqtt/mqtt_multi_thread-example.c deleted file mode 100644 index aec7a14..0000000 --- a/iotkit-embedded/sample/mqtt/mqtt_multi_thread-example.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifdef _PLATFORM_IS_LINUX_ - -#include -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" - -#include -#include - -#define PRODUCT_KEY "yfTuLfBJTiL" -#define DEVICE_NAME "TestDeviceForDemo" -#define DEVICE_SECRET "fSCl9Ns5YPnYN8Ocg0VEel1kXFnRlV6c" - -/* These are pre-defined topics */ -#define TOPIC_UPDATE "/"PRODUCT_KEY"/"DEVICE_NAME"/update" -#define TOPIC_ERROR "/"PRODUCT_KEY"/"DEVICE_NAME"/update/error" -#define TOPIC_GET "/"PRODUCT_KEY"/"DEVICE_NAME"/get" -#define TOPIC_DATA "/"PRODUCT_KEY"/"DEVICE_NAME"/data" - -#define MQTT_MSGLEN (1024) - -char g_product_key[PRODUCT_KEY_LEN + 1]; -char g_product_secret[PRODUCT_SECRET_LEN + 1]; -char g_device_name[DEVICE_NAME_LEN + 1]; -char g_device_secret[DEVICE_SECRET_LEN + 1]; - -#define EXAMPLE_TRACE(fmt, ...) \ - do { \ - HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ - HAL_Printf(fmt, ##__VA_ARGS__); \ - HAL_Printf("%s", "\r\n"); \ - } while(0) - - -void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_UNDEF: - EXAMPLE_TRACE("undefined event occur."); - break; - - case IOTX_MQTT_EVENT_DISCONNECT: - EXAMPLE_TRACE("MQTT disconnect."); - break; - - case IOTX_MQTT_EVENT_RECONNECT: - EXAMPLE_TRACE("MQTT reconnect."); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - EXAMPLE_TRACE("subscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - EXAMPLE_TRACE("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - EXAMPLE_TRACE("subscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: - EXAMPLE_TRACE("unsubscribe success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - EXAMPLE_TRACE("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK: - EXAMPLE_TRACE("unsubscribe nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: - EXAMPLE_TRACE("publish success, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: - EXAMPLE_TRACE("publish timeout, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_NACK: - EXAMPLE_TRACE("publish nack, packet-id=%u", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - EXAMPLE_TRACE("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - - default: - EXAMPLE_TRACE("Should NOT arrive here."); - break; - } -} - -static void _demo_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg; - - /* print topic name and topic message */ - EXAMPLE_TRACE("----"); - EXAMPLE_TRACE("Topic: '%.*s' (Length: %d)", - ptopic_info->topic_len, - ptopic_info->ptopic, - ptopic_info->topic_len); - EXAMPLE_TRACE("Payload: '%.*s' (Length: %d)", - ptopic_info->payload_len, - ptopic_info->payload, - ptopic_info->payload_len); - EXAMPLE_TRACE("----"); -} - -void* thread_subscribe1(void *pclient) -{ - int ret = -1; - int cnt = 400; - - while(--cnt) { - HAL_SleepMs(100); - ret = IOT_MQTT_Subscribe(pclient, TOPIC_DATA, IOTX_MQTT_QOS1, _demo_message_arrive, NULL); - if (ret < 0) { - printf("subscribe error"); - return NULL; - } - HAL_SleepMs(20); - ret = IOT_MQTT_Unsubscribe(pclient, TOPIC_GET); - if (ret < 0) { - printf("subscribe error"); - return NULL; - } - HAL_SleepMs(100); - } - return NULL; -} - -void* thread_subscribe2(void *pclient) -{ - int ret = -1; - int cnt = 400; - - while(--cnt) { - HAL_SleepMs(300); - ret = IOT_MQTT_Unsubscribe(pclient, TOPIC_DATA); - if (ret < 0) { - printf("subscribe error"); - return NULL; - } - HAL_SleepMs(30); - ret = IOT_MQTT_Subscribe(pclient, TOPIC_GET, IOTX_MQTT_QOS1, _demo_message_arrive, NULL); - if (ret < 0) { - printf("subscribe error"); - return NULL; - } - HAL_SleepMs(30); - } - return NULL; -} - -// 多线程subscribe -void CASE2(void * pclient) -{ - int ret = -1; - pthread_t pid1; - pthread_t pid2; - - if (pclient == NULL) { - printf("param error"); - return; - } - - ret = pthread_create(&pid1, NULL, thread_subscribe1, (void*)pclient); - if (ret != 0) { - printf("pthread_create failed!\n"); - return; - } - - ret = pthread_create(&pid2, NULL, thread_subscribe2, (void*)pclient); - if (ret != 0) { - printf("pthread_create failed!\n"); - return; - } -} - - - -void* thread_publish1(void *pclient) -{ - int cnt = 400; - int ret = -1; - char msg_pub[MQTT_MSGLEN] = {0}; - iotx_mqtt_topic_info_t topic_msg; - - strcpy(msg_pub, "11111 message: hello! start!"); - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - while(--cnt) { - ret = IOT_MQTT_Publish(pclient, TOPIC_DATA, &topic_msg); - printf("thread<%d>:ret = %d\n", (int)pthread_self(), ret); - HAL_SleepMs(300); - } - - return NULL; -} - -void* thread_publish2(void *pclient) -{ - int cnt = 600; - int ret = -1; - char msg_pub[MQTT_MSGLEN] = {0}; - iotx_mqtt_topic_info_t topic_msg; - - strcpy(msg_pub, "22222 message: hello! start!"); - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - while(--cnt) { - ret = IOT_MQTT_Publish(pclient, TOPIC_DATA, &topic_msg); - printf("thread<%d>:ret = %d\n", (int)pthread_self(), ret); - HAL_SleepMs(200); - } - - return NULL; -} - -// 多线程publish -void CASE1(void * pclient) -{ - int ret = -1; - pthread_t pid1; - pthread_t pid2; - - if (pclient == NULL) { - printf("param error"); - return; - } - - ret = IOT_MQTT_Subscribe(pclient, TOPIC_DATA, IOTX_MQTT_QOS1, _demo_message_arrive, NULL); - if (ret < 0) { - printf("subscribe error"); - return; - } - - ret = pthread_create(&pid1, NULL, thread_publish1, (void*)pclient); - if (ret != 0) { - printf("pthread_create failed!\n"); - return; - } - - ret = pthread_create(&pid2, NULL, thread_publish2, (void*)pclient); - if (ret != 0) { - printf("pthread_create failed!\n"); - return; - } -} - - -// yield thread -static int yield_exit = 0; - -void *thread_yield(void *pclient) -{ - while(yield_exit == 0) { - IOT_MQTT_Yield(pclient, 200); - - HAL_SleepMs(200); - } - - return NULL; -} - - -int mqtt_client(void) -{ - int rc = 0;//, msg_len, cnt = 0; - void *pclient; - iotx_conn_info_pt pconn_info; - iotx_mqtt_param_t mqtt_params; - char *msg_buf = NULL, *msg_readbuf = NULL; - pthread_t pid1; - - if (NULL == (msg_buf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - if (NULL == (msg_readbuf = (char *)HAL_Malloc(MQTT_MSGLEN))) { - EXAMPLE_TRACE("not enough memory"); - rc = -1; - goto do_exit; - } - - /**< get device info*/ - HAL_GetProductKey(g_product_key); - HAL_GetDeviceName(g_device_name); - HAL_GetDeviceSecret(g_device_secret); - /**< end*/ - /* Device AUTH */ - if (0 != IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&pconn_info)) { - EXAMPLE_TRACE("AUTH request failed!"); - rc = -1; - goto do_exit; - } - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = msg_readbuf; - mqtt_params.read_buf_size = MQTT_MSGLEN; - mqtt_params.pwrite_buf = msg_buf; - mqtt_params.write_buf_size = MQTT_MSGLEN; - - mqtt_params.handle_event.h_fp = event_handle; - mqtt_params.handle_event.pcontext = NULL; - - - /* Construct a MQTT client with specify parameter */ - pclient = IOT_MQTT_Construct(&mqtt_params); - if (NULL == pclient) { - EXAMPLE_TRACE("MQTT construct failed"); - rc = -1; - goto do_exit; - } - - EXAMPLE_TRACE("TEST CASE"); - pthread_create(&pid1, NULL, thread_yield, (void*)pclient); - - // mutli thread publish - CASE1(pclient); - - // mutli thread subscribe - CASE2(pclient); - - HAL_SleepMs(100000); - IOT_MQTT_Unsubscribe(pclient, TOPIC_DATA); - IOT_MQTT_Unsubscribe(pclient, TOPIC_GET); - - HAL_SleepMs(200); - yield_exit = 1; - HAL_SleepMs(200); - - - IOT_MQTT_Destroy(&pclient); - -do_exit: - if (NULL != msg_buf) { - HAL_Free(msg_buf); - } - - if (NULL != msg_readbuf) { - HAL_Free(msg_readbuf); - } - - return rc; -} - - -int main(int argc, char **argv) -{ - IOT_OpenLog("mqtt"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - /**< set device info*/ - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - /**< end*/ - mqtt_client(); - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - EXAMPLE_TRACE("out of sample!"); - - return 0; -} - -#else - -int main(int argc, char **argv) -{ - /*EXAMPLE_TRACE("not support, pleasae support multi-thread first!!!"); - - EXAMPLE_TRACE("Linux is support, please build in ubuntu.x86");*/ - - return 0; -} -#endif - diff --git a/iotkit-embedded/sample/mqtt/mqtt_rrpc-example.c b/iotkit-embedded/sample/mqtt/mqtt_rrpc-example.c deleted file mode 100644 index 114f6f6..0000000 --- a/iotkit-embedded/sample/mqtt/mqtt_rrpc-example.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" - -#define PRODUCT_KEY "lLeATwv18gi" -#define DEVICE_NAME "test1" -#define DEVICE_SECRET "HQ4AB77MRpAxzgRQAnJdjewGaiEBoJZR" - -/* These are the pre-defined topics */ -#define TOPIC_RRPC_REQ "/sys/"PRODUCT_KEY"/"DEVICE_NAME"/rrpc/request/" -#define TOPIC_RRPC_RSP "/sys/"PRODUCT_KEY"/"DEVICE_NAME"/rrpc/response/" - -#define TEST_TOPIC "/sys/lLeATwv18gi/test1/rrpc/request/890192612580343808" -#define TEST_PAYLOAD "hello world" -#define TEST_TOPIC_PAYLOAD "/sys/lLeATwv18gi/test1/rrpc/request/890192612580343808hello world" - -char g_product_key[PRODUCT_KEY_LEN + 1]; -char g_product_secret[PRODUCT_SECRET_LEN + 1]; -char g_device_name[DEVICE_NAME_LEN + 1]; -char g_device_secret[DEVICE_SECRET_LEN + 1]; - -#define RRPC_MQTT_MSGLEN (1024) -#define MSG_ID_LEN_MAX (64) -#define TOPIC_LEN_MAX (1024) - -static int running_unittest = 0; - -void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_UNDEF: - HAL_Printf("undefined event occur.\n"); - break; - - case IOTX_MQTT_EVENT_DISCONNECT: - HAL_Printf("MQTT disconnect.\n"); - break; - - case IOTX_MQTT_EVENT_RECONNECT: - HAL_Printf("MQTT reconnect.\n"); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - HAL_Printf("subscribe success, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - HAL_Printf("subscribe wait ack timeout, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - HAL_Printf("subscribe nack, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: - HAL_Printf("unsubscribe success, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - HAL_Printf("unsubscribe timeout, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK: - HAL_Printf("unsubscribe nack, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: - HAL_Printf("publish success, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: - HAL_Printf("publish timeout, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_NACK: - HAL_Printf("publish nack, packet-id=%u\n", (unsigned int)packet_id); - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - HAL_Printf("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s\n", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - - default: - HAL_Printf("Should NOT arrive here.\n"); - break; - } -} - - -void mqtt_rrpc_msg_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg; - iotx_mqtt_topic_info_t topic_msg; - char msg_pub[RRPC_MQTT_MSGLEN] = {0}; - char topic[TOPIC_LEN_MAX] = {0}; - char msg_id[MSG_ID_LEN_MAX] = {0}; - - /* print topic name and topic message */ - HAL_Printf("----\n"); - HAL_Printf("Topic: '%.*s' (Length: %d)\n", - ptopic_info->topic_len, - ptopic_info->ptopic, - ptopic_info->topic_len); - HAL_Printf("Payload: '%.*s' (Length: %d)\n", - ptopic_info->payload_len, - ptopic_info->payload, - ptopic_info->payload_len); - HAL_Printf("----\n"); - - if (snprintf(msg_id, - ptopic_info->topic_len - strlen(TOPIC_RRPC_REQ) + 1, - "%s", - ptopic_info->ptopic + strlen(TOPIC_RRPC_REQ)) - > sizeof(msg_id)) { - HAL_Printf("snprintf error!\n"); - return; - } - - HAL_Printf("response msg_id = %s\n", msg_id); - if (snprintf(topic, sizeof(topic), "%s%s", TOPIC_RRPC_RSP, msg_id) > sizeof(topic)) { - HAL_Printf("snprintf error!\n"); - return; - } - HAL_Printf("response topic = %s\n", topic); - - sprintf(msg_pub, "rrpc client has received message!\n"); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - if (IOT_MQTT_Publish(pclient, topic, &topic_msg) < 0) { - HAL_Printf("error occur when publish!\n"); - } -} - - -int mqtt_rrpc_client(void) -{ - int rc = 0; - void *pclient; - iotx_conn_info_pt pconn_info; - iotx_mqtt_param_t mqtt_params; - char *msg_buf = NULL, *msg_readbuf = NULL; - - - if (NULL == (msg_buf = (char *)HAL_Malloc(RRPC_MQTT_MSGLEN))) { - HAL_Printf("not enough memory!\n"); - rc = -1; - goto do_exit; - } - - if (NULL == (msg_readbuf = (char *)HAL_Malloc(RRPC_MQTT_MSGLEN))) { - HAL_Printf("not enough memory!\n"); - rc = -1; - goto do_exit; - } - - /**< get device info */ - HAL_GetProductKey(g_product_key); - HAL_GetDeviceName(g_device_name); - HAL_GetDeviceSecret(g_device_secret); - /**< end*/ - - /* Device AUTH */ - if (0 != IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&pconn_info)) { - HAL_Printf("AUTH request failed!\n"); - rc = -1; - goto do_exit; - } - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = msg_readbuf; - mqtt_params.read_buf_size = RRPC_MQTT_MSGLEN; - mqtt_params.pwrite_buf = msg_buf; - mqtt_params.write_buf_size = RRPC_MQTT_MSGLEN; - - mqtt_params.handle_event.h_fp = event_handle; - mqtt_params.handle_event.pcontext = NULL; - - - /* Construct a MQTT client with specify parameter */ - pclient = IOT_MQTT_Construct(&mqtt_params); - if (NULL == pclient) { - HAL_Printf("MQTT construct failed\n"); - rc = -1; - goto do_exit; - } - - /* Subscribe the specific topic */ - rc = IOT_MQTT_Subscribe(pclient, TOPIC_RRPC_REQ "+", IOTX_MQTT_QOS0, mqtt_rrpc_msg_arrive, NULL); - if (rc < 0) { - IOT_MQTT_Destroy(&pclient); - HAL_Printf("IOT_MQTT_Subscribe failed, rc = %d\n", rc); - rc = -1; - goto do_exit; - } - - HAL_SleepMs(1000); - do { - /* handle the MQTT packet received from TCP or SSL connection */ - IOT_MQTT_Yield(pclient, 200); - HAL_SleepMs(1000); - HAL_Printf("Waiting RRPC from Cloud ...\n"); - - if (running_unittest) { - HAL_Printf("Break waiting since in unittest mode\n"); - break; - } - } while (1); - - - IOT_MQTT_Unsubscribe(pclient, TOPIC_RRPC_REQ"+"); - - HAL_SleepMs(200); - - IOT_MQTT_Destroy(&pclient); - - -do_exit: - if (NULL != msg_buf) { - HAL_Free(msg_buf); - } - - if (NULL != msg_readbuf) { - HAL_Free(msg_readbuf); - } - - return rc; -} - - -void test_mqtt_rrpc_msg_arrive(void) -{ - iotx_mqtt_topic_info_t topic_info; - iotx_mqtt_event_msg_t msg; - - topic_info.packet_id = 0; - topic_info.qos = 0; - topic_info.dup = 0; - topic_info.retain = 0; - topic_info.topic_len = strlen(TEST_TOPIC); - topic_info.payload_len = strlen(TEST_PAYLOAD); - topic_info.ptopic = TEST_TOPIC_PAYLOAD; - topic_info.payload = TEST_TOPIC_PAYLOAD + strlen(TEST_TOPIC); - - msg.event_type = 0; - msg.msg = &topic_info; - mqtt_rrpc_msg_arrive(NULL, NULL, &msg); -} - -int main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp(argv[1], "unittest")) { - HAL_Printf("***********unittest start*****************\n"); - test_mqtt_rrpc_msg_arrive(); - HAL_Printf("***********unittest end*****************\n"); - running_unittest = 1; - } - /**< set device info*/ - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - /**< end*/ - mqtt_rrpc_client(); - - HAL_Printf("out of sample!\n"); - - return 0; -} diff --git a/iotkit-embedded/sample/ota/CMakeLists.txt b/iotkit-embedded/sample/ota/CMakeLists.txt deleted file mode 100644 index 634eaf8..0000000 --- a/iotkit-embedded/sample/ota/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_executable(ota_mqtt-example ota_mqtt-example.c) -target_link_libraries(ota_mqtt-example iot_sdk) diff --git a/iotkit-embedded/sample/ota/ota_coap-example.c b/iotkit-embedded/sample/ota/ota_coap-example.c deleted file mode 100644 index c0ff877..0000000 --- a/iotkit-embedded/sample/ota/ota_coap-example.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" - -//#define IOTX_PRODUCT_KEY "21ESeH6RYT7" -//#define IOTX_DEVICE_NAME "ota_demo" -//#define IOTX_DEVICE_SECRET "HTVEzMoQrNLV5CjmjKs2l16aDpmXi1Aa" -//#define IOTX_DEVICE_ID "21ESeH6RYT7.ota_demo" - -#define IOTX_PRODUCT_KEY "stMRPCR0yQu" -#define IOTX_DEVICE_NAME "xikan_ota" -#define IOTX_DEVICE_SECRET "XZjhoJclBJpvcEoa8eLYSxnb3ksRVd3W" -#define IOTX_DEVICE_ID "stMRPCR0yQu.xikan_ota" - -//#define IOTX_PRE_DTLS_SERVER_URI "coaps://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5684" -#define IOTX_PRE_NOSEC_SERVER_URI "coap://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5683" - - -//#define IOTX_PRE_NOSEC_SERVER_URI "coap://iot-as-coap.alibaba.net:5683" - -#define EXAMPLE_TRACE(fmt, ...) \ - do { \ - HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ - HAL_Printf(fmt, ##__VA_ARGS__); \ - HAL_Printf("%s", "\r\n"); \ - } while(0) - - -#define OTA_BUF_LEN (5000) - -extern int iotx_get_well_known(iotx_coap_context_t *p_context); - -static int fetch_ota(void *h_ota, void *h_coap) -{ - int rc = 1; - FILE *fp; - uint32_t last_percent = 0, percent = 0; - char version[128], md5sum[33]; - int32_t len, size_downloaded, size_file; - char buf_ota[OTA_BUF_LEN]; - int32_t firmware_valid; - - if (NULL == (fp = fopen("ota.bin", "wb+"))) { - EXAMPLE_TRACE("open file failed"); - return -1; - } - - do { - len = IOT_OTA_FetchYield(h_ota, buf_ota, OTA_BUF_LEN, 1); - if (len > 0) { - if (1 != fwrite(buf_ota, len, 1, fp)) { - EXAMPLE_TRACE("write data to file failed"); - rc = -1; - break; - } - }else { - IOT_OTA_ReportProgress(h_ota, IOT_OTAP_FETCH_FAILED, NULL); - EXAMPLE_TRACE("ota fetch fail"); - } - - /* get OTA information */ - IOT_OTA_Ioctl(h_ota, IOT_OTAG_FETCHED_SIZE, &size_downloaded, 4); - IOT_OTA_Ioctl(h_ota, IOT_OTAG_FILE_SIZE, &size_file, 4); - IOT_OTA_Ioctl(h_ota, IOT_OTAG_MD5SUM, md5sum, 33); - IOT_OTA_Ioctl(h_ota, IOT_OTAG_VERSION, version, 128); - - last_percent = percent; - percent = (size_downloaded * 100) / size_file; - if (percent - last_percent > 0) { - IOT_OTA_ReportProgress(h_ota, percent, NULL); - IOT_OTA_ReportProgress(h_ota, percent, "hello"); - } - - IOT_CoAP_Yield(h_coap); - - } while (!IOT_OTA_IsFetchFinish(h_ota)); - - while (1 == rc) { - IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4); - if (0 == firmware_valid) { - EXAMPLE_TRACE("The firmware is invalid"); - rc = -1; - break; - } else { - EXAMPLE_TRACE("The firmware is valid"); - rc = -1; - break; - } - } - - if (NULL != fp) { - fclose(fp); - } - - return rc; -} - - -//-1, fetch failed -//0, no any ota firmware -//1, fetch successfully -static int try_fetch_ota(void *h_ota, void *h_coap) -{ - if (IOT_OTA_IsFetching(h_ota)) { - return fetch_ota(h_ota, h_coap); - } - - return 0; -} - -int iotx_set_devinfo(iotx_deviceinfo_t *p_devinfo) -{ - if (NULL == p_devinfo) { - return IOTX_ERR_INVALID_PARAM; - } - - memset(p_devinfo, 0x00, sizeof(iotx_deviceinfo_t)); - /**< get device info*/ - HAL_GetProductKey(p_devinfo->product_key); - HAL_GetDeviceSecret(p_devinfo->device_secret); - HAL_GetDeviceName(p_devinfo->device_name); - HAL_GetDeviceID(p_devinfo->device_id); - /**< end*/ - - return IOTX_SUCCESS; -} - - -int main(int argc, char **argv) -{ - int rc = 0; - void *h_ota = NULL; - iotx_coap_config_t config; - iotx_deviceinfo_t deviceinfo; - iotx_coap_context_t *h_coap = NULL; - - IOT_OpenLog("coap-ota"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - - /**< set device info */ - HAL_SetProductKey(IOTX_PRODUCT_KEY); - HAL_SetDeviceName(IOTX_DEVICE_NAME); - HAL_SetDeviceSecret(IOTX_DEVICE_SECRET); - /**< end */ - iotx_set_devinfo(&deviceinfo); - - memset(&config, 0x00, sizeof(iotx_coap_config_t)); - config.p_devinfo = (iotx_deviceinfo_t *)&deviceinfo; - config.p_url = IOTX_PRE_NOSEC_SERVER_URI; - h_coap = IOT_CoAP_Init(&config); - if (NULL == h_coap) { - rc = -1; - EXAMPLE_TRACE("initialize CoAP failed"); - return -1; - } - - IOT_CoAP_DeviceNameAuth(h_coap); - - h_ota = IOT_OTA_Init(deviceinfo.product_key, deviceinfo.device_name, h_coap); - if (NULL == h_ota) { - rc = -1; - EXAMPLE_TRACE("initialize OTA failed"); - goto do_exit; - } - - int ota_code = 0; - do { - - IOT_CoAP_Yield(h_coap); - - IOT_OTA_ReportVersion(h_ota, "iotx_ver_1.0.0"); - - HAL_SleepMs(2000); - - ota_code = try_fetch_ota(h_ota, h_coap); - - } while (1 != ota_code); - - EXAMPLE_TRACE("OTA success"); - -do_exit: - if (NULL != h_ota) { - IOT_OTA_Deinit(h_ota); - } - if (NULL != h_coap) { - IOT_CoAP_Deinit(&h_coap); - } - - return rc; -} - diff --git a/iotkit-embedded/sample/subdev/CMakeLists.txt b/iotkit-embedded/sample/subdev/CMakeLists.txt deleted file mode 100644 index 15490c7..0000000 --- a/iotkit-embedded/sample/subdev/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_executable(subdev-example subdev_example_api.c subdev-example.c) -target_link_libraries(subdev-example iot_sdk) diff --git a/iotkit-embedded/sample/subdev/readme.txt b/iotkit-embedded/sample/subdev/readme.txt deleted file mode 100644 index 3f9cc25..0000000 --- a/iotkit-embedded/sample/subdev/readme.txt +++ /dev/null @@ -1,28 +0,0 @@ -本示例包括三个部分: - 示例如何使用subdev的API直接进行开发 - demo_gateway_function(msg_buf, msg_readbuf); - - 示例使用subdev_example_api.h中对topic进行封装的API进行网关开发 - demo_thing_function(msg_buf, msg_readbuf); - - 示例使用subdev_example_api.h中对topic进行封装的API进行单品设备开发 - demo_only_one_device(msg_buf, msg_readbuf); - - -目前在网关上添加子设备支持两种方式: - 静态注册:在云端控制台手动添加设备,获取设备三元组(productKey,deviceName和deviceSecret),然后提供给网关,通过接口IOT_Thing_Register/IOT_Subdevice_Register进行静态注册(IOTX_Thing_REGISTER_TYPE_STATIC); - 动态注册:无需在云端控制添加设备,直接在网关通过接口接口IOT_Thing_Register/IOT_Subdevice_Register进行动态注册(IOTX_Thing_REGISTER_TYPE_DYNAMIC). - - 动态注册具体请参考示例demo_gateway_function 中关于动态注册的范例。 - - -src/subdev中的代码实现主子设备功能,可以使用src/subdev代码直接进行网关开发,支持主子设备功能。 -example/subdev_example_api.c/.h是对事物三要素property、event和service的topic的封装,使用者可以使用这些API直接进行物的操作,而无需关心具体topic。 - - -主子设备功能需要首先定义在make.settings中定义 FEATURE_SUBDEVICE_ENABLED = y -如果该设备是单品设备,请在make.settings中定义 FEATURE_SUBDEVICE_STATUS = subdevice - - -网关设备在测试过程中出现MQTT_PUSH_TO_LIST_ERROR(-42),原因是由于内存的关系,IoT套件目前预设支持最多的topic是30,如需调整,请修改src/mqtt/mqtt_client.h 中IOTX_MC_SUB_REQUEST_NUM_MAX和IOTX_MC_SUB_NUM_MAX的定义。 - diff --git a/iotkit-embedded/sample/subdev/subdev-example.c b/iotkit-embedded/sample/subdev/subdev-example.c deleted file mode 100644 index c924f04..0000000 --- a/iotkit-embedded/sample/subdev/subdev-example.c +++ /dev/null @@ -1,1091 +0,0 @@ - -#include -#include -#include - -#include "iot_import.h" -#include "iot_export.h" -#include "subdev_example_api.h" - - -extern void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len); -extern void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len); - - -#define PRODUCT_KEY "a1BGmFnszAj" -#define DEVICE_NAME "gateway" -#define DEVICE_SECRET "Z9lPWO48TyOg90ykmxfkYK4TdJTiZrDF" - -#define SUB_1_PRODUCT_KEY "a1BGmFnszAj" -#define SUB_1_DEVICE_NAME "subdev_5" -#define SUB_1_DEVICE_SECRET "iJJcce70yMvXaeJzdRGwBzvNXBpI6cxR" - -#define SUB_2_PRODUCT_KEY "a1BGmFnszAj" -#define SUB_2_DEVICE_NAME "subdev_6" -#define SUB_2_DEVICE_SECRET "N7OyAHhVFHBp4NFfLHLz2nEBXyzrjDEC" - -#define MSG_LEN_MAX (1024 * 4) - -char g_product_key[PRODUCT_KEY_LEN + 1]; -char g_product_secret[PRODUCT_SECRET_LEN + 1]; -char g_device_name[DEVICE_NAME_LEN + 1]; -char g_device_secret[DEVICE_SECRET_LEN + 1]; - -#define TOPIC_GATEWAY_UPDATE "/"PRODUCT_KEY"/"DEVICE_NAME"/update" -#define TOPIC_SUBDEVICE1_UPDATE "/"SUB_1_PRODUCT_KEY"/"SUB_1_DEVICE_NAME"/update" -#define TOPIC_SUBDEVICE2_UPDATE "/"SUB_2_PRODUCT_KEY"/"SUB_2_DEVICE_NAME"/updae" - -static void* g_thing_t = NULL; -static void* g_gateway_t = NULL; - -static int _calc_sign(const char* product_key, - const char* device_name, - const char* device_secret, - char* hmac_sigbuf, - const int hmac_buflen, - const char* sign_method, - const char *client_id, - const char *timestamp_str) -{ - char signature[64]; - char hmac_source[256]; - - memset(signature, 0, sizeof(signature)); - memset(hmac_source, 0, sizeof(hmac_source)); - HAL_Snprintf(hmac_source, - sizeof(hmac_source), - "clientId%s" "deviceName%s" "productKey%s" "timestamp%s", - client_id, - device_name, - product_key, - timestamp_str); - - if (0 == strncmp(sign_method, "hmacsha1", strlen("hmacsha1"))) { - utils_hmac_sha1(hmac_source, strlen(hmac_source), - signature, - device_secret, - strlen(device_secret)); - } else if (0 == strncmp(sign_method, "hmacmd5", strlen("hmacmd5"))){ - utils_hmac_md5(hmac_source, strlen(hmac_source), - signature, - device_secret, - strlen(device_secret)); - } - - memcpy(hmac_sigbuf, signature, hmac_buflen); - return 0; -} - - -void rrpc_request_handler(void* gateway, - const char* product_key, - const char* device_name, - const char* message_id, - const char* payload) -{ - printf("rrpc_request_callback, product_key [%s], device_name [%s], message_id [%s], payload:%s \n", - product_key, - device_name, - message_id, - payload); - - if (IOT_Gateway_RRPC_Response(gateway, - product_key, - device_name, - message_id, - "aa00090000ff00003039001b") >= 0) { - printf("gateway rrpc repose ok success\n"); - } else { - printf("gateway rrpc repose ok fail\n"); - } -} - -void service_request_handler(void* thing_t, - const char* product_key, - const char* device_name, - iotx_thing_service_type_t service_type, - uint32_t message_id, - char* params, - uint32_t params_length, - const char* service_id) // preperty's serviceid is NULL -{ - printf("service request callback product_key[%s]\n device_name[%s]\n message_id[%d]\n" - "service_type[%d]\n service_id[%s]\n params[%s]\n\n", - product_key, device_name, message_id, service_type, service_id, params); - - switch(service_type) { - case IOTX_Thing_SERVICE_TYPE_PROPERTY_SET: - if (FAIL_RETURN == IOT_Thing_Set_Property_Response(thing_t, - product_key, - device_name, - message_id, - 200)) { - printf("service reponse fail\n"); - } else { - printf("service reponse success\n"); - } - break; - case IOTX_Thing_SERVICE_TYPE_PROPERTY_GET: - if (FAIL_RETURN == IOT_Thing_Get_Property_Response(thing_t, - product_key, - device_name, - message_id, - "Property_get", - 200)) { - printf("service reponse fail\n"); - } else { - printf("service reponse success\n"); - } - break; - case IOTX_Thing_SERVICE_TYPE_UNDEFINED: - if (FAIL_RETURN == IOT_Thing_Service_Response(thing_t, - product_key, - device_name, - service_id, - message_id, - 200)) { - printf("service reponse fail\n"); - } else { - printf("service reponse success\n"); - } - break; - - default: - printf("service_type error\n"); - break; - } -} - -void down_raw_handler(void* thing_t, - const char* product_key, - const char* device_name, - const char* raw_data, - uint32_t raw_data_length) -{ - printf("service request callback product_key[%s], device_name[%s], raw_data[%d][%s]\n", - product_key, device_name, raw_data_length, raw_data); - - if (FAIL_RETURN == IOT_Tmp_Down_Raw_Response(thing_t, - product_key, - device_name, - "down raw reply")){ - printf("down raw reply fail"); - return; - } - - if (SUCCESS_RETURN == IOT_Thing_Publish_Rawdata(thing_t, - product_key, - device_name, - "up raw data test", - strlen("up raw data test"))) { - printf("publish raw data success"); - } else { - printf("publish raw data fail"); - } -} - -void thing_control_handler(void* thing_t, - const char* product_key, - const char* device_name, - iotx_thing_control_type_t thing_control_type, - uint32_t message_id) -{ - printf("thing control callback product_key[%s], device_name[%s], thing_control_type[%d] message_id[%d]\n", - product_key, device_name, thing_control_type, message_id); - - if (SUCCESS_RETURN == IOT_Thing_Control_Response(thing_t, - product_key, - device_name, - message_id, - 200, - thing_control_type)) { - printf("thing control success"); - } else { - printf("thing control fail"); - } -} - - -// 示例如何使用subdev的API直接进行开发 -int demo_gateway_function(char *msg_buf, char *msg_readbuf) -{ - int rc, msg_len, cnt = 0;; - iotx_conn_info_pt puser_info; - iotx_mqtt_param_t mqtt_t; - iotx_gateway_param_t gateway_param; - iotx_mqtt_topic_info_t topic_msg; - char msg_pub[128] = {0}; - char sign[41] = {0}; - char timestamp[20] = {0}; - char client_id[64/*32*/] = {0}; - - /**< get device info*/ - HAL_GetProductKey(g_product_key); - HAL_GetDeviceName(g_device_name); - HAL_GetDeviceSecret(g_device_secret); - /**< end*/ - - /* Device AUTH */ - rc = IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&puser_info); - if (SUCCESS_RETURN != rc) { - printf("rc = IOT_SetupConnInfo() = %d\n", rc); - return rc; - } - - /* Construct a master-slave */ - memset(&mqtt_t, 0, sizeof(iotx_mqtt_param_t)); - memset(&gateway_param, 0, sizeof(iotx_gateway_param_t)); - - gateway_param.mqtt = &mqtt_t; - gateway_param.mqtt->port = puser_info->port; - gateway_param.mqtt->host = puser_info->host_name; - gateway_param.mqtt->client_id = puser_info->client_id; - gateway_param.mqtt->username = puser_info->username; - gateway_param.mqtt->password = puser_info->password; - gateway_param.mqtt->pub_key = puser_info->pub_key; - - gateway_param.mqtt->request_timeout_ms = 2000; - gateway_param.mqtt->clean_session = 0; - gateway_param.mqtt->keepalive_interval_ms = 60000; - gateway_param.mqtt->pread_buf = msg_readbuf; - gateway_param.mqtt->read_buf_size = MSG_LEN_MAX; - gateway_param.mqtt->pwrite_buf = msg_buf; - gateway_param.mqtt->write_buf_size = MSG_LEN_MAX; - - gateway_param.mqtt->handle_event.h_fp = NULL; - gateway_param.mqtt->handle_event.pcontext = NULL; - - printf(" ~~~~~~~~~~~~~~~~ start test ~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - /* construct */ - printf(" ~~~~~~~~~~~~~~ start construct ~~~~~~~~~~~~~ \n"); - g_gateway_t = IOT_Gateway_Construct(&gateway_param); - if (NULL == g_gateway_t) { - printf("construct Gateway failed!\n"); - return rc; - } - if (FAIL_RETURN == IOT_Gateway_RRPC_Register(g_gateway_t, - PRODUCT_KEY, - DEVICE_NAME, - rrpc_request_handler)) { - printf("rrpc register error\n"); - IOT_Gateway_Destroy(&g_gateway_t); - return FAIL_RETURN; - } - printf(" ~~~~~~~~~~~~ construct success ~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - printf(" ~~~~~~~~~~~~~~~ start login ~~~~~~~~~~~~~~~~ \n"); - - /* timestamp */ - strncpy(timestamp, "2524608000000", strlen("2524608000000") + 1); - - /* client id */ - HAL_Snprintf(client_id, /*32*/64, "%s.%s", SUB_1_PRODUCT_KEY, SUB_1_DEVICE_NAME); - - /* sign */ - if (FAIL_RETURN == _calc_sign(SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - SUB_1_DEVICE_SECRET, - sign, - 41, - "hmacsha1", - client_id, - timestamp)) { - printf("sign fail \n"); - return FAIL_RETURN; - } - - printf(" ~~~~~~~~~~~~~~ start register ~~~~~~~~~~~~~~~ \n"); - - if (FAIL_RETURN == (rc = IOT_Subdevice_Register(g_gateway_t, - IOTX_Thing_REGISTER_TYPE_STATIC, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA))) { - printf("register fail \n"); - IOT_Gateway_Destroy(&g_gateway_t); - return FAIL_RETURN; - } - - rc = IOT_Subdevice_Login(g_gateway_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA, - IOTX_SUBDEV_CLEAN_SESSION_TRUE); - - if (SUCCESS_RETURN != rc) { - printf("1 rc = IOT_Subdevice_Login() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } - if (FAIL_RETURN == IOT_Gateway_RRPC_Register(g_gateway_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - rrpc_request_handler)) { - printf("rrpc register error\n"); - return FAIL_RETURN; - } - - printf(" ~~~~~~~~~~~~~~ start register ~~~~~~~~~~~~~~~ \n"); - - - // 如果想测试动态注册,请将如下代码打开,并且将SUB_2_DEVICE_NAME重新定义一个值,例如“subdev_6” -#if 0 - printf(" ~~~~~~~~~~~~~ dynamic register ~~~~~~~~~~~~~~ \n"); - - if (FAIL_RETURN == (rc = IOT_Subdevice_Register(g_gateway_t, - IOTX_Thing_REGISTER_TYPE_DYNAMIC, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - NULL, - NULL, - NULL, - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA))) { - printf("2 register fail \n"); - IOT_Gateway_Destroy(&g_gateway_t); - return FAIL_RETURN; - } - rc = IOT_Subdevice_Login(g_gateway_t, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - NULL, - NULL, - NULL, - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA, - IOTX_SUBDEV_CLEAN_SESSION_FALSE); - - if (SUCCESS_RETURN != rc) { - printf("2 rc = IOT_Subdevice_Login() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } - - if (FAIL_RETURN == IOT_Gateway_RRPC_Register(g_gateway_t, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - rrpc_request_handler)) { - printf("rrpc register error\n"); - return FAIL_RETURN; - } -#else - memset(client_id, 0x0, 64); - /* client id */ - HAL_Snprintf(client_id, /*32*/64, "%s.%s", SUB_2_PRODUCT_KEY, SUB_2_DEVICE_NAME); - - memset(sign, 0x0, 41); - /* sign */ - if (FAIL_RETURN == _calc_sign(SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - SUB_2_DEVICE_SECRET, - sign, - 41, - "hmacsha1", - client_id, - timestamp)) { - printf("sign fail \n"); - return FAIL_RETURN; - } - - if (FAIL_RETURN == (rc = IOT_Subdevice_Register(g_gateway_t, - IOTX_Thing_REGISTER_TYPE_STATIC, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA))) { - printf("2 register fail \n"); - IOT_Gateway_Destroy(&g_gateway_t); - return FAIL_RETURN; - } - rc = IOT_Subdevice_Login(g_gateway_t, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA, - IOTX_SUBDEV_CLEAN_SESSION_FALSE); - - if (SUCCESS_RETURN != rc) { - printf("2 rc = IOT_Subdevice_Login() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } - - if (FAIL_RETURN == IOT_Gateway_RRPC_Register(g_gateway_t, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - rrpc_request_handler)) { - printf("rrpc register error\n"); - return FAIL_RETURN; - } - -#endif - printf(" ~~~~~~~~~~~~~~ login success ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - printf(" ~~~~~~~~~~~~~ start publish ~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~ gateway publish ~~~~~~~~~~~~~~ \n"); - /* Initialize topic information */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - strcpy(msg_pub, "message: hello! start!"); - - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - - rc = IOT_Gateway_Publish(g_gateway_t, TOPIC_GATEWAY_UPDATE, &topic_msg); - printf("gateway rc = IOT_Gateway_Publish() = %d\n", rc); - - do { - /* Generate topic message */ - cnt++; - printf(" ~~~~~~~~~~~ subdevice1 publish ~~~~~~~~~~~~ \n"); - msg_len = snprintf(msg_pub, sizeof(msg_pub), "subdevice1, hello"); - if (msg_len < 0) { - printf("Error occur! Exit program\n"); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return -1; - } - - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = msg_len; - - rc = IOT_Gateway_Publish(g_gateway_t, TOPIC_SUBDEVICE1_UPDATE, &topic_msg); - if (rc < 0) { - printf("error occur when publish\n"); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return -1; - } - printf("subdevice1 packet_id=%u, publish topic msg=%s\n", (uint32_t)rc, msg_pub); - - /* handle the MQTT packet received from TCP or SSL connection */ - IOT_Gateway_Yield(g_gateway_t, 200); - - printf(" ~~~~~~~~~~~ subdevice2 publish ~~~~~~~~~~~~ \n"); - memset(msg_pub, 0x0, 128); - msg_len = snprintf(msg_pub, sizeof(msg_pub), "subdevice2, hello"); - - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.payload = (void *)msg_pub; - topic_msg.payload_len = strlen(msg_pub); - rc = IOT_Gateway_Publish(g_gateway_t, TOPIC_SUBDEVICE2_UPDATE, &topic_msg); - if (rc < 0) { - printf("error occur when publish\n"); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return -1; - } - printf("subdevice2 packet_id=%u, publish topic msg=%s\n", (uint32_t)rc, msg_pub); - } while (0); - - printf(" ~~~~~~~~~~~~ publish success ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - /* handle the MQTT packet received from TCP or SSL connection */ - while (cnt < 30) { - IOT_Gateway_Yield(g_gateway_t, 200); - cnt++; - } - - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - HAL_SleepMs(200); - - printf(" ~~~~~~~~~~~~~ start logout ~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Subdevice_Logout(g_gateway_t, SUB_1_PRODUCT_KEY, SUB_1_DEVICE_NAME); - - if (SUCCESS_RETURN != rc) { - printf("1 rc = IOT_Subdevice_Logout() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } - - rc = IOT_Subdevice_Logout(g_gateway_t, SUB_2_PRODUCT_KEY, SUB_2_DEVICE_NAME); - - if (SUCCESS_RETURN != rc) { - printf("2 rc = IOT_Subdevice_Logout() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } - printf(" ~~~~~~~~~~~~~ logout success ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - // 请勿随意unregister 一个设备,如果该设备被unregister后,该设备就不能再使用,请注意 -#if 0 - rc = IOT_Subdevice_Unregister(g_gateway_t, SUB_1_PRODUCT_KEY, SUB_1_DEVICE_NAME); - if (SUCCESS_RETURN != rc) { - printf("1 rc = IOT_Subdevice_Unregister() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } - - rc = IOT_Subdevice_Unregister(g_gateway_t, SUB_2_PRODUCT_KEY, SUB_2_DEVICE_NAME); - if (SUCCESS_RETURN != rc) { - printf("2 rc = IOT_Subdevice_Unregister() = %d\n", rc); - IOT_Gateway_Destroy((void**)&g_gateway_t); - return rc; - } -#endif - - IOT_Gateway_Destroy((void**)&g_gateway_t); - printf(" ~~~~~~~~~~~~ destory success ~~~~~~~~~~~~~~ \n"); - - return SUCCESS_RETURN; -} - - -/* test for only one device */ -// 示例使用subdev_example_api.h中对topic进行封装的API进行单品设备开发 -int demo_only_one_device(char *msg_buf, char *msg_readbuf) -{ - int rc, cnt = 0; - uint32_t length = 0; - iotx_conn_info_pt puser_info; - iotx_mqtt_param_t mqtt_t; - iotx_thing_param_t thing_param; - - //具体取值请根据自行创建的产品模型进行调整,可以参考运行时日志会提示dsl具体大小,取值需比dsl大小大即可 - char sub_dsltemplate_get[1024 * 4] = {0} ; - - /**< get device info*/ - HAL_GetProductKey(g_product_key); - HAL_GetDeviceName(g_device_name); - HAL_GetDeviceSecret(g_device_secret); - /**< end*/ - - /* Device AUTH */ - rc = IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&puser_info); - if (SUCCESS_RETURN != rc) { - printf("rc = IOT_SetupConnInfo() = %d\n", rc); - return rc; - } - - /* Construct a master-slave */ - memset(&mqtt_t, 0, sizeof(iotx_mqtt_param_t)); - memset(&thing_param, 0, sizeof(iotx_thing_param_t)); - - thing_param.mqtt = &mqtt_t; - thing_param.mqtt->port = puser_info->port; - thing_param.mqtt->host = puser_info->host_name; - thing_param.mqtt->client_id = puser_info->client_id; - thing_param.mqtt->username = puser_info->username; - thing_param.mqtt->password = puser_info->password; - thing_param.mqtt->pub_key = puser_info->pub_key; - - thing_param.mqtt->request_timeout_ms = 2000; - thing_param.mqtt->clean_session = 0; - thing_param.mqtt->keepalive_interval_ms = 60000; - thing_param.mqtt->pread_buf = msg_readbuf; - thing_param.mqtt->read_buf_size = MSG_LEN_MAX; - thing_param.mqtt->pwrite_buf = msg_buf; - thing_param.mqtt->write_buf_size = MSG_LEN_MAX; - - thing_param.mqtt->handle_event.h_fp = NULL; - thing_param.mqtt->handle_event.pcontext = NULL; - - printf(" ~~~~~~~~~~~~~~~~ start test ~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - /* construct */ - printf(" ~~~~~~~~~~~~~~ start construct ~~~~~~~~~~~~~ \n"); - g_thing_t = IOT_Thing_Construct(&thing_param); - if (NULL == g_thing_t) { - printf("construct device Thing failed!\n"); - return rc; - } - if (FAIL_RETURN == IOT_Thing_RRPC_Register(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - rrpc_request_handler)) { - printf("rrpc register error\n"); - return FAIL_RETURN; - } - printf(" ~~~~~~~~~~~~ construct success ~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - printf(" ~~~~~~~~ start register callback ~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~ service register ~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Service_Register(g_thing_t, service_request_handler); - if (SUCCESS_RETURN != rc) { - printf("service register rc = IOT_Thing_Service_Register() = %d\n", rc); - goto exit; - } - - printf(" ~~~~~~~~~~~~ down raw register ~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Down_Raw_Register(g_thing_t, down_raw_handler); - if (SUCCESS_RETURN != rc) { - printf("raw register rc = IOT_Thing_Down_Raw_Register() = %d\n", rc); - goto exit; - } - - printf(" ~~~~~~~~~~ thing control register ~~~~~~~~~~ \n"); - rc = IOT_Thing_Control_Register(g_thing_t, thing_control_handler); - if (SUCCESS_RETURN != rc) { - printf("raw register rc = IOT_Thing_Down_Raw_Register() = %d\n", rc); - goto exit; - } - printf(" ~~~~~~~~ register callback success ~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - length = 1024 * 4; //具体取值请根据自行创建的产品模型进行调整,可以参考运行时日志会提示dsl具体大小,取值需比dsl大小大即可 - printf(" ~~~~~~~~~~~~ start dsl template ~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~ get ~~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Get_Dsl_Template(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - sub_dsltemplate_get, - &length); - if (SUCCESS_RETURN != rc) { - printf("dsl template get rc = IOT_Thing_Dsl_Template() = %d\n", rc); - goto exit; - } - - printf("sub_dsltemplate_get: length[%d]:[%s]\n", length, sub_dsltemplate_get); - printf(" ~~~~~~~~~~~ dsl template success ~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~ start thing property ~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~ post ~~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Post_Property(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - "{\"afabwa\":\"sfs\"}"); - printf(" ~~~~~~~~~~ thing property success ~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~ start trigger event ~~~~~~~~~~~ \n"); - rc = IOT_Thing_Trigger_Event(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - "{\"dafd\":0.90}", - "propertyIdentifier20"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~~~ start deviceinfo ~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~ update ~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Update_Deviceinfo(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - "{\"attrKey\":\"Temperature\",\"attrValue\":36.8}"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~~~~~~~~ delete ~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Delete_Deviceinfo(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - "{\"attrKey\":\"Temperature\",\"attrValue\":\"36.8\"}"); - - printf(" ~~~~~~~~~~~~ deviceinfo success ~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~ start publish rawdata ~~~~~~~~~~ \n"); - rc = IOT_Thing_Publish_Rawdata(g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - "aa00090000ff00003039001b", - strlen("aa00090000ff00003039001b")); - printf(" ~~~~~~~~~ publish rawdata success ~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - printf(" ~~~~~~~~~~~~~~~ start yield ~~~~~~~~~~~~~~~ \n"); - while(cnt < 30) { - IOT_Thing_Yield(g_thing_t, 200); - cnt++; - } - - exit: - - HAL_SleepMs(200); - - IOT_Thing_Destroy((void**)&g_thing_t); - printf(" ~~~~~~~~~~~~ destory success ~~~~~~~~~~~~~~ \n"); - - return SUCCESS_RETURN; -} - - -// 示例使用subdev_example_api.h中对topic进行封装的API进行网关开发 -int demo_thing_function(char *msg_buf, char *msg_readbuf) -{ - int rc, cnt = 0; - uint32_t length = 0; - uint32_t topo_length = 0; - iotx_conn_info_pt puser_info; - iotx_mqtt_param_t mqtt_t; - iotx_thing_param_t thing_param; - - //具体取值请根据自行创建的产品模型进行调整,可以参考运行时日志会提示dsl具体大小,取值需比dsl大小大即可 - char sub_dsltemplate_get[1024 * 4] = {0} ; - - char dsltemplate_printf[512] = {0}; - int printf_num = 0; - char sign[41] = {0}; - char timestamp[20] = {0}; - char client_id[32] = {0}; //请根据devicename和productkey调整大小 - - char get_topo_reply[512] = {0}; - - /**< get device info*/ - HAL_GetProductKey(g_product_key); - HAL_GetDeviceName(g_device_name); - HAL_GetDeviceSecret(g_device_secret); - /**< end*/ - - /* Device AUTH */ - rc = IOT_SetupConnInfo(g_product_key, g_device_name, g_device_secret, (void **)&puser_info); - if (SUCCESS_RETURN != rc) { - printf("rc = IOT_SetupConnInfo() = %d\n", rc); - return rc; - } - - /* Construct a master-slave */ - memset(&mqtt_t, 0, sizeof(iotx_mqtt_param_t)); - memset(&thing_param, 0, sizeof(iotx_thing_param_t)); - - thing_param.mqtt = &mqtt_t; - thing_param.mqtt->port = puser_info->port; - thing_param.mqtt->host = puser_info->host_name; - thing_param.mqtt->client_id = puser_info->client_id; - thing_param.mqtt->username = puser_info->username; - thing_param.mqtt->password = puser_info->password; - thing_param.mqtt->pub_key = puser_info->pub_key; - - thing_param.mqtt->request_timeout_ms = 2000; - thing_param.mqtt->clean_session = 0; - thing_param.mqtt->keepalive_interval_ms = 60000; - thing_param.mqtt->pread_buf = msg_readbuf; - thing_param.mqtt->read_buf_size = MSG_LEN_MAX; - thing_param.mqtt->pwrite_buf = msg_buf; - thing_param.mqtt->write_buf_size = MSG_LEN_MAX; - - thing_param.mqtt->handle_event.h_fp = NULL; - thing_param.mqtt->handle_event.pcontext = NULL; - - printf(" ~~~~~~~~~~~~~~~~ start test ~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - /* construct */ - printf(" ~~~~~~~~~~~~~~ start construct ~~~~~~~~~~~~~ \n"); - g_thing_t = IOT_Thing_Construct(&thing_param); - if (NULL == g_thing_t) { - printf("construct device Thing failed!\n"); - return rc; - } - - if (FAIL_RETURN == IOT_Thing_RRPC_Register(g_thing_t, //g_thing_t, - PRODUCT_KEY, - DEVICE_NAME, - rrpc_request_handler)) { - printf("rrpc register error\n"); - return FAIL_RETURN; - } - printf(" ~~~~~~~~~~~~ construct success ~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - // 静态注册子设备 - printf(" ~~~~~~~~~~~~~~ start register ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~ static ~~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~ sub1 ~~~~~~~~~~~~~~~~~~~ \n"); - - /* timestamp */ - strncpy(timestamp, "2524608000000", strlen("2524608000000") + 1); - - /* client id */ - HAL_Snprintf(client_id, 32, "%s.%s",SUB_1_PRODUCT_KEY, SUB_1_DEVICE_NAME); - - /* sign */ - if (FAIL_RETURN == _calc_sign(SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - SUB_1_DEVICE_SECRET, - sign, - 41, - "hmacsha1", - client_id, - timestamp)) { - printf("sign fail \n"); - return FAIL_RETURN; - } - rc = IOT_Thing_Register(g_thing_t, - IOTX_Thing_REGISTER_TYPE_STATIC, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_Thing_SIGN_METHOD_TYPE_SHA); - if (SUCCESS_RETURN != rc) { - printf("static rc = IOT_Thing_Register() = %d\n", rc); - IOT_Thing_Destroy((void**)&g_thing_t); - return rc; - } - - // login - printf(" ~~~~~~~~~~~~~~~ start login ~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Login(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_Thing_SIGN_METHOD_TYPE_SHA, - IOTX_Thing_CLEAN_SESSION_TYPE_TRUE); - if (SUCCESS_RETURN != rc) { - printf("login sub1 rc = IOT_Thing_Login() = %d\n", rc); - goto exit; - return rc; - } - - printf(" ~~~~~~~~~~~~~~ login success ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - if (FAIL_RETURN == (rc = IOT_Thing_RRPC_Register(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - rrpc_request_handler))) { - printf("rrpc register error\n"); - goto exit; - } - - // 动态注册子设备请查看demo_gateway_function中的示例 - printf(" ~~~~~~~~~~~~~~~~~~ sub2 ~~~~~~~~~~~~~~~~~~~ \n"); - /* client id */ - memset(client_id, 0x0, 32); - HAL_Snprintf(client_id, 32, "%s.%s", SUB_2_PRODUCT_KEY, SUB_2_DEVICE_NAME); - - /* sign */ - memset(sign, 0x0, 41); - if (FAIL_RETURN == _calc_sign(SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - SUB_2_DEVICE_SECRET, - sign, - 41, - "hmacmd5", - client_id, - timestamp)) { - printf("sign fail \n"); - return FAIL_RETURN; - } - rc = IOT_Thing_Register(g_thing_t, - IOTX_Thing_REGISTER_TYPE_STATIC, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_Thing_SIGN_METHOD_TYPE_MD5); - if (SUCCESS_RETURN != rc) { - printf("dynamic rc = IOT_Thing_Register() = %d\n", rc); - IOT_Thing_Destroy((void**)&g_thing_t); - return rc; - } - //printf("dynamic register, device_secret = %s\n", sub2_devcie_secret); - printf(" ~~~~~~~~~~~~ register success ~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~ start login ~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Login(g_thing_t, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - timestamp, - client_id, - sign, - IOTX_Thing_SIGN_METHOD_TYPE_MD5, - IOTX_Thing_CLEAN_SESSION_TYPE_FALSE); - if (SUCCESS_RETURN != rc) { - printf("login sub2 rc = IOT_Thing_Login() = %d\n", rc); - goto exit; - } - if (FAIL_RETURN == ( rc = IOT_Thing_RRPC_Register(g_thing_t, - SUB_2_PRODUCT_KEY, - SUB_2_DEVICE_NAME, - rrpc_request_handler))) { - printf("rrpc register error\n"); - goto exit; - } - printf(" ~~~~~~~~~~~~~~ login success ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - - printf(" ~~~~~~~~ start register callback ~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~ service register ~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Service_Register(g_thing_t, service_request_handler); - if (SUCCESS_RETURN != rc) { - printf("service register rc = IOT_Thing_Service_Register() = %d\n", rc); - goto exit; - } - - printf(" ~~~~~~~~~~~~ down raw register ~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Down_Raw_Register(g_thing_t, down_raw_handler); - if (SUCCESS_RETURN != rc) { - printf("raw register rc = IOT_Thing_Down_Raw_Register() = %d\n", rc); - goto exit; - } - - printf(" ~~~~~~~~~~ thing control register ~~~~~~~~~~ \n"); - rc = IOT_Thing_Control_Register(g_thing_t, thing_control_handler); - if (SUCCESS_RETURN != rc) { - printf("raw register rc = IOT_Thing_Down_Raw_Register() = %d\n", rc); - goto exit; - } - printf(" ~~~~~~~~ register callback success ~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - length = 1024 * 4; //具体取值请根据自行创建的产品模型进行调整,可以参考运行时日志会提示dsl具体大小,取值需比dsl大小大即可 - printf(" ~~~~~~~~~~~~ start dsl template ~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~ get ~~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Get_Dsl_Template(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - sub_dsltemplate_get, - &length); - - printf("sub_dsltemplate_get: length[%d]", length); - while(printf_num < length) { - memset(dsltemplate_printf, 0x0, 512); - if (length-printf_num > 500) { - strncpy(dsltemplate_printf, &sub_dsltemplate_get[printf_num], 500); - printf_num += 500; - } else if (length - printf_num <= 500){ - strncpy(dsltemplate_printf, &sub_dsltemplate_get[printf_num], length-printf_num); - printf_num = length; - } - printf("%s", dsltemplate_printf); - } - printf("\n"); - printf(" ~~~~~~~~~~~ dsl template success ~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - topo_length = 512; - if (FAIL_RETURN == ( rc = IOT_Thing_Get_TOPO(g_thing_t, get_topo_reply, &topo_length))) { - printf("IOT_Thing_Get_TOPO error\n"); - goto exit; - } - printf(" get_topo_reply length %d \n", topo_length); - printf(" get_topo_reply %s \n", get_topo_reply); - - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~ start thing property ~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~ post ~~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Post_Property(g_thing_t, - SUB_1_PRODUCT_KEY,//SUB_2_PRODUCT_KEY, - SUB_1_DEVICE_NAME,//SUB_2_DEVICE_NAME, - "{\"afabwa\":\"sfs\"}"); - printf(" ~~~~~~~~~~ thing property success ~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~ start trigger event ~~~~~~~~~~~ \n"); - rc = IOT_Thing_Trigger_Event(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - "{\"propertyIdentifier20\":\"0.90\"}", - "propertyIdentifier20"); - - printf(" ~~~~~~~~~~~ trigger event success ~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~~~ start deviceinfo ~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~ update ~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Update_Deviceinfo(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - "[{\"attrKey\":\"Temperature\",\"attrValue\":\"36.8\"}]"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~~~~~~~~ delete ~~~~~~~~~~~~~~~~~ \n"); - rc = IOT_Thing_Delete_Deviceinfo(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - "[{\"attrKey\":\"Temperature\",\"attrValue\":\"36.8\"}]"); - - printf(" ~~~~~~~~~~~~ deviceinfo success ~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - //具体参数请自行参考云端控制台提示 - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~ start publish rawdata ~~~~~~~~~~ \n"); - rc = IOT_Thing_Publish_Rawdata(g_thing_t, - SUB_1_PRODUCT_KEY, - SUB_1_DEVICE_NAME, - "aa00090000ff00003039001b", - strlen("aa00090000ff00003039001b")); - - printf(" ~~~~~~~~~ publish rawdata success ~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - printf(" ~~~~~~~~~~~~~~~ start yield ~~~~~~~~~~~~~~~ \n"); - while(cnt < 30) { - IOT_Thing_Yield(g_thing_t, 200); - cnt++; - } - - exit: - - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - IOT_Thing_Logout(g_thing_t, SUB_1_PRODUCT_KEY, SUB_1_DEVICE_NAME); - IOT_Thing_Logout(g_thing_t, SUB_2_PRODUCT_KEY, SUB_2_DEVICE_NAME); - - printf(" ~~~~~~~~~~~~~ logout success ~~~~~~~~~~~~~~ \n"); - printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n"); - - HAL_SleepMs(200); - - IOT_Thing_Destroy((void**)&g_thing_t); - printf(" ~~~~~~~~~~~~ destory success ~~~~~~~~~~~~~~ \n"); - - return SUCCESS_RETURN; -} - - -int main() -{ - char msg_buf[MSG_LEN_MAX] ={0}; - char msg_readbuf[MSG_LEN_MAX] ={0}; - - IOT_OpenLog("masterslave"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - - /**< set device info*/ - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - /**< end*/ - - // 示例如何使用subdev的API直接进行开发 - //demo_gateway_function(msg_buf, msg_readbuf); - - // 示例使用subdev_example_api.h中对topic进行封装的API进行网关开发 - demo_thing_function(msg_buf, msg_readbuf); - - // 示例使用subdev_example_api.h中对topic进行封装的API进行单品设备开发 - //demo_only_one_device(msg_buf, msg_readbuf); - - printf("out of demo!\n"); - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); - - return 0; -} - diff --git a/iotkit-embedded/sample/subdev/subdev_example_api.c b/iotkit-embedded/sample/subdev/subdev_example_api.c deleted file mode 100644 index a7ad217..0000000 --- a/iotkit-embedded/sample/subdev/subdev_example_api.c +++ /dev/null @@ -1,2177 +0,0 @@ - -#include -#include -#include - -#include "iot_import.h" -#include "lite-utils.h" -#include "subdev_example_api.h" - -iotx_thing_masterlave_pt g_thing_masterlave_t = NULL; - -#define GET_JSON_VALUE(node, param, buf) \ - do { \ - (node) = LITE_json_value_of((param), (buf)); \ - if((node) == NULL) { \ - log_err("get json value error!"); \ - return FAIL_RETURN; \ - } \ - } while(0) - - -#define GET_JSON_VALUE_WHIH_FREE(node, param, buf) \ - do { \ - LITE_free(node); \ - (node) = LITE_json_value_of((param), (buf)); \ - if((node) == NULL) { \ - log_err("get json value error!"); \ - return FAIL_RETURN; \ - } \ - } while(0) - -#define MALLOC_MEMORY_WITH_RESULT(buffer, length, result) \ - do { \ - if (buffer) \ - LITE_free(buffer); \ - (buffer) = (void*)LITE_malloc(length); \ - if (NULL == (buffer)) { \ - log_err("Not enough memory"); \ - return (result); \ - } \ - memset((buffer), 0x0, (length)); \ - } while(0) - -typedef struct iotx_thing_subscribe_topic_st { - char* format; - char* params_1; - char* params_2; - char* params_3; -}iotx_thing_subscribe_topic_t, *iotx_thing_subscribe_topic_pt; - -extern void iotx_thing_event_handle(void *pcontext, void *pclient, void* msg); - -extern iotx_device_info_pt iotx_device_info_get(void); - -char* iotx_thing_splice_common_event_packet(const char* params, - const char* event_id, - int32_t* msg_id) -{ -#define EVENT_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":%s,\"method\":\"thing.event.%s.post\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - if (params == NULL || msg_id == NULL) { - log_err("input params error!"); - return NULL; - } - - /* sum the string length */ - len = strlen(EVENT_PACKET_FMT) + strlen(params) + strlen(event_id) + 12; - - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - EVENT_PACKET_FMT, - id, - params, - event_id); - - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - -char* iotx_thing_splice_common_deviceinfo_packet(const char* deviceinfo, - const char* method, - int32_t* msg_id) -{ -#define DEVICEINFO_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":%s,\"method\":\"thing.deviceinfo.%s\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - if (deviceinfo == NULL || method == NULL || msg_id == NULL) { - log_err("input params error!"); - return NULL; - } - - /* sum the string length */ - len = strlen(EVENT_PACKET_FMT) + strlen(deviceinfo) + strlen(method) + 12; - - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - DEVICEINFO_PACKET_FMT, - id, - deviceinfo, - method); - - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - -char *iotx_thing_splice_default_reply_get_packet(int32_t msg_id, - uint32_t code, - const char* data) -{ -#define SET_DEFAULT_REPLY_GET_PACKET_FMT "{\"id\":%d,\"code\":%d,\"data\":{%s}}" - - int len, ret; - char* msg = NULL; - - PARAMETER_NULL_CHECK_WITH_RESULT(data, NULL); - - /* sum the string length */ - len = strlen(SET_DEFAULT_REPLY_GET_PACKET_FMT) + 12 + 4 + strlen(data); - - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - ret = HAL_Snprintf(msg, - len, - SET_DEFAULT_REPLY_GET_PACKET_FMT, - msg_id, - code, - data); - - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - return msg; -} - - -char *iotx_thing_splice_default_reply_packet(int32_t msg_id, uint32_t code) -{ -#define SET_DEFAULT_REPLY_PACKET_FMT "{\"id\":%d,\"code\":%d,\"data\":{}}" - - int len, ret; - char* msg = NULL; - - /* sum the string length */ - len = strlen(SET_DEFAULT_REPLY_PACKET_FMT) + 12 + 4; - - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - ret = HAL_Snprintf(msg, - len, - SET_DEFAULT_REPLY_PACKET_FMT, - msg_id, - code); - - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - return msg; -} - - -char *iotx_thing_splice_topo_add_packet(const char* product_key, - const char* device_name, - const char* sign, - const char* sign_method, - const char* timestamp, - const char* client_id, - int32_t* msg_id) -{ -#define TOPO_ADD_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":[{\"deviceName\":\"%s\",\"productKey\":\"%s\",\"sign\":\"%s\",\"signMethod\":\"%s\",\"timestamp\":\"%s\",\"clientId\":\"%s\"}],\"method\":\"thing.topo.add\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - if (device_name == NULL || product_key == NULL || sign == NULL || sign_method == NULL || timestamp == NULL || client_id == NULL || msg_id == NULL) { - log_err("input params error!"); - return NULL; - } - - /* sum the string length */ - len = strlen(TOPO_ADD_PACKET_FMT) + strlen(device_name) + strlen(product_key) + strlen(sign) - + strlen(sign_method) + strlen(timestamp) + strlen(client_id) + 12; - - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - TOPO_ADD_PACKET_FMT, - id, - device_name, - product_key, - sign, - sign_method, - timestamp, - client_id); - - if(ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - - -char* iotx_thing_splice_common_packet(const char* product_key, - const char* device_name, - int32_t* msg_id, - const char* param1, - const char* param2, - int flag) -{ -#define COMMON_PACKET_FMT_1 "{\"id\":%d,\"version\":\"1.0\",\"params\":{},\"method\":\"thing.%s.%s\"}" -#define COMMON_PACKET_FMT_2 "{\"id\":%d,\"version\":\"1.0\",\"params\":[{\"deviceName\":\"%s\",\"productKey\":\"%s\"}],\"method\":\"thing.%s.%s\"}" - - int len, ret = -1; - char* msg = NULL; - int32_t id = 0; - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param1, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param2, NULL); - PARAMETER_NULL_CHECK_WITH_RESULT(msg_id, NULL); - - /* sum the string length */ - len = strlen(COMMON_PACKET_FMT_2) + strlen(device_name) + - strlen(product_key) + 12 + strlen("unregister") + strlen("dsltemplate"); - - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - if (flag == 0) { - ret = HAL_Snprintf(msg, - len, - COMMON_PACKET_FMT_1, - id, - param1, - param2); - } else { - ret = HAL_Snprintf(msg, - len, - COMMON_PACKET_FMT_2, - id, - device_name, - product_key, - param1, - param2); - } - if(ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - -int iotx_thing_publish_common_packet(void* handle, - const char* topic_product_key, - const char* topic_device_name, - const char* packet_product_key, - const char* packet_device_name, - const char* param1, - const char* param2, - const char* param3, - iotx_thing_reply_type_t reply_type) -{ - int rc = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - int32_t msg_id = 0; - iotx_mqtt_topic_info_t topic_msg; - char* packet = NULL; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - PARAMETER_Thing_CHECK(thing_t); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic_product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic_device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(packet_product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(packet_device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param1, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param2, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param3, FAIL_RETURN); - - /* 组装topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - topic_product_key, - topic_device_name, - param1, - param2); - - memset(thing_t->thing_data_t->replys[reply_type].topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(thing_t->thing_data_t->replys[reply_type].topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - topic_product_key, - topic_device_name, - param1, - param3); - - /* 组装packet */ - if (reply_type == IOTX_Thing_REPLY_DSL_GET) { - packet = iotx_thing_splice_common_packet(packet_product_key, packet_device_name, &msg_id, param1, param2, 0); - } else { - packet = iotx_thing_splice_common_packet(packet_product_key, packet_device_name, &msg_id, param1, param2, 1); - } - - /* 组装mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)packet; - topic_msg.payload_len = strlen(packet); - topic_msg.packet_id = 0; - - /* 发送packet */ - if (SUCCESS_RETURN != (rc = iotx_thing_publish_topic_sync(thing_t, - msg_id, - topic, - &topic_msg, - reply_type))) { - LITE_free(packet); - return rc; - } - - LITE_free(packet); - - if (200 == thing_t->thing_data_t->replys[reply_type].code) { - log_info("common publish successfully [%s]", thing_t->thing_data_t->replys[reply_type].topic); - } else { - log_info("common publish error [%s]\n code[%d]", thing_t->thing_data_t->replys[reply_type].topic, thing_t->thing_data_t->replys[reply_type].code); - if (thing_t->thing_data_t->replys[reply_type].data) - LITE_free(thing_t->thing_data_t->replys[reply_type].data); - - return (~thing_t->thing_data_t->replys[reply_type].code + 1); - } - - return SUCCESS_RETURN; -} - -int iotx_thing_publish_common_event_packet(void* handle, - const char* product_key, - const char* device_name, - const char* topic_params, - const char* packet_params, - iotx_thing_reply_type_t reply_type) -{ - int rc = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - int32_t msg_id = 0; - iotx_mqtt_topic_info_t topic_msg; - char* packet = NULL; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - PARAMETER_Thing_CHECK(thing_t); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic_params, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(packet_params, FAIL_RETURN); - - /* 组装topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_FMT, - product_key, - device_name, - "event", - topic_params, - "post"); - - memset(thing_t->thing_data_t->replys[reply_type].topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(thing_t->thing_data_t->replys[reply_type].topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_FMT, - product_key, - device_name, - "event", - topic_params, - "post_reply"); - - /* 组装packet */ - packet = iotx_thing_splice_common_event_packet(packet_params, topic_params, &msg_id); - - /* 组装mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)packet; - topic_msg.payload_len = strlen(packet); - topic_msg.packet_id = 0; - - /* 发送 packet */ - if (SUCCESS_RETURN != (rc = iotx_thing_publish_topic_sync(thing_t, - msg_id, - topic, - &topic_msg, - reply_type))) { - LITE_free(packet); - return rc; - } - - LITE_free(packet); - - if (200 == thing_t->thing_data_t->replys[reply_type].code) { - log_info("common publish successfully [%s]", thing_t->thing_data_t->replys[reply_type].topic); - } else { - log_info("common publish error [%s]\n code[%d]", thing_t->thing_data_t->replys[reply_type].topic, thing_t->thing_data_t->replys[reply_type].code); - if (thing_t->thing_data_t->replys[reply_type].data) - LITE_free(thing_t->thing_data_t->replys[reply_type].data); - return(~thing_t->thing_data_t->replys[reply_type].code + 1); - } - - return SUCCESS_RETURN; -} - - -int iotx_thing_publish_common_deviceinfo_packet(void* handle, - const char* product_key, - const char* device_name, - const char* deviceinfo, - const char* param1, - const char* param2, - iotx_thing_reply_type_t reply_type) -{ - int rc = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - int32_t msg_id = 0; - iotx_mqtt_topic_info_t topic_msg; - char* packet = NULL; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - PARAMETER_Thing_CHECK(thing_t); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(deviceinfo, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param1, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(param2, FAIL_RETURN); - - /* 组装topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - product_key, - device_name, - "deviceinfo", - param1); - - memset(thing_t->thing_data_t->replys[reply_type].topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(thing_t->thing_data_t->replys[reply_type].topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - product_key, - device_name, - "deviceinfo", - param2); - - /* 组装packet */ - packet = iotx_thing_splice_common_deviceinfo_packet(deviceinfo, param1, &msg_id); - - /* 组装mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)packet; - topic_msg.payload_len = strlen(packet); - topic_msg.packet_id = 0; - - /* 发送packet */ - if (SUCCESS_RETURN != (rc = iotx_thing_publish_topic_sync(thing_t, - msg_id, - topic, - &topic_msg, - reply_type))) { - LITE_free(packet); - return rc; - } - - LITE_free(packet); - - if (200 == thing_t->thing_data_t->replys[reply_type].code) { - log_info("common publish successfully [%s]", thing_t->thing_data_t->replys[reply_type].topic); - } else { - log_info("common publish error [%s]\n code[%d]", thing_t->thing_data_t->replys[reply_type].topic, thing_t->thing_data_t->replys[reply_type].code); - if (thing_t->thing_data_t->replys[reply_type].data) - LITE_free(thing_t->thing_data_t->replys[reply_type].data); - return (~thing_t->thing_data_t->replys[reply_type].code + 1); - } - - return SUCCESS_RETURN; -} - - -int iotx_thing_publish_topic_sync(iotx_thing_masterlave_pt thing_t, - int32_t msg_id, - const char* topic, - iotx_mqtt_topic_info_pt topic_msg, - iotx_thing_reply_type_t reply) -{ - int rc = 0; - int yiled_count = 0; - - PARAMETER_Thing_CHECK(thing_t); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(topic_msg, FAIL_RETURN); - - log_info("topic: [%s] \n", topic); - - thing_t->thing_data_t->replys[reply].id = msg_id; - - if ((rc = IOT_Gateway_Publish(thing_t->gateway, topic, topic_msg)) < 0) { - log_err("Gateway Publish error!"); - return rc; - } - - while (msg_id == thing_t->thing_data_t->replys[reply].id) { - if (yiled_count > IOT_GATEWAY_YIELD_MAX_COUNT) { - log_info("yiled max count, time out"); - return FAIL_RETURN; - } - IOT_Thing_Yield(thing_t, 200); - yiled_count++; - } - - if (thing_t->thing_data_t->replys[reply].id == 0) - return SUCCESS_RETURN; - - if (thing_t->thing_data_t->replys[reply].data) - LITE_free(thing_t->thing_data_t->replys[reply].data); - - return FAIL_RETURN; -} - - -int iotx_thing_subscribe_unsubscribe_topic(iotx_thing_masterlave_pt thing_t, - const char* topic, - iotx_thing_subcribe_unsubscribe_types_t is_subscribe) -{ - int ret = 0; - int yiled_count = 0; - - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - - if (IOTX_Thing_SUBSCRIBE_TYPE == is_subscribe) { - ret = IOT_Gateway_Subscribe(thing_t->gateway, - topic, - IOTX_MQTT_QOS0, - iotx_thing_event_handle, - thing_t); - } else { - ret = IOT_Gateway_Unsubscribe(thing_t->gateway, topic); - } - thing_t->thing_data_t->sync_status = ret; - - while (ret == thing_t->thing_data_t->sync_status) { - if (yiled_count > IOT_GATEWAY_YIELD_MAX_COUNT) { - log_info("yiled max count, time out"); - return FAIL_RETURN; - } - - IOT_Thing_Yield(thing_t, 200); - yiled_count++; - } - - if (0 == thing_t->thing_data_t->sync_status) { - log_info(" %s successfully", topic); - } else { - log_info(" %s error!", topic); - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - - -int iotx_thing_subscribe_unsubscribe_basic(iotx_thing_masterlave_pt thing_t, - iotx_thing_subcribe_unsubscribe_types_t is_subscribe) -{ - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - int i = 0; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_thing_subscribe_topic_t basic_subscribe_topic[7] = { - {TOPIC_Thing_COMMON_FMT, "sub", "register_reply", ""}, - {TOPIC_Thing_COMMON_FMT, "sub", "unregister_reply", ""}, - {TOPIC_Thing_COMMON_FMT, "topo", "add_reply", ""}, - {TOPIC_Thing_COMMON_FMT, "topo", "delete_reply", ""}, - {TOPIC_Thing_COMMON_FMT, "topo", "get_reply", ""}, - {TOPIC_Thing_COMMON_FMT, "config", "get_reply", ""}, - {TOPIC_Thing_COMMON_FMT, "list", "found_reply", ""}, - }; - - PARAMETER_Thing_CHECK(thing_t); - - for (i = 0; i < 4; i++) { - memset(topic, 0X0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - basic_subscribe_topic[i].format, - pdevice_info->product_key, - pdevice_info->device_name, - basic_subscribe_topic[i].params_1, - basic_subscribe_topic[i].params_2, - basic_subscribe_topic[i].params_3); - if (SUCCESS_RETURN != iotx_thing_subscribe_unsubscribe_topic(thing_t, topic, is_subscribe)) - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - -int iotx_thing_subscribe_unsubscribe_enhance(iotx_thing_masterlave_pt thing_t, - const char* product_key, - const char* device_name, - iotx_thing_subcribe_unsubscribe_types_t is_subscribe) -{ - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - int i = 0; - iotx_thing_subscribe_topic_t enhance_subscribe_topic[6] = { - {TOPIC_Thing_COMMON_FMT, "service", "+", ""}, - {TOPIC_Thing_COMMON_EXT_FMT, "event", "+", "post_reply"}, - {TOPIC_Thing_COMMON_EXT_FMT, "event", "property", "post_reply"}, - {TOPIC_Thing_COMMON_EXT_FMT, "service", "property", "set"}, - {TOPIC_Thing_COMMON_EXT_FMT, "service", "property", "get"}, - {TOPIC_Thing_COMMON_EXT_FMT, "topo", "add", "notify"} - }; - - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - for (i = 0; i < 6; i++) { - memset(topic, 0X0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - enhance_subscribe_topic[i].format, - product_key, - device_name, - enhance_subscribe_topic[i].params_1, - enhance_subscribe_topic[i].params_2, - enhance_subscribe_topic[i].params_3); - if (SUCCESS_RETURN != iotx_thing_subscribe_unsubscribe_topic(thing_t, topic, is_subscribe)) - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - - -/* parse common_reply result */ -static int iotx_thing_common_reply_proc(iotx_thing_masterlave_pt thing_t, - const char* topic, - char* payload, - iotx_thing_reply_type_t type) -{ - char* node = NULL; - - /* check parameter */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(payload, FAIL_RETURN); - - /* parse result */ - /* there is no "id" in UP_RAW */ - if (IOTX_Thing_REPLY_UP_RAW == type) { - log_info("recv up raw reply"); - thing_t->thing_data_t->replys[type].id = 0; /* raw data */ - GET_JSON_VALUE(node, "code", payload); - thing_t->thing_data_t->replys[type].code = atoi(node); - } else { - GET_JSON_VALUE(node, "id", payload); - if (thing_t->thing_data_t->replys[type].id == atoi(node)) { - thing_t->thing_data_t->replys[type].id = 0; - } - GET_JSON_VALUE_WHIH_FREE(node, "code", payload); - thing_t->thing_data_t->replys[type].code = atoi(node); - } - - GET_JSON_VALUE_WHIH_FREE(node, "data", payload); - MALLOC_MEMORY_WITH_FREE_AND_RESULT(thing_t->thing_data_t->replys[type].data, strlen(node) + 1, node, FAIL_RETURN); - strncpy(thing_t->thing_data_t->replys[type].data, node, strlen(node)); - - LITE_free(node); - node = NULL; - - return SUCCESS_RETURN; -} - -/* parse product_key and device_name form topic */ -static int iotx_thing_parse_topic(char* topic, char* product_key, char* device_name) -{ - char* temp = NULL; - char* start = NULL; - - /* check parameter */ - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - if (0 == strncmp(topic, "/sys/", strlen("/sys/"))) { - /* productKey */ - start = topic + strlen("/sys/"); - temp = strchr(start, '/'); - if (temp == NULL || temp - start > PRODUCT_KEY_LEN) { - log_info("productKey parse error"); - return FAIL_RETURN; - } - strncpy(product_key, start, temp - start); - product_key[temp - start] = '\0'; - - /* deviceName */ - start = temp + 1; - temp = strchr(start, '/'); - if (temp == NULL || temp - start > DEVICE_NAME_LEN) { - log_info("deviceName parse error"); - return FAIL_RETURN; - } - strncpy(device_name, start, temp - start); - device_name[temp - start] = '\0'; - - return SUCCESS_RETURN; - } else { - log_info("topic error"); - return FAIL_RETURN; - } -} - -/* handle service request */ -static int iotx_thing_service_request_proc(iotx_thing_masterlave_pt thing_t, - char* topic, - char* payload) -{ - char product_key[PRODUCT_KEY_LEN] = {0}; - char device_name[DEVICE_NAME_LEN] = {0}; - iotx_thing_service_type_t service_type = IOTX_Thing_SERVICE_TYPE_PROPERTY_GET; - char* service_id = NULL, *temp = NULL, *node = NULL, *params = NULL; - int message_id = 0; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(payload, FAIL_RETURN); - - log_info("receive service request"); - - /* parse */ - if (SUCCESS_RETURN == iotx_thing_parse_topic(topic, product_key, device_name) && - (NULL != thing_t->service_callback)) { - temp = strstr(topic, "/thing/service"); - if (temp == NULL) { - log_err("parse error"); - return FAIL_RETURN; - } - - /* service type */ - temp = strstr(topic, "/thing/service/property"); - if (temp) { - temp = temp + strlen("/thing/service/property"); - if (0 == strncmp(temp, "/set", strlen("/set"))) { - service_type = IOTX_Thing_SERVICE_TYPE_PROPERTY_SET; - } else if(0 == strncmp(temp, "/get", strlen("/get"))) { - service_type = IOTX_Thing_SERVICE_TYPE_PROPERTY_GET; - }else { - log_info("service topic error [%s]", topic); - return FAIL_RETURN; - } - } else { - temp = strstr(topic, "/thing/service"); - temp = temp + strlen("/thing/service/"); - service_type = IOTX_Thing_SERVICE_TYPE_UNDEFINED; - service_id = temp; - } - - /* parse payload */ - GET_JSON_VALUE(node, "id", payload); - message_id = atoi(node); - - GET_JSON_VALUE_WHIH_FREE(node, "params", payload); - MALLOC_MEMORY_WITH_RESULT(params, strlen(node) + 1, FAIL_RETURN); - strncpy(params, node, strlen(node)); - - LITE_free(node); - node = NULL; - - thing_t->service_callback(thing_t, - product_key, - device_name, - service_type, - message_id, - params, - strlen(params), - service_id); - - LITE_free(params); - - return SUCCESS_RETURN; - } - - return FAIL_RETURN; -} - -/* handle service request */ -static int iotx_thing_topo_update_proc(iotx_thing_masterlave_pt thing_t, - char* topic, - char* payload) -{ - char product_key[PRODUCT_KEY_LEN] = {0}; - char device_name[DEVICE_NAME_LEN] = {0}; - iotx_thing_service_type_t service_type = IOTX_Thing_SERVICE_TYPE_PROPERTY_GET; - char* service_id = NULL, *temp = NULL, *node = NULL, *params = NULL; - int message_id = 0; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(payload, FAIL_RETURN); - - log_info("receive topo update"); - - /* parse */ - if (SUCCESS_RETURN == iotx_thing_parse_topic(topic, product_key, device_name) && - (NULL != thing_t->service_callback)) { // reuse service callback - temp = strstr(topic, "/thing/topo"); - if (temp == NULL) { - log_err("parse error"); - return FAIL_RETURN; - } - - /* service type */ - temp = strstr(topic, "/thing/topo/add/notify"); - if (temp) { - service_type = IOTX_Thing_SERVICE_TYPE_TOPO_UPDATE; - service_id = "add/notify"; - } else { - log_info("topo topic error [%s]", topic); - return FAIL_RETURN; - } - - /* parse payload */ - GET_JSON_VALUE(node, "id", payload); - message_id = atoi(node); - - GET_JSON_VALUE_WHIH_FREE(node, "params", payload); - MALLOC_MEMORY_WITH_RESULT(params, strlen(node) + 1, FAIL_RETURN); - strncpy(params, node, strlen(node)); - - LITE_free(node); - node = NULL; - - thing_t->service_callback(thing_t, - product_key, - device_name, - service_type, - message_id, - params, - strlen(params), - service_id); - - LITE_free(params); - - return SUCCESS_RETURN; - } - - return FAIL_RETURN; -} - - - -/* handle down_raw */ -static int iotx_thing_down_raw_proc(iotx_thing_masterlave_pt thing_t, - char* topic, - char* payload) -{ - char product_key[PRODUCT_KEY_LEN] = {0}; - char device_name[DEVICE_NAME_LEN] = {0}; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(payload, FAIL_RETURN); - - log_info("receive down raw"); - - if (SUCCESS_RETURN == iotx_thing_parse_topic(topic, product_key, device_name)) { - if (thing_t->raw_callback) { - thing_t->raw_callback(thing_t, - product_key, - device_name, - payload, - strlen(payload)); - /* pulish a down_raw_reply packet */ - return SUCCESS_RETURN; - } - } - - return FAIL_RETURN; -} - -/* handle thing control request */ -static int iotx_thing_proc(iotx_thing_masterlave_pt thing_t, - char* topic, - char* payload, - iotx_thing_control_type_t control_type) -{ - char product_key[PRODUCT_KEY_LEN] = {0}; - char device_name[DEVICE_NAME_LEN] = {0}; - int message_id = 0; - char *node = NULL; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(payload, FAIL_RETURN); - - log_info("receive thing control"); - GET_JSON_VALUE(node, "id", payload); - message_id = atoi(node); - - if (SUCCESS_RETURN == iotx_thing_parse_topic(topic, product_key, device_name)) { - if (thing_t->thing_callback) { - thing_t->thing_callback(thing_t, product_key, device_name, message_id, control_type); - return SUCCESS_RETURN; - } - } - - return FAIL_RETURN; -} - - -#ifdef SUBDEV_VIA_CLOUD_CONN -static int iotx_thing_receive_date(iotx_thing_masterlave_pt thing_t, - iotx_cloud_connection_msg_rsp_pt msg_rsp) -{ - iotx_thing_reply_type_t reply_type = IOTX_Thing_REPLY_REGISTER; - char* temp = NULL; - char* publish_topic = NULL; - char* publish_payload = NULL; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(msg_rsp, FAIL_RETURN); - - log_info("recv publish message"); - - MALLOC_MEMORY_WITH_RESULT(publish_topic, msg_rsp->URI_length, FAIL_RETURN); - MALLOC_MEMORY_WITH_FREE_AND_RESULT(publish_payload, msg_rsp->payload_length, publish_topic, FAIL_RETURN); - - strncpy(publish_topic, msg_rsp->URI, msg_rsp->URI_length); - strncpy(publish_payload, msg_rsp->payload, msg_rsp->payload_length); - - /* reply topic array */ - for (; reply_type < IOTX_Thing_REPLY_MAX; reply_type++) { - if (msg_rsp->URI_length == strlen(thing_t->thing_data_t->replys[reply_type].topic) && - (0 == strncmp(msg_rsp->URI, thing_t->thing_data_t->replys[reply_type].topic, msg_rsp->URI_length))) { - iotx_thing_common_reply_proc(thing_t, publish_topic, publish_payload, reply_type); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - } - - /* sys topic */ - if (0 == strncmp(msg_rsp->URI, "/sys/", strlen("/sys/"))) { - /* service */ - temp = strstr(msg_rsp->URI, "/thing/service/"); - if (temp != NULL) { - iotx_thing_service_request_proc(thing_t, publish_topic, publish_payload); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* raw data */ - temp = strstr(msg_rsp->URI, "/thing/model/down_raw"); - if (temp != NULL) { - iotx_thing_down_raw_proc(thing_t, publish_topic, publish_payload); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* thing control - disable */ - temp = strstr(msg_rsp->URI, "/thing/disable"); - if (temp != NULL) { - iotx_thing_proc(thing_t, publish_topic, publish_payload, IOTX_Thing_CONTROL_TYPE_DISABLE); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* thing control - delete */ - temp = strstr(msg_rsp->URI, "/thing/delete"); - if (temp != NULL) { - iotx_thing_proc(thing_t, publish_topic, publish_payload, IOTX_Thing_CONTROL_TYPE_DELETE); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* thing control - enable */ - temp = strstr(msg_rsp->URI, "/thing/enable"); - if (temp != NULL) { - iotx_thing_proc(thing_t, publish_topic, publish_payload, IOTX_Thing_CONTROL_TYPE_ENABLE); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - } - - log_info("can not find the topic!"); - - LITE_free(publish_topic); - LITE_free(publish_payload); - return FAIL_RETURN; -} - -#else - -/* publish callback */ -static int iotx_thing_recv_publish_callback(iotx_thing_masterlave_pt thing_t, - iotx_mqtt_event_msg_pt msg) -{ - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - iotx_thing_reply_type_t reply_type = IOTX_Thing_REPLY_REGISTER; - char* temp = NULL; - char* publish_topic = NULL; - char* publish_payload = NULL; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(topic_info, FAIL_RETURN); - - log_info("recv publish message"); - - MALLOC_MEMORY_WITH_RESULT(publish_topic, topic_info->topic_len + 1, FAIL_RETURN); - MALLOC_MEMORY_WITH_FREE_AND_RESULT(publish_payload, topic_info->payload_len + 1, publish_topic, FAIL_RETURN); - - strncpy(publish_topic, topic_info->ptopic, topic_info->topic_len); - strncpy(publish_payload, topic_info->payload, topic_info->payload_len); - - /* reply topic array */ - for (; reply_type < IOTX_Thing_REPLY_MAX; reply_type++) { - if (topic_info->topic_len == strlen(thing_t->thing_data_t->replys[reply_type].topic) && - (0 == strncmp(topic_info->ptopic, thing_t->thing_data_t->replys[reply_type].topic, topic_info->topic_len))) { - iotx_thing_common_reply_proc(thing_t, publish_topic, publish_payload, reply_type); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - } - - /* sys topic */ - if (0 == strncmp(topic_info->ptopic, "/sys/", strlen("/sys/"))) { - /* service */ - temp = strstr(topic_info->ptopic, "/thing/service/"); - if (temp != NULL) { - iotx_thing_service_request_proc(thing_t, publish_topic, publish_payload); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* raw data */ - temp = strstr(topic_info->ptopic, "/thing/model/down_raw"); - if (temp != NULL) { - iotx_thing_down_raw_proc(thing_t, publish_topic, publish_payload); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* thing control - disable */ - temp = strstr(topic_info->ptopic, "/thing/disable"); - if (temp != NULL) { - iotx_thing_proc(thing_t, publish_topic, publish_payload, IOTX_Thing_CONTROL_TYPE_DISABLE); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* thing control - delete */ - temp = strstr(topic_info->ptopic, "/thing/delete"); - if (temp != NULL) { - iotx_thing_proc(thing_t, publish_topic, publish_payload, IOTX_Thing_CONTROL_TYPE_DELETE); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* thing control - enable */ - temp = strstr(topic_info->ptopic, "/thing/enable"); - if (temp != NULL) { - iotx_thing_proc(thing_t, publish_topic, publish_payload, IOTX_Thing_CONTROL_TYPE_ENABLE); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - - /* topo update */ - temp = strstr(topic_info->ptopic, "/thing/topo"); - if (temp != NULL) { - iotx_thing_topo_update_proc(thing_t, publish_topic, publish_payload); - LITE_free(publish_topic); - LITE_free(publish_payload); - return SUCCESS_RETURN; - } - } - - log_info("can not find the topic!"); - - LITE_free(publish_topic); - LITE_free(publish_payload); - return FAIL_RETURN; -} -#endif - - -/* event callback */ -void iotx_thing_event_handle(void *pcontext, void *pclient, void* msg_pt) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)pcontext; -#ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_rsp_pt msg = (iotx_cloud_connection_msg_rsp_pt)msg_pt; -#else - iotx_mqtt_event_msg_pt msg = (iotx_mqtt_event_msg_pt)msg_pt; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)(msg->msg); - uintptr_t packet_id = (uintptr_t)msg->msg; -#endif - - /* parameter check */ - if (thing_t == NULL) { - log_info("param error"); - return; - } - - if (thing_t->gateway == NULL) { - log_info("param error"); - return; - } - - if (thing_t->thing_data_t == NULL) { - log_info("param error"); - return; - } - -#ifdef SUBDEV_VIA_CLOUD_CONN - log_info("event type %d", msg->rsp_type); - - switch (msg->rsp_type) - { - case IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_SUCCESS: - case IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_SUCCESS: - thing_t->thing_data_t->sync_status = 0; - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_FAIL: - case IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_FAIL: - thing_t->thing_data_t->sync_status = -1; - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SEND_SUCCESS: - case IOTX_CLOUD_CONNECTION_RESPONSE_NEW_DATA: - iotx_thing_receive_date(thing_t, msg); - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SEND_FAIL: - break; - - default: - break; - } -#else - PARAMETER_NULL_CHECK(topic_info); - - log_info("event type %d", msg->event_type); - - switch (msg->event_type) { - /* success */ - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: - if (thing_t->thing_data_t->sync_status == packet_id) { - thing_t->thing_data_t->sync_status = 0; - } - break; - - /* fail */ - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK: - if (thing_t->thing_data_t->sync_status == packet_id) { - thing_t->thing_data_t->sync_status = -1; - } - break; - - /* publish */ - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - iotx_thing_recv_publish_callback(thing_t, msg); - break; - - /* reconnect */ - case IOTX_MQTT_EVENT_RECONNECT: - /* CMP will handle the reconnect event */ - log_info("mqtt reconnect"); - break; - - default: - log_warning("unknown event"); - break; - } -#endif - return; -} - -/* constuct Thing instanct, create gateway and MQTT, subscribe gateway topic */ -void* IOT_Thing_Construct(iotx_thing_param_pt param) -{ - iotx_gateway_param_t gateway_param; - iotx_thing_masterlave_pt thing_t = NULL; - void* gateway = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - /* parameter check */ - PARAMETER_NULL_CHECK_WITH_RESULT(param, NULL); - PARAMETER_NULL_CHECK_WITH_RESULT(param->mqtt, NULL); - - if (g_thing_masterlave_t != NULL) { - log_err("thing have been construct"); - return NULL; - } - - MALLOC_MEMORY_WITH_RESULT(thing_t, sizeof(iotx_thing_masterlave_t), NULL); - MALLOC_MEMORY_WITH_FREE_AND_RESULT(thing_t->thing_data_t, sizeof(iotx_thing_masterlave_data_t), thing_t, NULL); - - memset(&gateway_param, 0x0, sizeof(iotx_gateway_param_t)); - gateway_param.mqtt = param->mqtt; - gateway_param.event_handler = iotx_thing_event_handle; /* set MQTT event callback */ - gateway_param.event_pcontext = thing_t; /* callback userdata */ - - /* create gateway */ - if (NULL == (gateway = IOT_Gateway_Construct(&gateway_param))) { - log_info("gateway construct fail"); - LITE_free(thing_t->thing_data_t); - LITE_free(thing_t); - return NULL; - } - - thing_t->gateway = gateway; - - g_thing_masterlave_t = thing_t; - - /* subscribe register and topo topic - if (FAIL_RETURN == iotx_thing_subscribe_unsubscribe_basic(thing_t, IOTX_Thing_SUBSCRIBE_TYPE)) { - if (FAIL_RETURN == IOT_Thing_Destroy((void**)&thing_t)) { - LITE_free(thing_t->thing_data_t); - LITE_free(thing_t); - } - return NULL; - } */ - - /* subscribe thing template topic */ - if (SUCCESS_RETURN != iotx_thing_subscribe_unsubscribe_enhance(thing_t, - pdevice_info->product_key, - pdevice_info->device_name, - IOTX_Thing_SUBSCRIBE_TYPE)) { - if (SUCCESS_RETURN != IOT_Thing_Destroy((void**)&thing_t)) { - LITE_free(thing_t->thing_data_t); - LITE_free(thing_t); - } - return NULL; - } - - return thing_t; -} - -/* destory Thing: MQTT disconnect, free memory */ -int IOT_Thing_Destroy(void** handle) -{ - iotx_thing_masterlave_pt thing_t = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - /* parameter chcek */ - PARAMETER_NULL_CHECK_WITH_RESULT(handle, FAIL_RETURN); - - thing_t = (iotx_thing_masterlave_pt)(*handle); - PARAMETER_Thing_CHECK(thing_t); - - /* unsubscribe register and topo topic - if (FAIL_RETURN == iotx_thing_subscribe_unsubscribe_basic(thing_t, IOTX_Thing_UNSUBSCRIBE_TYPE)) { - log_info("unsubscribe basic topic fail"); - }*/ - - /* unsubscribe thing template topic */ - if (SUCCESS_RETURN != iotx_thing_subscribe_unsubscribe_enhance(thing_t, - pdevice_info->product_key, - pdevice_info->device_name, - IOTX_Thing_UNSUBSCRIBE_TYPE)){ - log_info("unsubscribe enhance topic fail"); - } - - /* gateway destory */ - if (SUCCESS_RETURN != IOT_Gateway_Destroy((void**)&(thing_t->gateway))) { - log_info("Gateway destory fail"); - return FAIL_RETURN; - } - - LITE_free(thing_t->thing_data_t); - LITE_free(thing_t); - *handle = NULL; - g_thing_masterlave_t = NULL; - - return SUCCESS_RETURN; -} - - -/* Register: static and dynamic */ -int IOT_Thing_Register(void* handle, - iotx_thing_register_types_t type, - const char* product_key, - const char* device_name, - char* timestamp, - char* client_id, - char* sign, - iotx_thing_sign_method_types_t sign_type) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - return IOT_Subdevice_Register(thing_t->gateway, type, product_key, device_name, timestamp, client_id, sign, sign_type); -} - -/* unregister: topo delete first, then unregister */ -int IOT_Thing_Unregister(void* handle, - const char* product_key, - const char* device_name) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - return IOT_Subdevice_Unregister(thing_t->gateway, product_key, device_name); -} - - -/* login */ -int IOT_Thing_Login(void* handle, - const char* product_key, - const char* device_name, - char* timestamp, - char* client_id, - char* sign, - iotx_thing_sign_method_types_t sign_method, - iotx_thing_clean_session_types_t clean_session) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - /* subdevice login */ - if (SUCCESS_RETURN != (rc = IOT_Subdevice_Login(thing_t->gateway, - product_key, - device_name, - timestamp, - client_id, - sign, - sign_method, - clean_session))) { - log_info("subdevice login fail"); - return rc; - } - - /* subscribe thing template topic */ - if (SUCCESS_RETURN != (rc = iotx_thing_subscribe_unsubscribe_enhance(thing_t, - product_key, - device_name, - IOTX_Thing_SUBSCRIBE_TYPE))) { - IOT_Subdevice_Logout(thing_t->gateway, product_key, device_name); - log_info("subscribe topic fail"); - return rc; - } - - return SUCCESS_RETURN; -} - -/* logout */ -int IOT_Thing_Logout(void* handle, - const char* product_key, - const char* device_name) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - /* subdevice logout */ - if (SUCCESS_RETURN != (rc = IOT_Subdevice_Logout(thing_t->gateway, product_key, device_name))) { - log_info("subdevice logout fail"); - return rc; - } - - /* unsubscribe thing template topic */ - if (SUCCESS_RETURN != (rc = iotx_thing_subscribe_unsubscribe_enhance(thing_t, - product_key, - device_name, - IOTX_Thing_UNSUBSCRIBE_TYPE))) { - log_info("unsubscribe topic fail"); - return rc; - } - - return SUCCESS_RETURN; -} - - -int IOT_Thing_Get_TOPO(void* handle, - char* get_toop_reply, - uint32_t* length) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(get_toop_reply, FAIL_RETURN); - - /* get topo */ - if (SUCCESS_RETURN != (rc = IOT_Gateway_Get_TOPO(thing_t->gateway, get_toop_reply, length))) { - log_info("get topo fail"); - return rc; - } - - return SUCCESS_RETURN; -} - - -int IOT_Thing_Get_Config(void* handle, - char* get_config_reply, - uint32_t* length) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(get_config_reply, FAIL_RETURN); - - /* get config */ - if (SUCCESS_RETURN != (rc = IOT_Gateway_Get_Config(thing_t->gateway, get_config_reply, length))) { - log_info("get config fail"); - return rc; - } - - return SUCCESS_RETURN; -} - - -int IOT_Thing_Publish_Found_List(void* handle, const char* product_key, - const char* device_name) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - - /* publish new subdevice found list */ - if (SUCCESS_RETURN != (rc = IOT_Gateway_Publish_Found_List(thing_t->gateway, product_key, device_name))) { - log_info("publish new dev found list fail"); - return rc; - } - - return SUCCESS_RETURN; -} - - -/* get dsl template */ -int IOT_Thing_Get_Dsl_Template(void* handle, - const char* product_key, - const char* device_name, - char* dsl_template, - uint32_t* length) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(dsl_template, FAIL_RETURN); - - if (SUCCESS_RETURN != (rc = iotx_thing_publish_common_packet(thing_t, - product_key, - device_name, - product_key, - device_name, - "dsltemplate", - "get", - "get_reply", - IOTX_Thing_REPLY_DSL_GET))) { - log_info("publish common packet error"); - return rc; - } - - /* check length */ - if (*length < strlen(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DSL_GET].data)) { - log_info("dsltemplate length is too small"); - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DSL_GET].data); - return FAIL_RETURN; - } - - memset(dsl_template, 0x0, *length); - strncpy(dsl_template, - thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DSL_GET].data, - strlen(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DSL_GET].data)); - (*length) = strlen(dsl_template); - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DSL_GET].data); - - return SUCCESS_RETURN; -} - -/* post property */ -int IOT_Thing_Post_Property(void* handle, - const char* product_key, - const char* device_name, - const char* property) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(property, FAIL_RETURN); - - if (SUCCESS_RETURN != (rc = iotx_thing_publish_common_event_packet(thing_t, - product_key, - device_name, - "property", - property, - IOTX_Thing_REPLY_PROPERTY_POST))) { - log_info("publish common event packet error"); - return rc; - } - - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_PROPERTY_POST].data); - - return SUCCESS_RETURN; -} - -/* update device info */ -int IOT_Thing_Update_Deviceinfo(void* handle, - const char* product_key, - const char* device_name, - const char* deviceinfo) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(deviceinfo, FAIL_RETURN); - - if (SUCCESS_RETURN != (rc = iotx_thing_publish_common_deviceinfo_packet(thing_t, - product_key, - device_name, - deviceinfo, - "update", - "update_reply", - IOTX_Thing_REPLY_DEVICEINFO_UPDATE))) { - log_info("publish common packet error"); - return rc; - } - - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DEVICEINFO_UPDATE].data); - - return SUCCESS_RETURN; -} - -/* delete device info */ -int IOT_Thing_Delete_Deviceinfo(void* handle, - const char* product_key, - const char* device_name, - const char* deviceinfo) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(deviceinfo, FAIL_RETURN); - - if (SUCCESS_RETURN != (rc = iotx_thing_publish_common_deviceinfo_packet(thing_t, - product_key, - device_name, - deviceinfo, - "delete", - "delete_reply", - IOTX_Thing_REPLY_DEVICEINFO_DELETE))) { - log_info("publish common packet error"); - return rc; - } - - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_DEVICEINFO_DELETE].data); - return SUCCESS_RETURN; -} - -/* response for set property */ -int IOT_Thing_Set_Property_Response(void* handle, - const char* product_key, - const char* device_name, - uint32_t msg_id, - uint32_t code) -{ - int rc = 0; - iotx_mqtt_topic_info_t topic_msg; - char * property_packet = NULL; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - log_info("IOT_Thing_Set_Property_Response"); - - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_FMT, - product_key, - device_name, - "service", - "property", - "set_reply"); - - property_packet = iotx_thing_splice_default_reply_packet(msg_id, code); - /* mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)property_packet; - topic_msg.payload_len = strlen(property_packet); - topic_msg.packet_id = 0; - - if ((rc = IOT_Gateway_Publish(thing_t->gateway, topic, &topic_msg)) < 0) { - log_err("Gateway Publish error!"); - LITE_free(property_packet); - return rc; - } - - LITE_free(property_packet); - - return SUCCESS_RETURN; -} - -/* response for get property */ -int IOT_Thing_Get_Property_Response(void* handle, - const char* product_key, - const char* device_name, - uint32_t msg_id, - const char* property_data, - uint32_t code) -{ - int rc = 0; - iotx_mqtt_topic_info_t topic_msg; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - char * property_packet = NULL; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(property_data, FAIL_RETURN); - - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_FMT, - product_key, - device_name, - "service", - "property", - "get_reply"); - - property_packet = iotx_thing_splice_default_reply_get_packet(msg_id, code, property_data); - /* 组装mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)property_packet; - topic_msg.payload_len = strlen(property_packet); - topic_msg.packet_id = 0; - - if ((rc = IOT_Gateway_Publish(thing_t->gateway, topic, &topic_msg)) < 0) { - log_err("Gateway Publish error!"); - LITE_free(property_packet); - return rc; - } - - LITE_free(property_packet); - - return SUCCESS_RETURN; -} - -/* register callback for service */ -int IOT_Thing_Service_Register(void* handle, - service_request_callback service_callback) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(service_callback, FAIL_RETURN); - - if (thing_t->service_callback != NULL) { - log_info("service_callback have been set, can not set again"); - return FAIL_RETURN; - } - - thing_t->service_callback = service_callback; - - return SUCCESS_RETURN; -} - -/* register callback for raw data */ -int IOT_Thing_Down_Raw_Register(void* handle, down_raw_callback raw_callback) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(raw_callback, FAIL_RETURN); - - if (thing_t->raw_callback != NULL) { - log_info("raw_callback have been set, can not set again"); - return FAIL_RETURN; - } - - thing_t->raw_callback = raw_callback; - - return SUCCESS_RETURN; -} - - -/* reply a down_raw_reply to server */ -int IOT_Tmp_Down_Raw_Response(void* handle, - const char* product_key, - const char* device_name, - const char* response) -{ - int rc = 0; - iotx_mqtt_topic_info_t topic_msg; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(response, FAIL_RETURN); - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - product_key, - device_name, - "model", - "down_raw_reply"); - - /* mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)response; - topic_msg.payload_len = strlen(response); - topic_msg.packet_id = 0; - - /* publish mqtt packet */ - if (SUCCESS_RETURN != (rc = IOT_Gateway_Publish(thing_t->gateway, topic, &topic_msg))) { - log_info("Gateway publish fail"); - return rc; - } - - return SUCCESS_RETURN; -} - - -/* register callback for thing control */ -int IOT_Thing_Control_Register(void* handle, - thing_control_callback thing_callback) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_NULL_CHECK_WITH_RESULT(thing_callback, FAIL_RETURN); - - thing_t->thing_callback = thing_callback; - - return SUCCESS_RETURN; -} - -/* register callback for RRPC */ -int IOT_Thing_RRPC_Register( void* handle, - const char* product_key, - const char* device_name, - rrpc_request_callback rrpc_callback) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(rrpc_callback, FAIL_RETURN); - - return IOT_Gateway_RRPC_Register(thing_t->gateway, - product_key, - device_name, - rrpc_callback); -} - -/* response for RRPC */ -int IOT_Thing_RRPC_Response(void* handle, - const char* product_key, - const char* device_name, - const char* message_id, - const char* response) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(message_id, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(response, FAIL_RETURN); - - return IOT_Gateway_RRPC_Response(thing_t->gateway, - product_key, - device_name, - message_id, - response); -} - -/* response for service */ -int IOT_Thing_Service_Response(void* handle, - const char* product_key, - const char* device_name, - const char* service_id, - uint32_t message_id, - uint32_t code) -{ - int rc = 0; - char* response_packet = NULL; - char response_reply_topic[20] = {0}; - iotx_mqtt_topic_info_t topic_msg; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(service_id, FAIL_RETURN); - - HAL_Snprintf(response_reply_topic, 20, "%s_reply", service_id); - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - product_key, - device_name, - "service", - response_reply_topic); - - /* packet */ - response_packet = iotx_thing_splice_default_reply_packet(message_id, code); - - /* mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)response_packet; - topic_msg.payload_len = strlen(response_packet); - topic_msg.packet_id = 0; - - /* publish mqtt packet */ - if (SUCCESS_RETURN != (rc = IOT_Gateway_Publish(thing_t->gateway, topic, &topic_msg))) { - log_info("Gateway publish fail"); - LITE_free(response_packet); - return rc; - } - - LITE_free(response_packet); - - return SUCCESS_RETURN; -} - -/* response for thing control */ -int IOT_Thing_Control_Response(void* handle, - const char* product_key, - const char* device_name, - uint32_t message_id, - uint32_t code, - iotx_thing_control_type_t control_type) -{ - int rc = 0; - char* response_packet = NULL; - iotx_mqtt_topic_info_t topic_msg; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - if (control_type == IOTX_Thing_CONTROL_TYPE_ENABLE) { - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_EXT_FMT, - product_key, - device_name, - "enable_reply"); - } else if (control_type == IOTX_Thing_CONTROL_TYPE_DISABLE) { - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_EXT_FMT, - product_key, - device_name, - "disable_reply"); - } else if (control_type == IOTX_Thing_CONTROL_TYPE_DELETE) { - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_EXT_EXT_FMT, - product_key, - device_name, - "delete_reply"); - } - - /* packet */ - response_packet = iotx_thing_splice_default_reply_packet(message_id, code); - - /* mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)response_packet; - topic_msg.payload_len = strlen(response_packet); - topic_msg.packet_id = 0; - - /* publish mqtt packet */ - if (SUCCESS_RETURN != (rc = IOT_Gateway_Publish(thing_t->gateway, topic, &topic_msg))) { - log_info("Gateway publish fail"); - LITE_free(response_packet); - return FAIL_RETURN; - } - - LITE_free(response_packet); - - return SUCCESS_RETURN; -} - -/* trigger event */ -int IOT_Thing_Trigger_Event(void* handle, - const char* product_key, - const char* device_name, - const char* params, - const char* event_id) -{ - int rc = 0; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(params, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(event_id, FAIL_RETURN); - - if (SUCCESS_RETURN != (rc = iotx_thing_publish_common_event_packet(thing_t, - product_key, - device_name, - event_id, - params, - IOTX_Thing_REPLY_EVENT_POST))) { - log_info("publish common event packet error"); - return rc; - } - - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_EVENT_POST].data); - - return SUCCESS_RETURN; -} - -/* publish raw data */ -int IOT_Thing_Publish_Rawdata(void* handle, - const char* product_key, - const char* device_name, - const char* raw_data, - uint32_t raw_data_length) -{ - int32_t msg_id = -2; /* for raw data */ - iotx_mqtt_topic_info_t topic_msg; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(raw_data, FAIL_RETURN); - - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - product_key, - device_name, - "model", - "up_raw"); - memset(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_UP_RAW].topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_UP_RAW].topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_Thing_COMMON_FMT, - product_key, - device_name, - "model", - "up_raw_reply"); - - /* mqtt packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)raw_data; - topic_msg.payload_len = raw_data_length; - topic_msg.packet_id = 0; - - /* publish packet */ - if (FAIL_RETURN == iotx_thing_publish_topic_sync(thing_t, - msg_id, - topic, - &topic_msg, - IOTX_Thing_REPLY_UP_RAW)) { - return FAIL_RETURN; - } - - LITE_free(thing_t->thing_data_t->replys[IOTX_Thing_REPLY_UP_RAW].data); - - if (200 == thing_t->thing_data_t->replys[IOTX_Thing_REPLY_UP_RAW].code) { - log_info("up raw success"); - } else { - log_info("up raw replay error!code:%d", thing_t->thing_data_t->replys[IOTX_Thing_REPLY_UP_RAW].code); - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - - -int IOT_Thing_Yield(void* handle, uint32_t timeout) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - - return IOT_Gateway_Yield(thing_t->gateway, timeout); -} - -int IOT_Thing_Subscribe(void* handle, - const char *topic_filter, - int qos, - iotx_subdev_event_handle_func_fpt topic_handle_func, - void *pcontext) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - - return IOT_Gateway_Subscribe(thing_t->gateway, topic_filter, qos, topic_handle_func, pcontext); -} - -int IOT_Thing_Unsubscribe(void* handle, const char *topic_filter) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - - return IOT_Gateway_Unsubscribe(thing_t->gateway, topic_filter); -} - -int IOT_Thing_Publish(void* handle, - const char *topic_name, - iotx_mqtt_topic_info_pt topic_msg) -{ - iotx_thing_masterlave_pt thing_t = (iotx_thing_masterlave_pt)handle; - - /* parameter check */ - PARAMETER_Thing_CHECK(thing_t); - - return IOT_Gateway_Publish(thing_t->gateway, topic_name, topic_msg); -} - - diff --git a/iotkit-embedded/sample/subdev/subdev_example_api.h b/iotkit-embedded/sample/subdev/subdev_example_api.h deleted file mode 100644 index da20b2c..0000000 --- a/iotkit-embedded/sample/subdev/subdev_example_api.h +++ /dev/null @@ -1,897 +0,0 @@ - -#ifndef SRC_SUBDEVICE_Thing_UTIL_H_ -#define SRC_SUBDEVICE_Thing_UTIL_H_ - -#include "exports/iot_export_subdev.h" - -/* The fomat of thing topic */ -#define TOPIC_Thing_COMMON_FMT "/sys/%s/%s/thing/%s/%s" - -/* The fomat of thing topic */ -#define TOPIC_Thing_COMMON_EXT_FMT "/sys/%s/%s/thing/%s/%s/%s" - -/* The fomat of thing topic */ -#define TOPIC_Thing_COMMON_EXT_EXT_FMT "/sys/%s/%s/thing/%s" - - -/* Register type */ -typedef enum IOTX_Thing_REGISTER_TYPES { - /* static, via web get device_secert */ - IOTX_Thing_REGISTER_TYPE_STATIC, - /* dynamic, via register API get device_secert */ - IOTX_Thing_REGISTER_TYPE_DYNAMIC, - - IOTX_Thing_REGISTER_TYPE_MAX -}iotx_thing_register_types_t; - - -/* Sign method */ -typedef enum IOTX_Thing_SIGN_METHOD_TYPES { - /* HmacSha1 */ - IOTX_Thing_SIGN_METHOD_TYPE_SHA, - - /* HmacMd5 */ - IOTX_Thing_SIGN_METHOD_TYPE_MD5, - - /* Undefined */ - IOTX_Thing_SIGN_METHOD_TYPE_UNDEFINED, - - /* Maximum number of sign method */ - IOTX_Thing_SIGN_METHOD_TYPE_MAX -}iotx_thing_sign_method_types_t; - - -/* Login clean seesion type */ -typedef enum IOTX_Thing_CLEAN_SESSION_TYPES { - /* True */ - IOTX_Thing_CLEAN_SESSION_TYPE_TRUE, - - /* False */ - IOTX_Thing_CLEAN_SESSION_TYPE_FALSE, - - /* Undefined */ - IOTX_Thing_CLEAN_SESSION_TYPE_UNDEFINED, - - /* Maximum number of login clean seesion type */ - IOTX_Thing_CLEAN_SESSION_TYPE_MAX -}iotx_thing_clean_session_types_t; - - -/* reply type */ -typedef enum IOTX_Thing_REPLY_ENUM { - /* thing/sub/register */ - IOTX_Thing_REPLY_REGISTER, - - /* thing/sub/unregister */ - IOTX_Thing_REPLY_UNREGISTER, - - /* thing/topo/add */ - IOTX_Thing_REPLY_TOPO_ADD, - - /* thing/topo/delete */ - IOTX_Thing_REPLY_TOPO_DELETE, - - /* thing/event/property/post */ - IOTX_Thing_REPLY_PROPERTY_POST, - - /* thing/dsltemplate/get */ - IOTX_Thing_REPLY_DSL_GET, - - /* thing/deviceinfo/update*/ - IOTX_Thing_REPLY_DEVICEINFO_UPDATE, - - /* thing/deviceinfo/delete*/ - IOTX_Thing_REPLY_DEVICEINFO_DELETE, - - /* thing/keyelement/post */ - IOTX_Thing_REPLY_KEYELEMENT_POST, - - /* thing/up_raw */ - IOTX_Thing_REPLY_UP_RAW, - - /* thing/event/+/post */ - IOTX_Thing_REPLY_EVENT_POST, - - /* Maximum number of reply type */ - IOTX_Thing_REPLY_MAX -}iotx_thing_reply_type_t; - - -/* service type */ -typedef enum IOTX_Thing_SERVICE_TYPES { - /* property/set*/ - IOTX_Thing_SERVICE_TYPE_PROPERTY_SET, - - /* property/get*/ - IOTX_Thing_SERVICE_TYPE_PROPERTY_GET, - - /* Undefined service type */ - IOTX_Thing_SERVICE_TYPE_UNDEFINED, - - IOTX_Thing_SERVICE_TYPE_TOPO_UPDATE, - - /* Maximum number of service type */ - IOTX_Thing_SERVICE_TYPE_MAX -}iotx_thing_service_type_t; - - -/* thing control type */ -typedef enum IOTX_Thing_CONTROL_TYPES { - /* thing/enable*/ - IOTX_Thing_CONTROL_TYPE_ENABLE, - /* thing/disable*/ - IOTX_Thing_CONTROL_TYPE_DISABLE, - /* thing/delete*/ - IOTX_Thing_CONTROL_TYPE_DELETE, - - /* Maximum number of thind control type */ - IOTX_Thing_CONTROL_TYPE_MAX -}iotx_thing_control_type_t; - - -/** - * @brief It define a datatype of function pointer. - * This type of function will be called when a service occur. - * - * @param thing, the thing context - * @param product_key, the product key - * @param deveice_name, the deveice name - * @param service_type, the service type - * @param message_id, the service's message id - * @param params, the service's params - * @param params_length, the length of service's params - * @param service_id, the service's id, defined by dsl template * - * - * @return none - */ -typedef void (*service_request_callback)(void* thing_t, - const char* product_key, - const char* device_name, - iotx_thing_service_type_t service_type, - uint32_t message_id, - char* params, - uint32_t params_length, - const char* service_id); - - -/** - * @brief It define a datatype of function pointer. - * This type of function will be called when a raw data down occur. - * - * @param thing, the thing context - * @param product_key, the product key - * @param deveice_name, the deveice name - * @param raw_data, the raw data - * @param raw_data_length, the length of raw data - * - * @return none - */ -typedef void (*down_raw_callback)(void* thing_t, - const char* product_key, - const char* device_name, - const char* raw_data, - uint32_t raw_data_length); - - -/** - * @brief It define a datatype of function pointer. - * This type of function will be called when a thing control occur. - * - * @param thing, the thing context - * @param product_key, the product key - * @param deveice_name, the deveice name - * @param raw_data, the raw data - * @param raw_data_length, the length of raw data - * - * @return none - */ -typedef void (*thing_control_callback)(void* thing_t, - const char* product_key, - const char* device_name, - iotx_thing_control_type_t thing_control_type, - uint32_t message_id); - - - -/* The structure of thing parameter */ -typedef struct { - iotx_mqtt_param_pt mqtt; -} iotx_thing_param_t, *iotx_thing_param_pt; - - -/** - * @brief Create a Thing construction - * This function used to create a Thing construction. - * - * @param parameter. - * - * @return 0, Create success; -1, Create fail. - */ -void* IOT_Thing_Construct(iotx_thing_param_pt param); - - -/** - * @brief Destory Thing construction - * - * @param pointer of handle, specify the Thing construction. - * - * @return 0, Destory success; -1, Destory fail. - */ -int IOT_Thing_Destroy(void** handle); - - -/** - * @brief Device register - * This function used to register device. - * - * @param pointer of handle, specify the Thing construction. - * @param register type. - * IOTX_Thing_REGISTER_TYPE_STATIC - * IOTX_Thing_REGISTER_TYPE_DYNAMIC - * @param product key. - * @param device name. - * @param timestamp. [if type = dynamic, must be NULL ] - * @param client_id. [if type = dynamic, must be NULL ] - * @param sign. [if type = dynamic, must be NULL ] - * @param sign_method. - * IOTX_Thing_SIGN_METHOD_TYPE_SHA - * IOTX_Thing_SIGN_METHOD_TYPE_MD5 - * - * @return 0, Logout success; -1, Logout fail. - */ -int IOT_Thing_Register(void* handle, - iotx_thing_register_types_t type, - const char* product_key, - const char* device_name, - char* timestamp, - char* client_id, - char* sign, - iotx_thing_sign_method_types_t sign_type); - - -/** - * @brief Device unregister - * This function used to unregister device. - * The device must dynamic register again if it want to use after unregister. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * - * @return 0, Unregister success; -1, Unregister fail. - */ -int IOT_Thing_Unregister(void* handle, - const char* product_key, - const char* device_name); - - -/** - * @brief Device login - * This function used to login device. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param timestamp. [if register type = dynamic, NULL ] - * @param client_id. [if register type = dynamic, NULL ] - * @param sign. [if register type = dynamic, NULL ] - * @param sign method. [if register type = dynamic, NO mean ] - * IOTX_Thing_SIGN_METHOD_TYPE_SHA - * IOTX_Thing_SIGN_METHOD_TYPE_MD5 - * @param clean session set. - * IOTX_Thing_CLEAN_SESSION_TYPE_TRUE - * IOTX_Thing_CLEAN_SESSION_TYPE_FALSE - * - * @return 0, Login success; -1, Login fail. - */ -int IOT_Thing_Login(void* handle, - const char* product_key, - const char* device_name, - char* timestamp, - char* client_id, - char* sign, - iotx_thing_sign_method_types_t sign_method, - iotx_thing_clean_session_types_t clean_session); - - -/** - * @brief Device logout - * This function used to logout device. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * - * @return 0, Logout success; -1, Logout fail. - */ -int IOT_Thing_Logout(void* handle, - const char* product_key, - const char* device_name); - -/** - * @brief Get topo - * This function publish a packet with topo/get topic and wait for the reply (with TOPO_GET_REPLY topic). - * - * @param pointer of handle, specify the Thing construction. - * @param get_toop_reply. - * @param length [in/out]. in -- get_topo_reply buffer length, out -- reply length - * - * @return 0, logout success; -1, logout failed. - */ -int IOT_Thing_Get_TOPO(void* handle, - char* get_toop_reply, - uint32_t* length); - -/** - * @brief Get config - * This function publish a packet with config/get topic and wait for the reply (with CONFIG_GET_REPLY topic). - * - * @param pointer of handle, specify the Thing construction. - * @param get_config_reply. - * @param length [in/out]. in -- get_config_reply buffer length, out -- reply length - * - * @return 0, logout success; -1, logout failed. - */ -int IOT_Thing_Get_Config(void* handle, - char* get_config_reply, - uint32_t* length); - -/** - * @brief Publish Found List - * This function publish a packet with new subdevice found list. - * - * @return 0, publish success; -1, publish failed. - */ -int IOT_Thing_Publish_Found_List(void* handle, const char* product_key, - const char* device_name); - - -/** - * @brief Get DSL template - * This function used to get DSL template. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param DSL template buffer [output]. - * @param buffer size [output]. - * - * @return 0, Get success; -1, Get fail. - */ -int IOT_Thing_Get_Dsl_Template(void* handle, - const char* product_key, - const char* device_name, - char* dsl_template, - uint32_t* length); - - -/** - * @brief Post key element - * This function used to post key element to set specify template. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param event. - * @param property. - * @param service. - * - * @return 0, Post success; -1, Post fail. - */ -int IOT_Thing_Post_Property(void* handle, - const char* product_key, - const char* device_name, - const char* property); - - -/** - * @brief Update device information - * This function used to update device information. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param device information. - * - * @return 0, Update success; -1, Update fail. - */ -int IOT_Thing_Update_Deviceinfo(void* handle, - const char* product_key, - const char* device_name, - const char* deviceinfo); - - -/** - * @brief Delete device information - * This function used to delete device information. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param device information. - * - * @return 0, Delete success; -1, Delete fail. - */ -int IOT_Thing_Delete_Deviceinfo(void* handle, - const char* product_key, - const char* device_name, - const char* deviceinfo); - - -/** - * @brief Post key element - * This function used to post key element to set specify template. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param event. - * @param property. - * @param service. - * - * @return 0, Post success; -1, Post fail. - */ -int IOT_Thing_Post_Keyelement(void* handle, - const char* product_key, - const char* device_name, - const char* evnet, - const char* property, - const char* service); - - -/** - * @brief Response set propety request - * This function used to response set propety request. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param set propety request message id. - * @param response code. - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Thing_Set_Property_Response(void* handle, - const char* product_key, - const char* device_name, - uint32_t msg_id, - uint32_t code); - - -/** - * @brief Response get propety request - * This function used to response get propety request. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param get propety request message id. - * @param property data. - * @param response code. - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Thing_Get_Property_Response(void* handle, - const char* product_key, - const char* device_name, - uint32_t msg_id, - const char* property_data, - uint32_t code); - - -/** - * @brief Register service request callback - * This function used to register service request callback. - * - * @param pointer of handle, specify the Thing construction. - * @param callback. - * - * @return 0, Register success; -1, Register fail. - */ -int IOT_Thing_Service_Register(void* handle, - service_request_callback service_callback); - - -/** - * @brief Response service request request - * This function used to response service request request. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param service request service id. - * @param service request message id. - * @param response code. - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Thing_Service_Response(void* handle, - const char* product_key, - const char* device_name, - const char* service_id, - uint32_t message_id, - uint32_t code); - - -/** - * @brief Register thing control callback - * This function used to register thing control callback. - * - * @param pointer of handle, specify the Thing construction. - * @param callback. - * - * @return 0, Register success; -1, Register fail. - */ -int IOT_Thing_Control_Register(void* handle, - thing_control_callback thing_callback); - - -/** - * @brief Response thing control request - * This function used to response thing control request. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param thing control request message id. - * @param response code. - * @param thing control type. - * IOTX_THING_CONTROL_TYPE_ENABLE - * IOTX_THING_CONTROL_TYPE_DISABLE - * IOTX_THING_CONTROL_TYPE_DELETE - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Thing_Control_Response(void* handle, - const char* product_key, - const char* device_name, - uint32_t message_id, - uint32_t code, - iotx_thing_control_type_t control_type); - - -/** - * @brief Register down raw callback - * This function used to register down raw callback. - * - * @param pointer of handle, specify the Thing construction. - * @param callback. - * - * @return 0, Register success; -1, Register fail. - */ -int IOT_Thing_Down_Raw_Register(void* handle, - down_raw_callback raw_callback); - - -/** - * @brief Response Down Raw - * This function used to response the raw data down. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param Response data. - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Tmp_Down_Raw_Response(void* handle, - const char* product_key, - const char* device_name, - const char* response); - - -/** - * @brief Register RRPC callback - * This function used to register one RRPC callback. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param rrpc callback function. - * every device has RRPC callback by itself. - * RRPC's payload is consists by message id, method and params - * for example: - * "method":"thing.service.property.set"; - * "method":"thing.service.property.get"; - * "method":"thing.service.{dsl.service.identifer}"; - * "method":"thing.service.disable"; - * "method":"thing.service.delete"; - * "method":"thing.service.enable"; - * - * - * @return 0, Register success; -1, Register fail. - */ -int IOT_Thing_RRPC_Register( void* handle, - const char* product_key, - const char* device_name, - rrpc_request_callback rrpc_callback); - - -/** - * @brief Response RRPC request - * This function used to response the RRPC request. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param The message id of RRPC request. - * @param Response data. - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Thing_RRPC_Response(void* handle, - const char* product_key, - const char* device_name, - const char* message_id, - const char* response); - - -/** - * @brief trigger event - * This function used to trigger an event. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param event parameter. - * @param event id. - * - * @return 0, trigger success; -1, trigger fail. - */ -int IOT_Thing_Trigger_Event(void* handle, - const char* product_key, - const char* device_name, - const char* params, - const char* event_id); - - -/** - * @brief publish a raw data - * This function used to publish a raw data. - * - * @param pointer of handle, specify the Thing construction. - * @param product key. - * @param device name. - * @param raw data. - * @param raw data length. - * - * @return 0, publish success; -1, publish fail. - */ -int IOT_Thing_Publish_Rawdata(void* handle, - const char* product_key, - const char* device_name, - const char* raw_data, - uint32_t raw_data_length); - - -/** - * @brief yield - * This function used to receive data. - * - * @param pointer of handle, specify the Thing construction. - * @param timeout. - * - * @return 0, recieve success; -1, recieve fail. */ -int IOT_Thing_Yield(void* handle, uint32_t timeout); - - -/** - * @brief subscribe - * This function used to subscribe a topic. - * - * @param pointer of handle, specify the Thing construction. - * @param topic. - * @param qos. - * @param received data callback. - * @param callback user data. - * - * @return 0, subscribe success; -1, subscribe fail. - */ -int IOT_Thing_Subscribe(void* handle, - const char *topic_filter, - int qos, - iotx_subdev_event_handle_func_fpt topic_handle_func, - void *pcontext); - - -/** - * @brief unsubscribe - * This function used to unsubscribe a topic. - * - * @param pointer of handle, specify the Thing construction. - * @param topic. - * - * @return 0, unsubscribe success; -1, unsubscribe fail. - */ -int IOT_Thing_Unsubscribe(void* handle, - const char *topic_filter); - - -/** - * @brief unsubscribe - * This function used to publish a mqtt packet. - * - * @param pointer of handle, specify the Thing construction. - * @param topic. - * @param mqtt message. - * - * @return 0, publish success; -1, publish fail. - */ -int IOT_Thing_Publish(void* handle, - const char *topic_name, - iotx_mqtt_topic_info_pt topic_msg); -/* The structure of common reply data */ -typedef struct iotx_thing_common_reply_data_st{ - int32_t id; - uint32_t code; - char topic[GATEWAY_TOPIC_LEN_MAX]; - char* data; /* the data size is dynamic, so data is a ptr, dynamic malloc buffer */ -}iotx_thing_common_reply_data_t,*iotx_thing_common_reply_data_pt; - - -/* The structure of thing data */ -typedef struct iotx_thing_masterlave_data_st { - uint32_t sync_status; - iotx_thing_common_reply_data_t replys[IOTX_Thing_REPLY_MAX]; -} iotx_thing_masterlave_data_t, *iotx_thing_masterlave_data_pt; - - -/* The structure of thing context */ -typedef struct iotx_thing_masterlave_st { - void* gateway; - iotx_thing_masterlave_data_pt thing_data_t; - service_request_callback service_callback; - down_raw_callback raw_callback; - thing_control_callback thing_callback; -} iotx_thing_masterlave_t, *iotx_thing_masterlave_pt; - -extern iotx_thing_masterlave_pt g_thing_masterlave_t; - - -#define PARAMETER_Thing_CHECK(thing_t) \ - do { \ - if ((thing_t) == NULL) { \ - log_info("param error"); \ - return FAIL_RETURN; \ - } \ - if ((thing_t) != g_thing_masterlave_t) { \ - log_info("param error"); \ - return FAIL_RETURN; \ - } \ - if ((thing_t)->gateway == NULL) { \ - log_info("param error"); \ - return FAIL_RETURN; \ - } \ - if ((thing_t)->thing_data_t == NULL) { \ - log_info("param error"); \ - return FAIL_RETURN; \ - } \ - } while(0) - - -#define PARAMETER_NULL_CHECK_WITH_RESULT(param, result) \ - do { \ - if ((param) == NULL) { \ - log_info("param error"); \ - return (result); \ - } \ - } while(0) - -#define PARAMETER_STRING_NULL_CHECK_WITH_RESULT(ptr, result) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, (ptr)); \ - return (result); \ - } \ - if (0 == strlen((ptr))) { \ - log_err("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return (result); \ - } \ - } while(0) - - -#define MALLOC_MEMORY_WITH_FREE_AND_RESULT(buffer, length, free_buffer, result) \ - do { \ - if (buffer) \ - LITE_free(buffer); \ - (buffer) = (void*)LITE_malloc(length); \ - if (NULL == (buffer)) { \ - log_err("Not enough memory"); \ - LITE_free(free_buffer); \ - return (result); \ - } \ - memset((buffer), 0x0, (length)); \ - } while(0) - -#define PARAMETER_NULL_CHECK(param) \ - do { \ - if ((param) == NULL) { \ - log_info("param error"); \ - return; \ - } \ - } while(0) - -typedef enum IOTX_Thing_SUBSCRIBE_UNSUBSCRIBE_TYPES { - IOTX_Thing_SUBSCRIBE_TYPE, - IOTX_Thing_UNSUBSCRIBE_TYPE -}iotx_thing_subcribe_unsubscribe_types_t; - -char* iotx_thing_splice_common_event_packet( - const char* params, - const char* event_id, - int32_t* msg_id); - -char* iotx_thing_splice_common_deviceinfo_packet(const char* deviceinfo, - const char* method, - int32_t* msg_id); - -char *iotx_thing_splice_default_reply_get_packet(int32_t msg_id, - uint32_t code, - const char* data); - -char *iotx_thing_splice_default_reply_packet(int32_t msg_id, uint32_t code); - -char *iotx_thing_splice_topo_add_packet(const char* product_key, - const char* device_name, - const char* sign, - const char* sign_method, - const char* timestamp, - const char* client_id, - int32_t* msg_id); - - -char* iotx_thing_splice_common_packet(const char* product_key, - const char* device_name, - int32_t* msg_id, - const char* param1, - const char* param2, - int flag); - -int iotx_thing_publish_common_packet(void* handle, - const char* topic_product_key, - const char* topic_device_name, - const char* packet_product_key, - const char* packet_device_name, - const char* param1, - const char* param2, - const char* param3, - iotx_thing_reply_type_t reply_type); - -int iotx_thing_publish_common_event_packet(void* handle, - const char* product_key, - const char* device_name, - const char* topic_params, - const char* packet_params, - iotx_thing_reply_type_t reply_type); - -int iotx_thing_publish_common_deviceinfo_packet(void* handle, - const char* product_key, - const char* device_name, - const char* deviceinfo, - const char* param1, - const char* param2, - iotx_thing_reply_type_t reply_type); - -int iotx_thing_publish_topic_sync(iotx_thing_masterlave_pt thing_t, - int32_t msg_id, - const char* topic, - iotx_mqtt_topic_info_pt topic_msg, - iotx_thing_reply_type_t reply); - -int iotx_thing_subscribe_unsubscribe_topic(iotx_thing_masterlave_pt thing_t, - const char* topic, - iotx_thing_subcribe_unsubscribe_types_t is_subscribe); - -int iotx_thing_subscribe_unsubscribe_basic(iotx_thing_masterlave_pt thing_t, - iotx_thing_subcribe_unsubscribe_types_t is_subscribe); - -int iotx_thing_subscribe_unsubscribe_enhance(iotx_thing_masterlave_pt thing_t, - const char* product_key, - const char* device_name, - iotx_thing_subcribe_unsubscribe_types_t is_subscribe); - -void iotx_thing_splice_device_cloud_id(char* device_cloud_id, - const char* product_key, - const char* device_name); - -#endif /* SRC_SUBDEVICE_Thing_UTIL_H_ */ diff --git a/iotkit-embedded/src/CMakeLists.txt b/iotkit-embedded/src/CMakeLists.txt deleted file mode 100644 index 7d10593..0000000 --- a/iotkit-embedded/src/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -add_subdirectory(platform) -add_subdirectory(utils) -add_subdirectory(shadow) -add_subdirectory(coap) -add_subdirectory(packages) -add_subdirectory(http) -if(FEATURE_SUBDEVICE_ENABLED) - add_subdirectory(subdev) -endif(FEATURE_SUBDEVICE_ENABLED) -if(FEATURE_CMP_ENABLED) - if(FEATURE_SERVICE_OTA_ENABLED) - add_subdirectory(fota) - add_subdirectory(cota) - endif(FEATURE_SERVICE_OTA_ENABLED) - if(FEATURE_DM_ENABLED) - add_subdirectory(dm) - endif(FEATURE_DM_ENABLED) -endif(FEATURE_CMP_ENABLED) -#add_subdirectory(sdk-tests) - -set(iot_sdk_c_sources $ - $ - $ - $ - $ - $ - $) - -if(FEATURE_SUBDEVICE_ENABLED) - set(iot_sdk_c_sources ${iot_sdk_c_sources} $) -endif(FEATURE_SUBDEVICE_ENABLED) - -if(WIN32) - set(iot_sdk_c_sources ${iot_sdk_c_sources} $) -else(WIN32) - set(iot_sdk_c_sources ${iot_sdk_c_sources} $) -endif(WIN32) - -add_library(iot_sdk STATIC ${iot_sdk_c_sources}) -if(WIN32) - target_link_libraries(iot_sdk ws2_32) -endif(WIN32) diff --git a/iotkit-embedded/src/atm/at_api.c b/iotkit-embedded/src/atm/at_api.c new file mode 100644 index 0000000..fd8073d --- /dev/null +++ b/iotkit-embedded/src/atm/at_api.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#include "infra_config.h" + +int at_conn_init(void); +int at_parser_init(void); + +/* See detail struct definition in at_wrapper.h */ +struct at_conn_input; +struct at_mqtt_input; +int at_conn_input(struct at_conn_input *param); +int at_mqtt_input(struct at_mqtt_input *param); + +int IOT_ATM_Init(void) +{ +#ifdef AT_PARSER_ENABLED + if (at_parser_init() < 0) { + return -1; + } +#endif + +#ifdef AT_TCP_ENABLED + if (at_conn_init() < 0) { + return -1; + } +#endif + + return 0; +} + + +int IOT_ATM_Input(void * param) +{ + int ret = -1; + +#if defined(AT_TCP_ENABLED) + ret = at_conn_input((struct at_conn_input *)param); +#elif defined(AT_MQTT_ENABLED) + ret = at_mqtt_input((struct at_mqtt_input *)param); +#endif + + return ret; +} diff --git a/iotkit-embedded/src/atm/at_api.h b/iotkit-embedded/src/atm/at_api.h new file mode 100644 index 0000000..e46c57c --- /dev/null +++ b/iotkit-embedded/src/atm/at_api.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#ifndef _AT_API_H_ +#define _AT_API_H_ + +/** + * AT module initialization. + * Call this function before example starts. + * at_parser or at_tcp will be initialized if enabled. + * @param[in] none + * + * @return 0 - success, -1 - failure + */ +int IOT_ATM_Init(void); + + +/** + * Hand received data to ATM layer. + * Call this function in low-layer HAL. + * @param[in] param pointer to input struct. + * See struct at_conn_input and struct at_mqtt_input + * in at_wrapper.h + * + * @return 0 - success, -1 - failure + */ +int IOT_ATM_Input(void * param); + +#endif diff --git a/iotkit-embedded/src/atm/at_conn_mbox.c b/iotkit-embedded/src/atm/at_conn_mbox.c new file mode 100644 index 0000000..e43ee54 --- /dev/null +++ b/iotkit-embedded/src/atm/at_conn_mbox.c @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#include "infra_types.h" +#include "at_wrapper.h" + +#include "at_conn_mbox.h" + +typedef struct +{ + void *buffer; + uint32_t length; + uint32_t head; + uint32_t tail; + uint8_t full; +} at_ringbuf_t; + +#ifndef PLATFORM_HAS_DYNMEM +static at_ringbuf_t ringbufs[AT_CONN_NUM] = {{NULL, 0, 0, 0, 0}}; +#endif + +static at_ringbuf_t *alloc_ringbuf(void) +{ +#ifdef PLATFORM_HAS_DYNMEM + return HAL_Malloc(sizeof(at_ringbuf_t)); +#else + int i; + + for (i = 0; i < AT_CONN_NUM; i++) { + if (NULL == ringbufs[i].buffer) { + return &ringbufs[i]; + } + } + + return NULL; +#endif +} + +static void free_ringbuf(at_ringbuf_t *ringbuf) +{ + if (ringbuf) { +#ifdef PLATFORM_HAS_DYNMEM + HAL_Free(ringbuf); +#else + memset(ringbuf, 0, sizeof(at_ringbuf_t)); +#endif + } +} + +static int at_ringbuf_available_read_space(at_ringbuf_t *ringbuf) +{ + if (ringbuf->full) + return ringbuf->length; + + if (ringbuf->head == ringbuf->tail) { + return 0; + } else if (ringbuf->head < ringbuf->tail) { + return ringbuf->tail - ringbuf->head; + } else { + return ringbuf->length - (ringbuf->head - ringbuf->tail); + } +} + +static int at_ringbuf_full(at_ringbuf_t *ringbuf) +{ + return ringbuf->full; +} + +static int at_ringbuf_empty(at_ringbuf_t *ringbuf) +{ + return (at_ringbuf_available_read_space(ringbuf) == 0); +} + +static at_ringbuf_t *at_ringbuf_create(int length, void *buf) +{ + at_ringbuf_t *ringbuf = NULL; + + if (length < 2 || NULL == buf) { + HAL_Printf("Error: ringbuf len MUST exceed one!"); + return NULL; + } + + ringbuf = alloc_ringbuf(); + if (ringbuf == NULL) { + return NULL; + } + memset(ringbuf, 0, sizeof(at_ringbuf_t)); + + ringbuf->length = length; + ringbuf->buffer = buf; + + return ringbuf; +} + +static void at_ringbuf_clear_all(at_ringbuf_t *ringbuf) +{ + ringbuf->head = ringbuf->tail = 0; +} + +static void at_ringbuf_destroy(at_ringbuf_t *ringbuf) +{ + if (ringbuf) { + if (ringbuf->buffer) { + at_ringbuf_clear_all(ringbuf); + + ringbuf->buffer = NULL; + } + free_ringbuf(ringbuf); + } +} + +static int at_ringbuf_write(at_ringbuf_t *ringbuf, void *data, int size) +{ + uint32_t next; + + if (ringbuf == NULL || data == NULL) { + return -1; + } + + if (at_ringbuf_full(ringbuf)) { + HAL_Printf("ringbuf full!"); + return -1; + } + + memcpy(&(((void **) ringbuf->buffer)[ringbuf->tail]), data, size); + next = (ringbuf->tail + 1) % (ringbuf->length); + if (next == ringbuf->head) { + ringbuf->full = 1; + } else { + ringbuf->tail = next; + } + + return 0; +} + +static int at_ringbuf_read(at_ringbuf_t *ringbuf, void *target, + unsigned int ms, unsigned int *size) +{ + *size = 0; + + if (ringbuf == NULL || target == NULL) { + return -1; + } + + /* TODO: timeout handle */ + if (at_ringbuf_empty(ringbuf)) { + return -1; + } + + memcpy(((void **)target), &((void **)ringbuf->buffer)[ringbuf->head], sizeof(void *)); + ((void **)ringbuf->buffer)[ringbuf->head] = NULL; + *size = sizeof(void *); + ringbuf->head = (ringbuf->head + 1) % (ringbuf->length); + + if (ringbuf->full) { + ringbuf->full = 0; + ringbuf->tail = (ringbuf->tail + 1) % (ringbuf->length); + } + + return 0; +} + +/**********************public interface***********************/ +int at_mbox_new(at_mbox_t *mb, int size, void *buf) +{ + void *hdl = NULL; + + if (NULL == mb || NULL == buf) { + return -1; + } + + hdl = at_ringbuf_create(size, buf); + if (hdl == NULL) { + return -1; + } + mb->hdl = hdl; + + return 0; +} + +void at_mbox_free(at_mbox_t *mb) +{ + if ((mb != NULL)) { + at_ringbuf_destroy((at_ringbuf_t *)mb->hdl); + } +} + +void at_mbox_post(at_mbox_t *mb, void *msg) +{ + at_ringbuf_write((at_ringbuf_t *)mb->hdl, &msg, sizeof(void *)); +} + +int at_mbox_trypost(at_mbox_t *mb, void *msg) +{ + if (at_ringbuf_write((at_ringbuf_t *)mb->hdl, + &msg, sizeof(void *)) != 0) { + return -1; + } else { + return 0; + } +} + +int at_mbox_valid(at_mbox_t *mbox) +{ + if (mbox == NULL) { + return 0; + } + + if (mbox->hdl == NULL) { + return 0; + } + + return 1; +} + +uint32_t at_mbox_fetch(at_mbox_t *mb, void **msg, uint32_t timeout) +{ + uint32_t begin_ms, end_ms, elapsed_ms; + uint32_t len; + uint32_t ret; + + if (mb == NULL) { + return AT_MBOX_TIMEOUT; + } + + begin_ms = HAL_UptimeMs(); + + if (timeout != 0UL) { + if (at_ringbuf_read((at_ringbuf_t *)mb->hdl, msg, timeout, &len) == 0) { + end_ms = HAL_UptimeMs(); + elapsed_ms = end_ms - begin_ms; + ret = elapsed_ms; + } else { + ret = AT_MBOX_TIMEOUT; + } + } else { + while (at_ringbuf_read((at_ringbuf_t *)mb->hdl, msg, AT_MBOX_TIMEOUT, &len) != 0); + end_ms = HAL_UptimeMs(); + elapsed_ms = end_ms - begin_ms; + + if (elapsed_ms == 0UL) { + elapsed_ms = 1UL; + } + + ret = elapsed_ms; + } + + return ret; +} + +uint32_t at_mbox_tryfetch(at_mbox_t *mb, void **msg) +{ + uint32_t len; + + if (mb == NULL) { + return AT_MBOX_EMPTY; + } + + if (at_ringbuf_read((at_ringbuf_t *)mb->hdl, msg, 0u, &len) != 0) { + return AT_MBOX_EMPTY; + } else { + return 0; + } +} + +int at_mbox_empty(at_mbox_t *mb) +{ + if (mb == NULL) { + return -1; + } + + return at_ringbuf_empty((at_ringbuf_t *)mb->hdl); +} + +void at_mbox_set_invalid(at_mbox_t *mb) +{ + if (mb != NULL) { + mb->hdl = NULL; + } +} diff --git a/iotkit-embedded/src/atm/at_conn_mbox.h b/iotkit-embedded/src/atm/at_conn_mbox.h new file mode 100644 index 0000000..a3a05c9 --- /dev/null +++ b/iotkit-embedded/src/atm/at_conn_mbox.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#ifndef _AT_CONN_MBOX_H_ +#define _AT_CONN_MBOX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define AT_CONN_NUM 3 +#define AT_MBOX_TIMEOUT (~0) +#define AT_MBOX_EMPTY (~0) + +typedef struct +{ + void *hdl; +} at_mbox_t; + +/** + * @ingroup sys_mbox + * Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (minimum) number of messages in this mbox + * @return 0 if successful, another err_t otherwise + */ +int at_mbox_new(at_mbox_t *mbox, int size, void *buf); +/** + * @ingroup sys_mbox + * Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +void at_mbox_post(at_mbox_t *mbox, void *msg); +/** + * @ingroup sys_mbox + * Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +int at_mbox_trypost(at_mbox_t *mbox, void *msg); +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! + */ +uint32_t at_mbox_fetch(at_mbox_t *mbox, void **msg, uint32_t timeout); +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or at_MBOX_EMPTY if the mailbox is empty + */ +uint32_t at_mbox_tryfetch(at_mbox_t *mbox, void **msg); + +/** + * @ingroup sys_mbox + * Delete an mbox + * @param mbox mbox to delete + */ +void at_mbox_free(at_mbox_t *mbox); + +/** + * @ingroup sys_mbox + * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid + */ +int at_mbox_valid(at_mbox_t *mbox); + +/** + * @ingroup sys_mbox + * Set an mbox invalid so that sys_mbox_valid returns 0 + */ +void at_mbox_set_invalid(at_mbox_t *mbox); + +/** + * @ingroup sys_mbox + * Set an mbox invalid so that sys_mbox_valid returns 0 + */ +int at_mbox_empty(at_mbox_t *mb); + +#ifdef __cplusplus +} +#endif + +#endif /*_at_ARCH_H_*/ + + diff --git a/iotkit-embedded/src/atm/at_conn_mgmt.c b/iotkit-embedded/src/atm/at_conn_mgmt.c new file mode 100644 index 0000000..1511370 --- /dev/null +++ b/iotkit-embedded/src/atm/at_conn_mgmt.c @@ -0,0 +1,654 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#include +#include + +#include "infra_types.h" +#include "mqtt_api.h" +#include "at_wrapper.h" + +#include "at_conn_mbox.h" +#include "at_conn_mgmt.h" + +#define AT_DEFAULT_INPUTMBOX_SIZE 3 +#define AT_DEFAULT_PAYLOAD_SIZE (CONFIG_MQTT_MESSAGE_MAXLEN + CONFIG_MQTT_TOPIC_MAXLEN + 20) + +#define AT_DEFAULT_SEND_TIMEOUT_MS 1000 +#define AT_DEFAULT_RECV_TIMEOUT_MS 1000 + +#define DNS_MAX_NAME_LENGTH 256 +#define AT_IP4_ANY_ADDR "0.0.0.0" +#define IPV4_STR_MAX_LEN 16 + +#define AT_MAX_PAYLOAD_SIZE 1512 + +#define UNUSED_ATCONN -1 + +#ifdef AT_DEBUG_MODE +#define AT_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define AT_ERROR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#else +#define AT_DEBUG(...) +#define AT_ERROR(...) +#endif + +enum netconn_state { + NETCONN_NONE = 0, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Contains all internal pointers and states used for a socket */ +struct at_conn { + /** connnection ID */ + int connid; + /** type of the netconn (TCP) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** remote port number */ + uint16_t remote_port; + /** remote ip address */ + char remote_ip[IPV4_STR_MAX_LEN]; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + uint16_t lastoffset; + /** mbox where received packets are stored until they are fetched + by the neconn application thread. */ + at_mbox_t recvmbox; + /** pointer buffer for mbox which is used by ringbuf module. */ + void *recvbuf[AT_DEFAULT_INPUTMBOX_SIZE]; + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) in milliseconds */ + int send_timeout_ms; + /** timeout in milliseconds to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout_ms; +}; + +typedef struct at_netbuf { + void *payload; + uint16_t len; + uint16_t remote_port; + char remote_ip[IPV4_STR_MAX_LEN]; +} at_netbuf_t; + +/** The global array of available at */ +static struct at_conn atconnects[AT_CONN_NUM]; +static void *g_atconnmutex = NULL; + +#ifndef PLATFORM_HAS_DYNMEM +static at_netbuf_t atnetbuf[AT_DEFAULT_INPUTMBOX_SIZE] = + {{NULL, 0, 0, {'\0'}}}; + +typedef struct at_payload { + uint8_t buf[AT_DEFAULT_PAYLOAD_SIZE]; + uint8_t used; +} at_payload_t; + +static at_payload_t atpayload[AT_DEFAULT_INPUTMBOX_SIZE] = + {{{0}, 0}}; +#endif + +static void *alloc_payload(int size) +{ +#ifdef PLATFORM_HAS_DYNMEM + return HAL_Malloc(size); +#else + int i; + + if (size <= 0 || size > AT_DEFAULT_PAYLOAD_SIZE) { + return NULL; + } + + for (i = 0; i < AT_DEFAULT_INPUTMBOX_SIZE; i++) { + if (0 == atpayload[i].used) { + atpayload[i].used = 1; + return atpayload[i].buf; + } + } + + return NULL; +#endif +} + +static void free_payload(void *payload) +{ + if (payload) { +#ifdef PLATFORM_HAS_DYNMEM + HAL_Free(payload); +#else + memset(payload, 0, sizeof(at_payload_t)); +#endif + } +} + +static at_netbuf_t *alloc_atnetbuf(void) +{ +#ifdef PLATFORM_HAS_DYNMEM + return HAL_Malloc(sizeof(at_netbuf_t)); +#else + int i; + + for (i = 0; i < AT_DEFAULT_INPUTMBOX_SIZE; i++) { + if (NULL == atnetbuf[i].payload) { + return &atnetbuf[i]; + } + } + + return NULL; +#endif +} + +static void free_atnetbuf(at_netbuf_t *netbuf) +{ + if (netbuf) { +#ifdef PLATFORM_HAS_DYNMEM + HAL_Free(netbuf); +#else + memset(netbuf, 0, sizeof(at_netbuf_t)); +#endif + } +} + +static struct at_conn *get_conn(int c) +{ + struct at_conn *conn = NULL; + + if ((c < 0) || (c >= AT_CONN_NUM)) { + AT_DEBUG("get_conn(%d): invalid", c); + return NULL; + } + + conn = &atconnects[c]; + + if (UNUSED_ATCONN == conn->connid) { + AT_DEBUG("get_conn(%d): not active", c); + return NULL; + } + + return conn; +} + +static int at_newconn(void) +{ + int i; + + for (i = 0; i < AT_CONN_NUM; i++) { + if (atconnects[i].connid == UNUSED_ATCONN) { + if (at_mbox_new(&atconnects[i].recvmbox, + AT_DEFAULT_INPUTMBOX_SIZE, + atconnects[i].recvbuf) != 0) { + AT_ERROR("fai to new input mail box size %d \n", AT_DEFAULT_INPUTMBOX_SIZE); + return -1; + } + + atconnects[i].type = NETCONN_INVALID; + atconnects[i].state = NETCONN_NONE; + atconnects[i].lastdata = NULL; + atconnects[i].lastoffset = 0; + atconnects[i].connid = i; + atconnects[i].send_timeout_ms = AT_DEFAULT_SEND_TIMEOUT_MS; + atconnects[i].recv_timeout_ms = AT_DEFAULT_RECV_TIMEOUT_MS; + return i; + } + } + + return -1; +} + +static void at_drainconn(struct at_conn *conn) +{ + at_netbuf_t *mem; + + if (NULL == conn) + return; + + if (at_mbox_valid(&conn->recvmbox)) { + while (at_mbox_tryfetch(&conn->recvmbox, (void **)(&mem)) != AT_MBOX_EMPTY) { + if (mem != NULL) { + if (mem->payload) { + free_payload(mem->payload); + mem->payload = NULL; + } + free_atnetbuf(mem); + } + } + at_mbox_free(&conn->recvmbox); + at_mbox_set_invalid(&conn->recvmbox); + } + + return; +} + +static int at_freeconn(struct at_conn *conn) +{ + at_netbuf_t *buf = NULL; + + if (NULL == conn) + return -1; + + if (NULL != conn->lastdata) { + buf = (at_netbuf_t *) conn->lastdata; + + if (buf->payload) { + free_payload(buf->payload); + buf->payload = NULL; + } + + free_atnetbuf(buf); + } + + conn->lastdata = NULL; + conn->lastoffset = 0; + + at_drainconn(conn); + + conn->type = NETCONN_INVALID; + conn->state = NETCONN_NONE; + conn->connid = UNUSED_ATCONN; + + return 0; +} + +static int at_conn_fetch(struct at_conn *conn, at_netbuf_t **new_buf) +{ + uint32_t ret = 0; + void *buf = NULL; + + if (NULL == conn || NULL == new_buf) { + return -1; + } + + if (!at_mbox_valid(&conn->recvmbox)) { + AT_ERROR("conn %d invalid recvmbox\n", conn->connid); + return -1; + } + + ret = at_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout_ms); + if (ret == AT_MBOX_TIMEOUT) { + AT_ERROR("at conn %d fetch data time out %d\n", conn->connid, conn->recv_timeout_ms); + return -1; + } + + *new_buf = buf; + return 0; +} + +/****************************public interface*********************/ +int at_conn_input(struct at_conn_input *param) +{ + int s = -1; + void *data = NULL; + int len = 0; + char *remote_ip = NULL; + uint16_t remote_port = 0; + struct at_conn *conn = NULL; + at_netbuf_t *buf = NULL; + + if (NULL == param) { + AT_ERROR("at conn input param NULL\n"); + return -1; + } + + s = param->fd; + data = param->data; + len = param->datalen; + remote_ip = param->remote_ip; + remote_port = param->remote_port; + + if (NULL == data || 0 == len) { + AT_ERROR("low level invalid input data\n"); + return -1; + } + + if (remote_ip != NULL && + strlen(remote_ip) > IPV4_STR_MAX_LEN) { + AT_ERROR("invalid ip string"); + return -1; + } + + conn = get_conn(s); + if (NULL == conn) { + AT_ERROR("conn %d doesn't exist\n", s); + return -1; + } + + if (conn->connid < 0) { + AT_ERROR("conn %d invalid connid\n", s); + return -1; + } + + if (!at_mbox_valid(&conn->recvmbox)) { + AT_ERROR("invalid conn to input packet\n"); + return -1; + } + + buf = alloc_atnetbuf(); + if (NULL == buf) { + AT_ERROR("alloc at net buf size %d fail\n", sizeof(at_netbuf_t)); + return -1; + } + memset(buf, 0, sizeof(*buf)); + + buf->payload = alloc_payload(len); + if (NULL == buf->payload) { + free_atnetbuf(buf); + AT_ERROR("alloc payload size %d fail\n", len); + return -1; + } + + memcpy(buf->payload, data, len); + buf->len = len; + buf->remote_port = remote_port; + if (remote_ip) + memcpy(buf->remote_ip, remote_ip, IPV4_STR_MAX_LEN); + + if (at_mbox_trypost(&conn->recvmbox, buf) != 0) { + free_payload(buf->payload); + buf->payload = NULL; + free_atnetbuf(buf); + AT_ERROR("try post recv packet fail\n"); + return -1; + } + + return 0; + } + +int at_conn_init(void) +{ + static int at_conn_init_done = 0; + int i; + + if (at_conn_init_done) { + AT_ERROR("at conn have already init done\n"); + return 0; + } + + for (i = 0; i < AT_CONN_NUM; i++) { + atconnects[i].connid = UNUSED_ATCONN; + } + + g_atconnmutex = HAL_MutexCreate(); + if (g_atconnmutex == NULL) { + AT_ERROR("failed to creat g_atconnmutex \n"); + return -1; + } + + if (HAL_AT_CONN_Init() != 0) { + AT_ERROR("at conn low level init fail\n"); + HAL_MutexDestroy(g_atconnmutex); + return -1; + } + + at_conn_init_done = 1; + + return 0 ; +} + +int at_conn_getaddrinfo(const char *nodename, char resultip[16]) +{ + int namelen; + + if (NULL == nodename || NULL == resultip) { + return -1; + } + + namelen = strlen(nodename); + if (namelen > DNS_MAX_NAME_LENGTH) + return -1; + + if (HAL_AT_CONN_DomainToIp((char *)nodename, resultip) != 0) { + AT_ERROR("domain to ip failed."); + return -1; + } + + return 0; +} + +int at_conn_setup(netconn_type_t type) +{ + struct at_conn *conn = NULL; + int connid = -1; + + if (type >= NETCONN_TYPE_NUM || type <= NETCONN_INVALID) { + return -1; + } + + HAL_MutexLock(g_atconnmutex); + if ((connid = at_newconn()) == -1) { + AT_ERROR("fai to new at conn\n"); + HAL_MutexUnlock(g_atconnmutex); + return -1; + } + + if ((conn = get_conn(connid)) == NULL) { + AT_ERROR("fai to get at conn\n"); + HAL_MutexUnlock(g_atconnmutex); + return -1; + } + + conn->type = type; + conn->state = NETCONN_NONE; + HAL_MutexUnlock(g_atconnmutex); + + return connid; +} + +int at_conn_start(int connid, char* remoteipaddr, uint16_t remoteport) +{ + char *ipv4anyadrr = AT_IP4_ANY_ADDR; + at_conn_t statconn = {0}; + struct at_conn *conn = NULL; + + HAL_MutexLock(g_atconnmutex); + conn = get_conn(connid); + if (NULL == conn) { + AT_ERROR("at_startconn: invalid conn\n"); + HAL_MutexUnlock(g_atconnmutex); + return -1; + } + + if (conn->state != NETCONN_NONE) { + AT_ERROR("at_startconn: conn %d state is %d \n", connid, conn->state); + HAL_MutexUnlock(g_atconnmutex); + return -1; + } + + statconn.fd = connid; + statconn.r_port = remoteport; + statconn.l_port = -1; + statconn.addr = (char *)remoteipaddr; + if (NULL == statconn.addr) { + statconn.addr = ipv4anyadrr; + } + + switch (conn->type) { + case NETCONN_TCP: + statconn.type = TCP_CLIENT; + if (HAL_AT_CONN_Start(&statconn) != 0) { + AT_ERROR("fail to setup tcp connect, remote is %s port is %d.\n", statconn.addr, remoteport); + HAL_MutexUnlock(g_atconnmutex); + return -1; + } + memcpy(conn->remote_ip, statconn.addr, IPV4_STR_MAX_LEN); + conn->remote_port = remoteport; + break; + default: + AT_ERROR("Unsupported at connection type.\n"); + HAL_MutexUnlock(g_atconnmutex); + return -1; + } + + /* Update at conn state */ + conn->state = NETCONN_CONNECT; + HAL_MutexUnlock(g_atconnmutex); + + return 0; +} + +int at_conn_close(int c) +{ + struct at_conn *conn = NULL; + int err; + + AT_DEBUG("at_close(%d)\r\n", c); + + conn = get_conn(c); + if (NULL == conn) { + return -1; + } + + if (conn->state == NETCONN_CONNECT) { + if (HAL_AT_CONN_Close(c, -1) != 0) { + AT_DEBUG("HAL_AT_close failed."); + } + } + + HAL_MutexLock(g_atconnmutex); + err = at_freeconn(conn); + HAL_MutexUnlock(g_atconnmutex); + if (err != 0) { + AT_ERROR("at_freeconn failed in %s.", __func__); + return -1; + } + + return 0; +} + +int at_conn_recvbufempty(int c) +{ + struct at_conn *conn = NULL; + + conn = get_conn(c); + if (NULL == conn) { + AT_ERROR("at_recvbufempty cannot get socket %d\n", c); + return -1; + } + + /* remain data */ + if (conn->lastdata) + return 0; + + if (!at_mbox_valid(&conn->recvmbox)) { + AT_ERROR("conn %d invalid recvmbox\n", c); + return -1; + } + + return at_mbox_empty(&conn->recvmbox); +} + +int at_conn_send(int c, const void *data, uint32_t size) +{ + struct at_conn *conn = NULL; + + if (NULL == data || size == 0 || size > AT_MAX_PAYLOAD_SIZE) { + AT_ERROR("at_conn_send fail to send, size %d\n", size); + return -1; + } + + conn = get_conn(c); + if (NULL == conn) { + AT_ERROR("at_conn_send fail to get conn %d\n", c); + return -1; + } + + if (conn->type == NETCONN_TCP) { + if (conn->state == NETCONN_NONE) { + AT_ERROR("at_conn_send connect %d state %d\n", c, conn->state); + return -1; + } + } + + if (HAL_AT_CONN_Send(c, (uint8_t *)data, size, NULL, -1, conn->send_timeout_ms)) { + AT_ERROR("c %d fail to send do nothing for now\n", c); + return -1; + } + + return size; +} + +int at_conn_recv(int c, void *mem, uint32_t len) +{ + struct at_conn *conn = NULL; + at_netbuf_t *buf = NULL; + int off = 0; + uint16_t buflen = 0; + uint16_t copylen = 0; + int err = 0; + uint8_t done = 0; + + if (NULL == mem || 0 == len) { + return -1; + } + + conn = get_conn(c); + if (NULL == conn) { + AT_ERROR("at_conn_recv fail to get conn %d\n", c); + return -1; + } + + do { + if (conn->lastdata) { + buf = conn->lastdata; + } else { + err = at_conn_fetch(conn, &buf); + if (err != 0 || buf == NULL || buf->payload == NULL) { + if (off > 0) { + return off; + } else { + return -1; + } + } + + conn->lastdata = buf; + } + + buflen = buf->len; + AT_DEBUG("at_conn_recv: buflen=%u, len=%u, off=%d, lastoffset=%u\n", + buflen, len, off, conn->lastoffset); + + buflen -= conn->lastoffset; + if (len > buflen) { + copylen = buflen; + } else { + copylen = len; + } + + memcpy(&((uint8_t *)mem)[off], &((uint8_t *)buf->payload)[conn->lastoffset], copylen); + off += copylen; + + if (NETCONN_TCP == conn->type) { + if (len < copylen) { + AT_ERROR("invalid copylen %d, len = %d\n", copylen, len); + return -1; + } + + len -= copylen; + if (len <= 0) { + done = 1; + } + } else { + done = 1; + } + + if ((NETCONN_TCP == conn->type) && (buflen > copylen)) { + conn->lastdata = buf; + conn->lastoffset += copylen; + } else { + conn->lastdata = NULL; + conn->lastoffset = 0; + free_payload(buf->payload); + buf->payload = NULL; + free_atnetbuf(buf); + buf = NULL; + } + } while (!done); + + return off; +} diff --git a/iotkit-embedded/src/atm/at_conn_mgmt.h b/iotkit-embedded/src/atm/at_conn_mgmt.h new file mode 100644 index 0000000..7131fef --- /dev/null +++ b/iotkit-embedded/src/atm/at_conn_mgmt.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2015-2019 Alibaba Group Holding Limited + */ + +#ifndef _AT_CONN_MGMT_H_ +#define _AT_CONN_MGMT_H_ + +typedef enum netconn_type { + NETCONN_INVALID = 0, + /** TCP IPv4 */ + NETCONN_TCP, + NETCONN_TYPE_NUM +} netconn_type_t; + +/** + * at connection module initialization + * + * @param null + * + * @return 0 : on success, -1: error + */ +int at_conn_init(void); + +/** + * receive data from an at connection + * + * @param[in]: connection id; + * @param[out]: pointer to output buffer + * @param[in]: expect length + * + * @return 0 : on success, -1: error + */ +int at_conn_recv(int connid, void *mem, uint32_t len); + +/** + * query ip from domain address + * + * @param[in]: domain address + * @param[out]: query result + * + * @return 0 : on success, -1: error + */ +int at_conn_getaddrinfo(const char *nodename, char resultip[16]); + + +/** + * setup an new at connection + * + * @param[in]: connection type only tcp support + * + * @return 0 : on success, -1: error + */ +int at_conn_setup(netconn_type_t type); + +/** + * start an at connection + * + * @param[in]: connection id + * @param[in]: remote ip address + * @param[in]: remote port + * + * @return 0 : on success, -1: error + */ +int at_conn_start(int connid, char* remoteipaddr, uint16_t remoteport); + +/** + * close an at connection + * + * @param[in] connection id + * + * @return 0 : on success, -1: error + */ +int at_conn_close(int connid); + +/** + * check whether recvbuf empty + * + * @param[in] connection id + * + * @return 0 : on success, -1: error + */ +int at_conn_recvbufempty(int connid); + +/** + * send data through an at connection + * + * @param[in] connection id + * @param[in] send buf pointer + * + * @return 0 : on success, -1: error + */ +int at_conn_send(int connid, const void *data, uint32_t size); + +#endif diff --git a/iotkit-embedded/src/atm/at_mqtt.c b/iotkit-embedded/src/atm/at_mqtt.c new file mode 100644 index 0000000..9b1c7ee --- /dev/null +++ b/iotkit-embedded/src/atm/at_mqtt.c @@ -0,0 +1,1269 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include + +#include "mqtt_api.h" +#include "mqtt_wrapper.h" +#include "at_mqtt.h" +#include "at_wrapper.h" + +#ifndef PLATFORM_HAS_OS + #ifdef AT_PARSER_ENABLED + #include "at_parser.h" + #endif +#endif + +#define MAL_TIMEOUT_FOREVER -1 +#define MAL_TIMEOUT_DEFAULT 3000 +#define MAL_MC_PACKET_ID_MAX (65535) +#define MAL_MC_DEFAULT_BUFFER_NUM 1 +#ifdef PLATFORM_HAS_DYNMEM + #define MAL_MC_MAX_BUFFER_NUM 14 +#else + #define MAL_MC_MAX_BUFFER_NUM 1 +#endif +#define MAL_MC_MAX_TOPIC_LEN CONFIG_MQTT_TOPIC_MAXLEN +#define MAL_MC_MAX_MSG_LEN CONFIG_MQTT_MESSAGE_MAXLEN + +#define MAL_MC_DEFAULT_TIMEOUT (8000) + +#define mal_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define mal_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define mal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define mal_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define mal_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define mal_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) + +#ifdef PLATFORM_HAS_DYNMEM + #ifdef INFRA_MEM_STATS + #include "infra_mem_stats.h" + #define mal_malloc(size) LITE_malloc(size, MEM_MAGIC, "mqtt") + #define mal_free(ptr) LITE_free(ptr) + #else + #define mal_malloc(size) HAL_Malloc(size) + #define mal_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;} + #endif /* INFRA_MEM_STATS */ +#else + #define IOTX_MC_CLIENT_MAX_COUNT 1 +#endif + +typedef struct at_mqtt_msg_buff_s { + uint8_t write_index; + uint8_t read_index; + uint8_t last_write_index; + uint8_t valid_flag[MAL_MC_MAX_BUFFER_NUM]; + uint8_t buffer_num; + char *topic[MAL_MC_MAX_BUFFER_NUM]; + char *msg_data[MAL_MC_MAX_BUFFER_NUM]; + void *buffer_mutex; +} at_mqtt_msg_buff_t; +static at_mqtt_msg_buff_t g_at_mqtt_buff_mgr; +#ifdef PLATFORM_HAS_DYNMEM +static char g_at_mqtt_topic[MAL_MC_DEFAULT_BUFFER_NUM][MAL_MC_MAX_TOPIC_LEN]; +static char g_at_mqtt_msg_data[MAL_MC_DEFAULT_BUFFER_NUM][MAL_MC_MAX_MSG_LEN]; +#else +static char g_at_mqtt_topic[MAL_MC_MAX_BUFFER_NUM][MAL_MC_MAX_TOPIC_LEN]; +static char g_at_mqtt_msg_data[MAL_MC_MAX_BUFFER_NUM][MAL_MC_MAX_MSG_LEN]; +iotx_mc_client_t g_iotx_mc_client[IOTX_MC_CLIENT_MAX_COUNT] = {0}; +#endif + +static iotx_mc_state_t mal_mc_get_client_state(iotx_mc_client_t *pClient); +static void mal_mc_set_client_state(iotx_mc_client_t *pClient, iotx_mc_state_t newState); + +typedef struct { + uint32_t time; +} mal_time_t; + +static uint32_t mal_time_is_expired(mal_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; + } +} + +static uint32_t mal_time_left(mal_time_t *end) +{ + uint32_t now, res; + + if (!end) { + return 0; + } + + if (mal_time_is_expired(end)) { + return 0; + } + + now = HAL_UptimeMs(); + res = end->time - now; + return res; +} + +static void mal_time_init(mal_time_t *timer) +{ + if (!timer) { + return; + } + + timer->time = 0; +} + +static void mal_time_countdown_ms(mal_time_t *timer, uint32_t millisecond) +{ + if (!timer) { + return; + } + + timer->time = HAL_UptimeMs() + millisecond; +} + +static int mal_mc_check_rule(char *iterm, iotx_mc_topic_type_t type) +{ + int i = 0; + int len = 0; + + if (NULL == iterm) { + mal_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) { + mal_err("the character # and + is error"); + return FAIL_RETURN; + } + } + } else { + if ('+' == iterm[i] || '#' == iterm[i]) { + mal_err("has character # and + is error"); + return FAIL_RETURN; + } + } + + if (iterm[i] < 32 || iterm[i] >= 127) { + return FAIL_RETURN; + } + } + return SUCCESS_RETURN; +} + +/* check whether the topic is matched or not */ +static char mal_mc_is_topic_matched(char *topicFilter, const char *topicName) +{ + char *curf; + const char *curn; + const char *curn_end; + + if (!topicFilter || !topicName) { + return 0; + } + + curf = topicFilter; + curn = topicName; + curn_end = curn + strlen(topicName); + + 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 */ + const 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'); +} + +/* Check topic name */ +/* 0, topic name is valid; NOT 0, topic name is invalid */ +static int mal_mc_check_topic(const char *topicName, iotx_mc_topic_type_t type) +{ + int mask = 0; + char *delim = "/"; + char *iterm = NULL; + char topicString[MAL_MC_MAX_TOPIC_LEN]; + if (NULL == topicName || '/' != topicName[0]) { + return FAIL_RETURN; + } + + if (strlen(topicName) > MAL_MC_MAX_TOPIC_LEN) { + mal_err("len of topicName(%d) exceeds 64", strlen(topicName)); + return FAIL_RETURN; + } + + memset(topicString, 0x0, MAL_MC_MAX_TOPIC_LEN); + strncpy(topicString, topicName, MAL_MC_MAX_TOPIC_LEN - 1); + + iterm = strtok(topicString, delim); + + if (SUCCESS_RETURN != mal_mc_check_rule(iterm, type)) { + mal_err("run iotx_check_rule error"); + return FAIL_RETURN; + } + + for (;;) { + iterm = strtok(NULL, delim); + + if (iterm == NULL) { + break; + } + + /* The character '#' is not in the last */ + if (1 == mask) { + mal_err("the character # is error"); + return FAIL_RETURN; + } + + if (SUCCESS_RETURN != mal_mc_check_rule(iterm, type)) { + mal_err("run iotx_check_rule error"); + return FAIL_RETURN; + } + + if (iterm[0] == '#') { + mask = 1; + } + } + + return SUCCESS_RETURN; +} + +#ifndef PLATFORM_HAS_DYNMEM +static int mal_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; + } + 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; + } + return 0; +} +static int mal_mc_check_handle_is_identical(iotx_mc_topic_handle_t *messageHandlers1, + iotx_mc_topic_handle_t *messageHandler2) +{ + if (mal_mc_check_handle_is_identical_ex(messageHandlers1, messageHandler2) != 0) { + return 1; + } + if (messageHandlers1->handle.h_fp != messageHandler2->handle.h_fp) { + return 1; + } + if (messageHandlers1->handle.pcontext != messageHandler2->handle.pcontext) { + return 1; + } + return 0; +} +#endif /* PLATFORM_HAS_DYNMEM */ +/* MQTT send connect packet */ +static int MALMQTTConnect(iotx_mc_client_t *pClient) +{ + 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}; + + HAL_GetProductKey(product_key); + HAL_GetDeviceName(device_name); + HAL_GetDeviceSecret(device_secret); + + if (0 != HAL_AT_MQTT_Connect(product_key, device_name, device_secret)) { + return FAIL_RETURN; + } + + return SUCCESS_RETURN; +} + +static int MALMQTTPublish(iotx_mc_client_t *c, const char *topicName, iotx_mqtt_topic_info_pt topic_msg) + +{ + if (!c || !topicName || !topic_msg) { + mal_err("MALMQTTPublish invalid parms\n"); + return FAIL_RETURN; + } + + if (0 != HAL_AT_MQTT_Publish(topicName, topic_msg->qos, topic_msg->payload, + topic_msg->payload_len)) { + mal_err("MALMQTTPublish publish failed\n"); + return FAIL_RETURN; + } + + return SUCCESS_RETURN; +} + +#ifdef PLATFORM_HAS_DYNMEM +static int remove_handle_from_list(iotx_mc_client_t *c, iotx_mc_topic_handle_t *h) +{ + iotx_mc_topic_handle_t **hp, *h1; + hp = &c->first_sub_handle; + while ((*hp) != NULL) { + h1 = *hp; + if (h1 == h) { + *hp = h->next; + } else { + hp = &h1->next; + } + } + + return 0; +} +#endif + +/* MQTT send subscribe packet */ +static int MALMQTTSubscribe(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 timeout_ms) +{ + int status; + iotx_mc_topic_handle_t *h = NULL; +#ifndef PLATFORM_HAS_DYNMEM + int idx = 0; + int dup = 0; +#endif + + if (!c || !topicFilter || !messageHandler) { + return FAIL_RETURN; + } +#ifdef PLATFORM_HAS_DYNMEM + h = mal_malloc(sizeof(iotx_mc_topic_handle_t)); + if (h == NULL) { + mal_err("maloc failed!"); + return FAIL_RETURN; + } +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + if (c->list_sub_handle[idx].used == 0) { + h = &c->list_sub_handle[idx]; + memset(h, 0, sizeof(iotx_mc_topic_handle_t)); + c->list_sub_handle[idx].used = 1; + break; + } + } + + if (h == NULL) { + mal_err("sub handle list is too short!"); + return FAIL_RETURN; + } +#endif +#ifdef PLATFORM_HAS_DYNMEM + memset(h, 0, sizeof(iotx_mc_topic_handle_t)); + + h->topic_filter = mal_malloc(strlen(topicFilter) + 1); + if (NULL == h->topic_filter) { + mal_free(h); + return FAIL_RETURN; + } +#else + if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) { + mal_err("sub topic length is too large!"); + memset(h, 0, sizeof(iotx_mc_topic_handle_t)); + return FAIL_RETURN; + } +#endif + memcpy((char *)h->topic_filter, topicFilter, strlen(topicFilter) + 1); + + h->handle.h_fp = messageHandler; + h->handle.pcontext = pcontext; + h->topic_type = TOPIC_NAME_TYPE; + + HAL_MutexLock(c->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM + h->next = c->first_sub_handle; + c->first_sub_handle = h; +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + if (&c->list_sub_handle[idx] != h && + 0 == mal_mc_check_handle_is_identical(&c->list_sub_handle[idx], h)) { + mal_warning("dup sub,topic = %s", topicFilter); + dup = 1; + } + } + if (dup == 1) { + memset(h, 0, sizeof(iotx_mc_topic_handle_t)); + } +#endif + HAL_MutexUnlock(c->lock_generic); + if (HAL_AT_MQTT_Subscribe(topicFilter, qos, &msgId, &status, timeout_ms) != 0) { + return FAIL_RETURN; + } + return SUCCESS_RETURN; +} + + +/* MQTT send unsubscribe packet */ +static int MALMQTTUnsubscribe(iotx_mc_client_t *c, const char *topicFilter, unsigned int msgId) +{ + int status; + int ret; +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *h; +#else + int idx; +#endif + + ret = HAL_AT_MQTT_Unsubscribe(topicFilter, &msgId, &status); + if (ret != 0) { + return -1; + } + +#ifdef PLATFORM_HAS_DYNMEM + for (h = c->first_sub_handle; h != NULL; h = h->next) { + if (((strlen(topicFilter) == strlen(h->topic_filter)) + && (strcmp(topicFilter, (char *)h->topic_filter) == 0)) + || (mal_mc_is_topic_matched((char *)h->topic_filter, topicFilter))) { + remove_handle_from_list(c, h); + } + } +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + if ((c->list_sub_handle[idx].used == 1) && + (((strlen(topicFilter) == strlen(c->list_sub_handle[idx].topic_filter)) + && (strcmp(topicFilter, (char *)c->list_sub_handle[idx].topic_filter) == 0)) || + mal_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, topicFilter))) { + mal_debug("topic be matched"); + memset(&c->list_sub_handle[idx], 0, sizeof(iotx_mc_topic_handle_t)); + } + } +#endif + + return 0; +} + +/* MQTT send disconnect packet */ +static int MALMQTTDisconnect(iotx_mc_client_t *c) +{ + return HAL_AT_MQTT_Disconnect(); +} + +/* get next packet-id */ +static int mal_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 == MAL_MC_PACKET_ID_MAX) ? 1 : c->packet_id + 1; + id = c->packet_id; + HAL_MutexUnlock(c->lock_generic); + + return id; +} + +/* handle PUBLISH packet received from remote MQTT broker */ +static int iotx_mc_handle_recv_PUBLISH(iotx_mc_client_t *c, char *topic, char *msg) +{ + iotx_mqtt_topic_info_t topic_msg = {0}; + int flag_matched = 0; + static uint64_t time_prev = 0; + uint64_t time_curr = 0; + /* flowControl for specific topic */ + char *filterStr = "{\"method\":\"thing.service.property.set\""; + int filterLen = strlen(filterStr); +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *h, *msg_handle; +#else + iotx_mc_topic_handle_t *msg_handle; + int idx; +#endif + + if (!c || !topic || !msg) { + return FAIL_RETURN; + } + mal_debug("recv pub topic=%s msg=%s", topic, msg); + + if (0 == memcmp(msg, filterStr, filterLen)) { + /* mal_debug("iotx_mc_handle_recv_PUBLISH match filterstring"); */ + time_curr = HAL_UptimeMs(); + if (time_curr < time_prev) { + time_curr = time_prev; + } + if ((time_curr - time_prev) <= (uint64_t)50) { + mal_debug("pub over threshould"); + return SUCCESS_RETURN; + } else { + time_prev = time_curr; + } + } + + /* we have to find the right message handler - indexed by topic */ + HAL_MutexLock(c->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM + for (h = c->first_sub_handle; h != NULL; h = h->next) { + if (((strlen(topic) == strlen(h->topic_filter)) + && (strcmp(topic, (char *)h->topic_filter) == 0)) + || (mal_mc_is_topic_matched((char *)h->topic_filter, topic))) { + msg_handle = h; +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + if ((c->list_sub_handle[idx].used == 1) && + (((strlen(topic) == strlen(c->list_sub_handle[idx].topic_filter)) + && (strcmp(topic, (char *)c->list_sub_handle[idx].topic_filter) == 0)) + || (mal_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, topic)))) { + msg_handle = &c->list_sub_handle[idx]; +#endif + mal_debug("pub topic is matched"); + + HAL_MutexUnlock(c->lock_generic); + + if (NULL != msg_handle->handle.h_fp) { + iotx_mqtt_event_msg_t event_msg; + topic_msg.payload = msg; + topic_msg.payload_len = strlen(msg); + topic_msg.ptopic = topic; + topic_msg.topic_len = strlen(topic); + event_msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED; + event_msg.msg = &topic_msg; + msg_handle->handle.h_fp(msg_handle->handle.pcontext, c, &event_msg); + flag_matched = 1; + } + + HAL_MutexLock(c->lock_generic); + } + } + + HAL_MutexUnlock(c->lock_generic); + + if (0 == flag_matched) { + mal_debug("NO matching any topic, call default handle function"); + + if (NULL != c->handle_event.h_fp) { + iotx_mqtt_event_msg_t event_msg; + + topic_msg.payload = msg; + topic_msg.payload_len = strlen(msg); + topic_msg.ptopic = topic; + topic_msg.topic_len = strlen(topic); + event_msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED; + event_msg.msg = &topic_msg; + + c->handle_event.h_fp(c->handle_event.pcontext, c, &event_msg); + } + } + + return SUCCESS_RETURN; +} + +/* MQTT cycle to handle packet from remote broker */ +static int mal_mc_cycle(iotx_mc_client_t *c, mal_time_t *timer) +{ + int rc = SUCCESS_RETURN; + char *msg = NULL; + char *topic = NULL; + uint8_t read_index = 0; + + if (!c) { + return FAIL_RETURN; + } + + if (HAL_AT_MQTT_State() == IOTX_MC_STATE_CONNECTED) { + mal_mc_set_client_state(c, IOTX_MC_STATE_CONNECTED); + } + + if (mal_mc_get_client_state(c) != IOTX_MC_STATE_CONNECTED) { + mal_err("mal state = %d error", mal_mc_get_client_state(c)); +#ifndef PLATFORM_HAS_OS +#ifdef AT_PARSER_ENABLED + at_yield(NULL, 0, NULL, 100); +#endif +#endif + return MQTT_STATE_ERROR; + } + + if (HAL_AT_MQTT_State() != IOTX_MC_STATE_CONNECTED) { + mal_err("hal mal state = %d error", HAL_AT_MQTT_State()); + mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); +#ifndef PLATFORM_HAS_OS +#ifdef AT_PARSER_ENABLED + at_yield(NULL, 0, NULL, 100); +#endif +#endif + return MQTT_NETWORK_ERROR; + } + + /* read the buf, see what work is due */ + HAL_MutexLock(g_at_mqtt_buff_mgr.buffer_mutex); + read_index = g_at_mqtt_buff_mgr.read_index; + + if (g_at_mqtt_buff_mgr.valid_flag[read_index] == 0) { + HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex); + return FAIL_RETURN; + } + + topic = g_at_mqtt_buff_mgr.topic[read_index]; + msg = g_at_mqtt_buff_mgr.msg_data[read_index]; + + rc = iotx_mc_handle_recv_PUBLISH(c, topic, msg); + if (SUCCESS_RETURN != rc) { + mal_err("recvPublishProc error,result = %d", rc); + } + + memset(g_at_mqtt_buff_mgr.topic[read_index], 0, MAL_MC_MAX_TOPIC_LEN); + memset(g_at_mqtt_buff_mgr.msg_data[read_index], 0, MAL_MC_MAX_MSG_LEN); + g_at_mqtt_buff_mgr.valid_flag[read_index] = 0; + + read_index++; + if (read_index >= g_at_mqtt_buff_mgr.buffer_num) { + read_index = 0; + } + + g_at_mqtt_buff_mgr.read_index = read_index; + HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex); + + return rc; +} + +/* get state of MQTT client */ +static iotx_mc_state_t mal_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; +} + +/* set state of MQTT client */ +static void mal_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 int mal_mc_recv_buf_init() +{ + int i; + g_at_mqtt_buff_mgr.read_index = 0; + g_at_mqtt_buff_mgr.write_index = 0; + g_at_mqtt_buff_mgr.last_write_index = 0; + g_at_mqtt_buff_mgr.buffer_num = MAL_MC_DEFAULT_BUFFER_NUM; + + for (i = 0; i < MAL_MC_MAX_BUFFER_NUM; i++) { + g_at_mqtt_buff_mgr.valid_flag[i] = 0; +#ifdef PLATFORM_HAS_DYNMEM + if (i < MAL_MC_DEFAULT_BUFFER_NUM) { + g_at_mqtt_buff_mgr.topic[i] = g_at_mqtt_topic[i]; + g_at_mqtt_buff_mgr.msg_data[i] = g_at_mqtt_msg_data[i]; + memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN); + memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN); + } else { + g_at_mqtt_buff_mgr.topic[i] = NULL; + g_at_mqtt_buff_mgr.msg_data[i] = NULL; + } +#else + g_at_mqtt_buff_mgr.topic[i] = g_at_mqtt_topic[i]; + g_at_mqtt_buff_mgr.msg_data[i] = g_at_mqtt_msg_data[i]; + memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN); + memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN); +#endif + } + + if (NULL == (g_at_mqtt_buff_mgr.buffer_mutex = HAL_MutexCreate())) { + mal_err("create buffer mutex error"); + return -1; + } + + return 0; +} + +static void mal_mc_recv_buf_deinit() +{ + int i; + g_at_mqtt_buff_mgr.read_index = 0; + g_at_mqtt_buff_mgr.write_index = 0; + g_at_mqtt_buff_mgr.last_write_index = 0; + +#ifdef PLATFORM_HAS_DYNMEM + for (i = 0; i < MAL_MC_MAX_BUFFER_NUM; i++) { + g_at_mqtt_buff_mgr.valid_flag[i] = 0; + if (i < MAL_MC_DEFAULT_BUFFER_NUM) { + memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN); + memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN); + } else { + if (i < g_at_mqtt_buff_mgr.buffer_num) { + if (g_at_mqtt_buff_mgr.topic[i] != NULL) { + mal_free(g_at_mqtt_buff_mgr.topic[i]); + } + if (g_at_mqtt_buff_mgr.msg_data[i] != NULL) { + mal_free(g_at_mqtt_buff_mgr.msg_data[i]); + } + } + } + } +#else + for (i = 0; i < g_at_mqtt_buff_mgr.buffer_num; i++) { + g_at_mqtt_buff_mgr.valid_flag[i] = 0; + memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN); + memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN); + } +#endif + + HAL_MutexDestroy(g_at_mqtt_buff_mgr.buffer_mutex); +} + +static int mal_mc_wait_for_result() +{ +#ifdef PLATFORM_HAS_OS + mal_time_t time; + int state = 0; + int timeout_ms = MAL_MC_DEFAULT_TIMEOUT; + mal_time_init(&time); + mal_time_countdown_ms(&time, timeout_ms); + do { + unsigned int left_t; + left_t = mal_time_left(&time); + if (left_t < 100) { + HAL_SleepMs(left_t); + } else { + HAL_SleepMs(100); + } + + state = HAL_AT_MQTT_State(); + } while (!mal_time_is_expired(&time) && (state != IOTX_MC_STATE_CONNECTED)); + + if (state == IOTX_MC_STATE_CONNECTED) { + return SUCCESS_RETURN; + } else { + return FAIL_RETURN; + } +#else + int state = 0; +#ifdef AT_PARSER_ENABLED + int timeout_ms = 1000; +#endif + int count = 10; + while ((count > 0) && ((state = HAL_AT_MQTT_State()) != IOTX_MC_STATE_CONNECTED)) { +#ifdef AT_PARSER_ENABLED + at_yield(NULL, 0, NULL, timeout_ms); +#endif + count --; + } + + if (state == IOTX_MC_STATE_CONNECTED) { + return SUCCESS_RETURN; + } else { + return FAIL_RETURN; + } +#endif +} + +static int mal_mc_disconnect(iotx_mc_client_t *pClient) +{ + int rc = -1; + + if (NULL == pClient) { + return NULL_VALUE_ERROR; + } + + if (wrapper_mqtt_check_state(pClient)) { + rc = MALMQTTDisconnect(pClient); + mal_debug("rc = MALMQTTDisconnect() = %d", rc); + } + + mal_mc_set_client_state(pClient, IOTX_MC_STATE_INITIALIZED); + + mal_info("mqtt disconnect!"); + return SUCCESS_RETURN; +} + +int at_mqtt_input(struct at_mqtt_input *param) +{ + char *topic; + uint32_t topic_len; + char *message; + uint32_t message_len; + uint8_t write_index; + char *copy_ptr; + + if (NULL == param) { + mal_err("input param null"); + return -1; + } + + topic = param->topic; + topic_len = param->topic_len; + message = param->message; + message_len = param->msg_len; + + if ((topic == NULL) || (topic_len == 0) || + (message == NULL) || (message_len == 0)) { + mal_err("input topic or message is NULL"); + return -1; + } + + if ((topic_len >= MAL_MC_MAX_TOPIC_LEN) || + (message_len >= MAL_MC_MAX_MSG_LEN)) { + mal_err("topic(%d) or message(%d) too large", topic_len, message_len); + return -1; + } + + HAL_MutexLock(g_at_mqtt_buff_mgr.buffer_mutex); + write_index = g_at_mqtt_buff_mgr.write_index; + + if ((g_at_mqtt_buff_mgr.valid_flag[write_index]) + && (g_at_mqtt_buff_mgr.buffer_num == MAL_MC_MAX_BUFFER_NUM)) { + mal_err("buffer is full"); + + HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex); + return -1; + } + if (g_at_mqtt_buff_mgr.valid_flag[write_index]) { + int last_write_index = write_index; + g_at_mqtt_buff_mgr.last_write_index = last_write_index; + write_index = g_at_mqtt_buff_mgr.buffer_num; + mal_err("increase buffer to %d", g_at_mqtt_buff_mgr.buffer_num); +#ifdef PLATFORM_HAS_DYNMEM + g_at_mqtt_buff_mgr.topic[write_index] = mal_malloc(MAL_MC_MAX_TOPIC_LEN); + if (g_at_mqtt_buff_mgr.topic[write_index] == NULL) { + mal_err("increase buffer failed, drop it"); + return -1; + } + g_at_mqtt_buff_mgr.msg_data[write_index] = mal_malloc(MAL_MC_MAX_MSG_LEN); + if (g_at_mqtt_buff_mgr.msg_data[write_index] == NULL) { + mal_err("increase buffer failed, drop it"); + mal_free(g_at_mqtt_buff_mgr.topic[write_index]); + return -1; + } + g_at_mqtt_buff_mgr.buffer_num ++; +#else + g_at_mqtt_buff_mgr.buffer_num ++; + g_at_mqtt_buff_mgr.topic[g_at_mqtt_buff_mgr.buffer_num] = g_at_mqtt_topic[g_at_mqtt_buff_mgr.buffer_num]; + g_at_mqtt_buff_mgr.msg_data[g_at_mqtt_buff_mgr.buffer_num] = g_at_mqtt_msg_data[g_at_mqtt_buff_mgr.buffer_num]; + memset(g_at_mqtt_buff_mgr.topic[g_at_mqtt_buff_mgr.buffer_num], 0, MAL_MC_MAX_TOPIC_LEN); + memset(g_at_mqtt_buff_mgr.msg_data[g_at_mqtt_buff_mgr.buffer_num], 0, MAL_MC_MAX_MSG_LEN); +#endif + } else { + g_at_mqtt_buff_mgr.last_write_index = 0; + } + + copy_ptr = g_at_mqtt_buff_mgr.topic[write_index]; + memcpy(copy_ptr, topic, topic_len); + copy_ptr = g_at_mqtt_buff_mgr.msg_data[write_index]; + memcpy(copy_ptr, message, message_len); + + g_at_mqtt_buff_mgr.valid_flag[write_index] = 1; + write_index++; + + if (write_index >= g_at_mqtt_buff_mgr.buffer_num) { + write_index = 0; + } + + if (g_at_mqtt_buff_mgr.last_write_index != 0) { + g_at_mqtt_buff_mgr.write_index = g_at_mqtt_buff_mgr.last_write_index; + } else { + g_at_mqtt_buff_mgr.write_index = write_index; + } + HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex); + + return 0; +} + +/* Initialize MQTT client */ +static int mal_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; + + if (pClient == NULL || pInitParams == NULL || + pInitParams->write_buf_size == 0 || pInitParams->read_buf_size == 0) { + return NULL_VALUE_ERROR; + } + + memset(pClient, 0, sizeof(iotx_mc_client_t)); + + if (HAL_AT_MQTT_Init(pInitParams) != 0) { + mal_err("low layer init failed"); + return FAIL_RETURN; + } + + pClient->lock_generic = HAL_MutexCreate(); + if (!pClient->lock_generic) { + return FAIL_RETURN; + } + + pClient->lock_yield = HAL_MutexCreate(); + if (!pClient->lock_yield) { + goto RETURN; + } + + pClient->handle_event.h_fp = pInitParams->handle_event.h_fp; + pClient->handle_event.pcontext = pInitParams->handle_event.pcontext; + + mal_mc_recv_buf_init(); + + mc_state = IOTX_MC_STATE_INITIALIZED; + rc = SUCCESS_RETURN; + +RETURN: + mal_mc_set_client_state(pClient, mc_state); + + if (rc != SUCCESS_RETURN) { + if (pClient->lock_generic) { + HAL_MutexDestroy(pClient->lock_generic); + pClient->lock_generic = NULL; + } + + if (pClient->lock_yield) { + HAL_MutexDestroy(pClient->lock_yield); + pClient->lock_yield = NULL; + } + } + + return rc; +} + +/************************ Public Interface ************************/ +void *wrapper_mqtt_init(iotx_mqtt_param_t *mqtt_params) +{ + int err; + iotx_mc_client_t *pclient; +#ifndef PLATFORM_HAS_DYNMEM + int idx; +#endif + +#ifdef PLATFORM_HAS_DYNMEM + pclient = (iotx_mc_client_t *)mal_malloc(sizeof(iotx_mc_client_t)); + if (NULL == pclient) { + mal_err("not enough memory."); + if (mqtt_params != NULL) { + mal_free(mqtt_params); + } + return NULL; + } +#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) { + mal_err("wrapper_mqtt_init IOTX_MC_CLIENT_MAX_COUNT too short: %d", IOTX_MC_CLIENT_MAX_COUNT); + return NULL; + } +#endif + err = mal_mc_init(pclient, mqtt_params); + if (SUCCESS_RETURN != err) { + mal_err("mal_mc_init failed"); +#ifdef PLATFORM_HAS_DYNMEM + mal_free(pclient); +#else + memset(pclient, 0, sizeof(iotx_mc_client_t)); +#endif + return NULL; + } + + return pclient; +} + +int wrapper_mqtt_connect(void *client) +{ + int rc = FAIL_RETURN; + + if (NULL == client) { + return NULL_VALUE_ERROR; + } + + rc = MALMQTTConnect((iotx_mc_client_t *)client); + if (rc != SUCCESS_RETURN) { + mal_err("send connect packet failed"); + return rc; + } + if (SUCCESS_RETURN != mal_mc_wait_for_result()) { + mal_err("current state is not connected"); + return FAIL_RETURN; + } + + mal_mc_set_client_state((iotx_mc_client_t *)client, IOTX_MC_STATE_CONNECTED); + + mal_info("mqtt connect success!"); + return SUCCESS_RETURN; +} + +int wrapper_mqtt_yield(void *client, int timeout_ms) +{ + int rc = SUCCESS_RETURN; + mal_time_t time; + unsigned int left_t; + + iotx_mc_client_t *pClient = (iotx_mc_client_t *)client; + + if (pClient == NULL) { + return NULL_VALUE_ERROR; + } + + if (timeout_ms < 0) { + mal_err("Invalid argument, timeout_ms = %d", timeout_ms); + return -1; + } + if (timeout_ms == 0) { + timeout_ms = 10; + } + + mal_time_init(&time); + mal_time_countdown_ms(&time, timeout_ms); + + do { + if (SUCCESS_RETURN != rc) { + unsigned int left_t = mal_time_left(&time); + /*mal_info("error occur or no data");*/ + if (left_t < 20) { + HAL_SleepMs(left_t); + } else { + HAL_SleepMs(20); + } + } + HAL_MutexLock(pClient->lock_yield); + + /* acquire package in cycle, such as PUBLISH */ + rc = mal_mc_cycle(pClient, &time); + HAL_MutexUnlock(pClient->lock_yield); + + left_t = mal_time_left(&time); + if (left_t < 10) { + HAL_SleepMs(left_t); + } else { + HAL_SleepMs(10); + } + } while (!mal_time_is_expired(&time)); + + return 0; +} + +int wrapper_mqtt_check_state(void *client) +{ + if (!client) { + return 0; + } + + if (mal_mc_get_client_state((iotx_mc_client_t *)client) == IOTX_MC_STATE_CONNECTED) { + return 1; + } + + return 0; +} + +int wrapper_mqtt_subscribe_sync(void *client, + const char *topicFilter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms) +{ + int rc = FAIL_RETURN; + unsigned int msgId; + iotx_mc_client_t *c = (iotx_mc_client_t *)client; + + if (NULL == client || NULL == topicFilter || strlen(topicFilter) == 0 || !topic_handle_func) { + mal_err(" paras error"); + return NULL_VALUE_ERROR; + } + + c = (iotx_mc_client_t *)client; + msgId = mal_mc_get_next_packetid(c); + + if (!wrapper_mqtt_check_state(c)) { + mal_err("mqtt client state is error,state = %d", mal_mc_get_client_state(c)); + return MQTT_STATE_ERROR; + } + + if (0 != mal_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) { + mal_err("topic format is error,topicFilter = %s", topicFilter); + return MQTT_TOPIC_FORMAT_ERROR; + } + + mal_debug("PERFORM subscribe to '%s' (msgId=%d)", topicFilter, msgId); + rc = MALMQTTSubscribe(c, topicFilter, qos, msgId, topic_handle_func, pcontext, timeout_ms); + if (rc != SUCCESS_RETURN) { + if (rc == MQTT_NETWORK_ERROR) { + mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); + } + + mal_err("run MQTTSubscribe error, rc = %d", rc); + return rc; + } + + mal_info("mqtt subscribe packet sent,topic = %s!", topicFilter); + return msgId; +} + +int wrapper_mqtt_subscribe(void *client, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext) +{ + return wrapper_mqtt_subscribe_sync(client, topic_filter, qos, topic_handle_func, pcontext, MAL_TIMEOUT_DEFAULT); +} + +int wrapper_mqtt_unsubscribe(void *client, const char *topicFilter) +{ + int rc = FAIL_RETURN; + unsigned int msgId; + iotx_mc_client_t *c; + + if (NULL == client || NULL == topicFilter) { + return NULL_VALUE_ERROR; + } + + c = (iotx_mc_client_t *)client; + msgId = mal_mc_get_next_packetid(c); + + if (0 != mal_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) { + mal_err("topic format is error,topicFilter = %s", topicFilter); + return MQTT_TOPIC_FORMAT_ERROR; + } + + if (!wrapper_mqtt_check_state(c)) { + mal_err("mqtt client state is error,state = %d", mal_mc_get_client_state(c)); + return MQTT_STATE_ERROR; + } + + rc = MALMQTTUnsubscribe(c, topicFilter, msgId); + if (rc != SUCCESS_RETURN) { + if (rc == MQTT_NETWORK_ERROR) { /* send the subscribe packet */ + mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); + } + + mal_err("run MALMQTTUnsubscribe error!"); + return rc; + } + + mal_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 (NULL == c || NULL == topicName || NULL == topic_msg || NULL == topic_msg->payload) { + return NULL_VALUE_ERROR; + } + + if (0 != mal_mc_check_topic(topicName, TOPIC_NAME_TYPE)) { + mal_err("topic format is error,topicFilter = %s", topicName); + return MQTT_TOPIC_FORMAT_ERROR; + } + + if (!wrapper_mqtt_check_state(c)) { + mal_err("mqtt client state is error,state = %d", mal_mc_get_client_state(c)); + return MQTT_STATE_ERROR; + } + + if (topic_msg->qos == IOTX_MQTT_QOS1 || topic_msg->qos == IOTX_MQTT_QOS2) { + msg_id = mal_mc_get_next_packetid(c); + topic_msg->packet_id = msg_id; + } + + if (topic_msg->qos == IOTX_MQTT_QOS2) { + mal_err("MALMQTTPublish return error,MQTT_QOS2 is now not supported."); + return MQTT_PUBLISH_QOS_ERROR; + } + + rc = MALMQTTPublish(c, topicName, topic_msg); + if (rc != SUCCESS_RETURN) { /* send the subscribe packet */ + if (rc == MQTT_NETWORK_ERROR) { + mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); + } + mal_err("MALMQTTPublish is error, rc = %d", rc); + return rc; + } + + return (int)msg_id; +} + +int wrapper_mqtt_release(void **client) +{ + iotx_mc_client_t *pClient; + + if (NULL == client) { + return NULL_VALUE_ERROR; + } + + pClient = (iotx_mc_client_t *)*client; + if (NULL == pClient) { + return NULL_VALUE_ERROR; + } + + /* iotx_delete_thread(pClient); */ + mal_mc_disconnect(pClient); + mal_mc_set_client_state(pClient, IOTX_MC_STATE_INVALID); +#ifdef PLATFORM_HAS_DYNMEM + if (pClient->first_sub_handle != NULL) { + iotx_mc_topic_handle_t *handler = pClient->first_sub_handle; + iotx_mc_topic_handle_t *next_handler = pClient->first_sub_handle; + while (handler) { + next_handler = handler->next; + if (handler->topic_filter != NULL) { + mal_free(handler->topic_filter); + handler->topic_filter = NULL; + } + mal_free(handler); + handler = next_handler; + } + } +#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_yield); + + mal_mc_recv_buf_deinit(); +#ifdef PLATFORM_HAS_DYNMEM + mal_free(pClient); + *client = NULL; +#else + memset(pClient, 0, sizeof(iotx_mc_client_t) * IOTX_MC_CLIENT_MAX_COUNT); +#endif + mal_info("mqtt release!"); + return SUCCESS_RETURN; +} diff --git a/iotkit-embedded/src/atm/at_mqtt.h b/iotkit-embedded/src/atm/at_mqtt.h new file mode 100644 index 0000000..4eea833 --- /dev/null +++ b/iotkit-embedded/src/atm/at_mqtt.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _AT_MQTT_H_ +#define _AT_MQTT_H_ + +#ifndef PLATFORM_HAS_DYNMEM + #ifndef IOTX_MC_SUBHANDLE_LIST_MAX_LEN + #define IOTX_MC_SUBHANDLE_LIST_MAX_LEN (5) + #endif + + #ifndef CONFIG_MQTT_TOPIC_MAXLEN + #define CONFIG_MQTT_TOPIC_MAXLEN (128) + #endif +#endif + +/* 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_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 { +#ifdef PLATFORM_HAS_DYNMEM + const char *topic_filter; +#else + const char topic_filter[CONFIG_MQTT_TOPIC_MAXLEN]; + int used; +#endif + iotx_mc_topic_type_t topic_type; + iotx_mqtt_event_handle_t handle; + struct iotx_mc_topic_handle_s *next; +} iotx_mc_topic_handle_t; + +typedef struct Client { + uint32_t packet_id; /* packet id */ + void *lock_generic; /* generic lock */ + void *lock_yield; +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *first_sub_handle; /* list of subscribe handle */ +#else + iotx_mc_topic_handle_t list_sub_handle[IOTX_MC_SUBHANDLE_LIST_MAX_LEN]; +#endif + void *lock_list_sub; /* lock for list of sub/unsub */ + iotx_mc_state_t client_state; /* state of MQTT client */ + iotx_mqtt_event_handle_t handle_event; /* event handle */ +#ifndef PLATFORM_HAS_DYNMEM + int used; +#endif +} iotx_mc_client_t, *iotx_mc_client_pt; + +#endif diff --git a/iotkit-embedded/src/atm/at_parser.c b/iotkit-embedded/src/atm/at_parser.c new file mode 100644 index 0000000..ec6e1e2 --- /dev/null +++ b/iotkit-embedded/src/atm/at_parser.c @@ -0,0 +1,948 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#include +#include + +#include "infra_types.h" +#include "at_wrapper.h" +#include "at_parser.h" + +#define OOB_MAX 5 + +typedef struct oob_s +{ + char * prefix; + char * postfix; + char * oobinputdata; + uint32_t reallen; + uint32_t maxlen; + at_recv_cb cb; + void * arg; +} oob_t; + +/* + * --> | slist | --> | slist | --> NULL + * --------- --------- + * | smhr | | smpr | + * --------- --------- + * | rsp | | rsp | + * --------- --------- + */ +#if !AT_SINGLE_TASK +#include "infra_list.h" +typedef struct at_task_s +{ + slist_t next; + void * smpr; + char * command; + char * rsp; + char * rsp_prefix; + char * rsp_success_postfix; + char * rsp_fail_postfix; + uint32_t rsp_prefix_len; + uint32_t rsp_success_postfix_len; + uint32_t rsp_fail_postfix_len; + uint32_t rsp_offset; + uint32_t rsp_len; +} at_task_t; +#endif + +/** + * Parser structure for parsing AT commands + */ +typedef struct +{ + uart_dev_t *_pstuart; + int _timeout; + char * _default_recv_prefix; + char * _default_recv_success_postfix; + char * _default_recv_fail_postfix; + char * _send_delimiter; + int _recv_prefix_len; + int _recv_success_postfix_len; + int _recv_fail_postfix_len; + int _send_delim_size; + oob_t _oobs[OOB_MAX]; + int _oobs_num; + void * at_uart_recv_mutex; + void * at_uart_send_mutex; + void * task_mutex; +#if !AT_SINGLE_TASK + slist_t task_l; +#endif +} at_parser_t; + +#define TASK_DEFAULT_WAIT_TIME 5000 + +#ifndef AT_WORKER_STACK_SIZE +#define AT_WORKER_STACK_SIZE 1024 +#endif + +#ifndef AT_UART_TIMEOUT_MS +#define AT_UART_TIMEOUT_MS 1000 +#endif + +#ifndef AT_CMD_DATA_INTERVAL_MS +#define AT_CMD_DATA_INTERVAL_MS 0 +#endif + +#ifdef AT_DEBUG_MODE +#define atpsr_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define atpsr_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define atpsr_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#define atpsr_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#else +#define atpsr_err(...) +#define atpsr_warning(...) +#define atpsr_info(...) +#define atpsr_debug(...) +#endif + +static uint8_t inited = 0; +static uart_dev_t at_uart; + +static at_parser_t at; + +#if !AT_SINGLE_TASK +static void* at_worker(void *arg); +#endif + +#ifndef PLATFORM_HAS_DYNMEM +#if !AT_SINGLE_TASK +static at_task_t g_at_task; +#endif +#endif + +static void at_uart_configure(uart_dev_t *u) +{ + u->port = AT_UART_PORT; + u->config.baud_rate = AT_UART_BAUDRATE; + u->config.data_width = AT_UART_DATA_WIDTH; + u->config.parity = AT_UART_PARITY; + u->config.stop_bits = AT_UART_STOP_BITS; + u->config.flow_control = AT_UART_FLOW_CONTROL; + u->config.mode = AT_UART_MODE; +} + +static int at_init_uart() +{ + at_uart_configure(&at_uart); + + if (HAL_AT_Uart_Init(&at_uart) != 0) { + return -1; + } + + at._pstuart = &at_uart; + + return 0; +} + +static void at_set_timeout(int timeout) +{ + at._timeout = timeout; +} + +static void at_set_recv_delimiter(const char *recv_prefix, + const char *recv_success_postfix, + const char *recv_fail_postfix) +{ + at._default_recv_prefix = (char *)recv_prefix; + at._default_recv_success_postfix = (char *)recv_success_postfix; + at._default_recv_fail_postfix = (char *)recv_fail_postfix; + at._recv_prefix_len = strlen(recv_prefix); + at._recv_success_postfix_len = strlen(recv_success_postfix); + at._recv_fail_postfix_len = strlen(recv_fail_postfix); +} + +static void at_set_send_delimiter(const char *delimiter) +{ + at._send_delimiter = (char *)delimiter; + at._send_delim_size = strlen(delimiter); +} + +static int at_init_task_mutex() +{ + at.task_mutex = HAL_MutexCreate(); + if (NULL == at.task_mutex) { + atpsr_err("Creating task mutex failed\r\n"); + return -1; + } + + return 0; +} + +static void at_deinit_task_mutex() +{ + if (at.task_mutex) { + HAL_MutexDestroy(at.task_mutex); + } + return; +} + +static int at_init_uart_recv_mutex() +{ + at.at_uart_recv_mutex = HAL_MutexCreate(); + if (NULL == at.at_uart_recv_mutex) { + atpsr_err("Creating at_uart_recv_mutex failed\r\n"); + return -1; + } + + return 0; +} + +static void at_deinit_uart_recv_mutex() +{ + if (at.at_uart_recv_mutex) { + HAL_MutexDestroy(at.at_uart_recv_mutex); + } + return; +} + +static int at_worker_uart_send_mutex_init() +{ + at.at_uart_send_mutex = HAL_MutexCreate(); + if (NULL == at.at_uart_send_mutex) { + atpsr_err("Creating at worker sem failed\r\n"); + return -1; + } + return 0; +} + +#if !AT_SINGLE_TASK +static void at_worker_uart_send_mutex_deinit() +{ + if (at.at_uart_send_mutex) { + HAL_MutexDestroy(at.at_uart_send_mutex); + } +} +#endif + +int at_parser_init(void) +{ + char *recv_prefix = AT_RECV_PREFIX; + char *recv_success_postfix = AT_RECV_SUCCESS_POSTFIX; + char *recv_fail_postfix = AT_RECV_FAIL_POSTFIX; + char *send_delimiter = AT_SEND_DELIMITER; + int timeout = AT_UART_TIMEOUT_MS; +#if !AT_SINGLE_TASK + void *task; + int stack_used; + hal_os_thread_param_t task_parms = {0}; +#endif + + if (inited == 1) { + atpsr_info("have already inited ,it will init again\r\n"); + return -1; + } + + memset(&at, 0, sizeof(at_parser_t)); + + if (at_init_uart() != 0) { + atpsr_err("at uart init fail \r\n"); + return -1; + } + + memset(at._oobs, 0, sizeof(oob_t) * OOB_MAX); + + at_set_timeout(timeout); + at_set_recv_delimiter(recv_prefix, recv_success_postfix, recv_fail_postfix); + at_set_send_delimiter(send_delimiter); + + if (at_init_uart_recv_mutex() != 0) { + atpsr_err("at_uart_recv_mutex init fail \r\n"); + return -1; + } + + if (at_init_task_mutex() != 0) { + at_deinit_uart_recv_mutex(); + atpsr_err("at mutex init fail \r\n"); + return -1; + } + + if (at_worker_uart_send_mutex_init() != 0) { + at_deinit_uart_recv_mutex(); + at_deinit_task_mutex(); + atpsr_err("fail to creat at worker sem\r\n"); + } + +#if AT_SINGLE_TASK + inited = true; +#else + slist_init(&at.task_l); + + task_parms.priority = os_thread_priority_normal; + task_parms.stack_size = AT_WORKER_STACK_SIZE; + task_parms.name = "at_worker"; + if (HAL_ThreadCreate(&task, at_worker, NULL, &task_parms, &stack_used) != 0) { + at_deinit_uart_recv_mutex(); + at_deinit_task_mutex(); + at_worker_uart_send_mutex_deinit(); + atpsr_err("fail to creat at task\r\n"); + return -1; + } +#endif + + return 0; +} + +static int at_sendto_lower(uart_dev_t *uart, void *data, uint32_t size, + uint32_t timeout, bool ackreq) +{ + int ret = -1; + + (void) ackreq; + ret = HAL_AT_Uart_Send(uart, data, size, timeout); + + return ret; +} + +static int at_recvfrom_lower(uart_dev_t *uart, void *data, uint32_t expect_size, + uint32_t *recv_size, uint32_t timeout) +{ + int ret = -1; + + ret = HAL_AT_Uart_Recv(uart, data, expect_size, recv_size, timeout); + + return ret; +} + +#if AT_SINGLE_TASK +int at_send_wait_reply(const char *cmd, int cmdlen, bool delimiter, + const char *data, int datalen, + char *replybuf, int bufsize, + const atcmd_config_t *atcmdconfig) +{ + int intval_ms = AT_CMD_DATA_INTERVAL_MS; + + if (at_send_no_reply(cmd, cmdlen, delimiter) < 0) { + return -1; + } + + if (data && datalen) { + if (intval_ms > 0) + HAL_SleepMs(intval_ms); + + if (at_send_no_reply(data, datalen, false) < 0) { + return -1; + } + } + + if (at_yield(replybuf, bufsize, atcmdconfig, at._timeout) < 0) { + return -1; + } + + return 0; +} +#else +static int at_worker_task_add(at_task_t *tsk) +{ + if (NULL == tsk) { + atpsr_err("invalid input %s \r\n", __func__); + return -1; + } + + HAL_MutexLock(at.task_mutex); + slist_add_tail(&tsk->next, &at.task_l); + HAL_MutexUnlock(at.task_mutex); + + return 0; +} + +static int at_worker_task_del(at_task_t *tsk) +{ + if (NULL == tsk) { + atpsr_err("invalid input %s \r\n", __func__); + return -1; + } + + HAL_MutexLock(at.task_mutex); + slist_del(&tsk->next, &at.task_l); + HAL_MutexUnlock(at.task_mutex); + if (tsk->smpr) { + HAL_SemaphoreDestroy(tsk->smpr); + } + if (tsk) { +#ifdef PLATFORM_HAS_DYNMEM + HAL_Free(tsk); +#endif + } + + return 0; +} + +int at_send_wait_reply(const char *cmd, int cmdlen, bool delimiter, + const char *data, int datalen, + char *replybuf, int bufsize, + const atcmd_config_t *atcmdconfig) +{ + int ret = 0; + int intval_ms = AT_CMD_DATA_INTERVAL_MS; + at_task_t *tsk; + + if (inited == 0) { + atpsr_err("at have not init yet\r\n"); + return -1; + } + + if (NULL == cmd || cmdlen <= 0) { + atpsr_err("%s invalid input \r\n", __FUNCTION__); + return -1; + } + + if (NULL == replybuf || 0 == bufsize) { + atpsr_err("%s invalid input \r\n", __FUNCTION__); + return -1; + } + + HAL_MutexLock(at.at_uart_send_mutex); +#ifdef PLATFORM_HAS_DYNMEM + tsk = (at_task_t *)HAL_Malloc(sizeof(at_task_t)); +#else + tsk = &g_at_task; +#endif + if (NULL == tsk) { + atpsr_err("tsk buffer allocating failed"); + HAL_MutexUnlock(at.at_uart_send_mutex); + return -1; + } + memset(tsk, 0, sizeof(at_task_t)); + + tsk->smpr = HAL_SemaphoreCreate(); + if (NULL == tsk->smpr) { + atpsr_err("failed to allocate semaphore"); + goto end; + } + + if (atcmdconfig) { + if (NULL != atcmdconfig->reply_prefix) { + tsk->rsp_prefix = atcmdconfig->reply_prefix; + tsk->rsp_prefix_len = strlen(atcmdconfig->reply_prefix); + } + + if (NULL != atcmdconfig->reply_success_postfix) { + tsk->rsp_success_postfix = atcmdconfig->reply_success_postfix; + tsk->rsp_success_postfix_len = strlen(atcmdconfig->reply_success_postfix); + } + + if (NULL != atcmdconfig->reply_fail_postfix) { + tsk->rsp_fail_postfix = atcmdconfig->reply_fail_postfix; + tsk->rsp_fail_postfix_len = strlen(atcmdconfig->reply_fail_postfix); + } + } + + tsk->command = (char *)cmd; + tsk->rsp = replybuf; + tsk->rsp_len = bufsize; + + at_worker_task_add(tsk); + + if ((ret = at_sendto_lower(at._pstuart, (void *)cmd, cmdlen, + at._timeout, true)) != 0) { + atpsr_err("uart send command failed"); + goto end; + } + + if (delimiter) { + if ((ret = at_sendto_lower(at._pstuart, (void *)at._send_delimiter, + strlen(at._send_delimiter), at._timeout, false)) != 0) { + atpsr_err("uart send delimiter failed"); + goto end; + } + } + + if (data && datalen > 0) { + if (intval_ms > 0) + HAL_SleepMs(intval_ms); + + if ((ret = at_sendto_lower(at._pstuart, (void *)data, datalen, at._timeout, true)) != 0) { + atpsr_err("uart send delimiter failed"); + goto end; + } + } + + if ((ret = HAL_SemaphoreWait(tsk->smpr, TASK_DEFAULT_WAIT_TIME)) != 0) { + atpsr_err("sem_wait failed"); + goto end; + } + +end: + at_worker_task_del(tsk); + HAL_MutexUnlock(at.at_uart_send_mutex); + return ret; +} +#endif + +int at_send_no_reply(const char *data, int datalen, bool delimiter) +{ + int ret = 0; + + if (inited == 0) { + atpsr_err("at have not init yet\r\n"); + return -1; + } + + if (NULL == data || datalen <= 0) { + atpsr_err("invalid input \r\n"); + return -1; + } + + HAL_MutexLock(at.at_uart_send_mutex); + if ((ret = at_sendto_lower(at._pstuart, (void *)data, + datalen, at._timeout, true)) != 0) { + atpsr_err("uart send raw content (%s) failed", data); + HAL_MutexUnlock(at.at_uart_send_mutex); + return -1; + } + + if (delimiter) { + if ((ret = at_sendto_lower(at._pstuart, (void *)at._send_delimiter, + strlen(at._send_delimiter), at._timeout, false)) != 0) { + atpsr_err("uart send delimiter failed"); + HAL_MutexUnlock(at.at_uart_send_mutex); + return -1; + } + } + HAL_MutexUnlock(at.at_uart_send_mutex); + + return ret; +} + +static int at_getc(char *c, int timeout_ms) +{ + int ret = 0; + char data; + uint32_t recv_size = 0; + + if (NULL == c) { + return -1; + } + + if (inited == 0) { + atpsr_err("at have not init yet\r\n"); + return -1; + } + + HAL_MutexLock(at.at_uart_recv_mutex); + ret = at_recvfrom_lower(at._pstuart, (void *)&data, 1, &recv_size, timeout_ms); + HAL_MutexUnlock(at.at_uart_recv_mutex); + + if (ret != 0) { +#ifdef WORKAROUND_DEVELOPERBOARD_DMA_UART + if (ret == 1) { + HAL_UART_Deinit(at._pstuart); + at_init_uart(); + } +#endif + return -1; + } + + if (recv_size == 1) { + *c = data; + return 0; + } else { + return -1; + } +} + +int at_read(char *outbuf, int readsize) +{ + int ret = 0; + uint32_t recv_size, total_read = 0; + + if (inited == 0) { + atpsr_err("at have not init yet\r\n"); + return -1; + } + + HAL_MutexLock(at.at_uart_recv_mutex); + while (total_read < readsize) { + ret = at_recvfrom_lower(at._pstuart, (void *)(outbuf + total_read), + readsize - total_read, &recv_size, at._timeout); + if (ret != 0) { + atpsr_err("at_read failed on uart_recv."); + break; + } + + if (recv_size <= 0) { + continue; + } + total_read += recv_size; + if (total_read >= readsize) { + break; + } + } + HAL_MutexUnlock(at.at_uart_recv_mutex); + + if (ret != 0) { + return -1; + } + + return total_read; +} + +#define RECV_BUFFER_SIZE 512 +static char at_rx_buf[RECV_BUFFER_SIZE]; +int at_register_callback(const char *prefix, const char *postfix, char *recvbuf, + int bufsize, at_recv_cb cb, void *arg) +{ + oob_t *oob = NULL; + int i = 0; + + if (bufsize < 0 || bufsize >= RECV_BUFFER_SIZE || NULL == prefix) { + atpsr_err("%s invalid input \r\n", __func__); + return -1; + } + + if (NULL != postfix && (NULL == recvbuf || 0 == bufsize)) { + atpsr_err("%s invalid postfix input \r\n", __func__); + return -1; + } + + if (at._oobs_num >= OOB_MAX) { + atpsr_err("No place left in OOB.\r\n"); + return -1; + } + + /*check oob exist*/ + for (i = 0; i < at._oobs_num; i++) { + if (NULL != at._oobs[i].prefix && + strcmp(prefix, at._oobs[i].prefix) == 0) { + atpsr_warning("oob prefix %s is already exist.\r\n", prefix); + return -1; + } + } + + oob = &(at._oobs[at._oobs_num++]); + + oob->oobinputdata = recvbuf; + if (oob->oobinputdata != NULL) { + memset(oob->oobinputdata, 0, bufsize); + } + oob->maxlen = bufsize; + oob->prefix = (char *)prefix; + oob->postfix = (char *)postfix; + oob->cb = cb; + oob->arg = arg; + oob->reallen = 0; + + atpsr_debug("New oob registered (%s)", oob->prefix); + + return 0; +} + +static void at_scan_for_callback(char c, char *buf, int *index) +{ + int k; + oob_t *oob = NULL; + int offset = *index; + + if (!buf || offset < 0) { + return; + } + + for (k = 0; k < at._oobs_num; k++) { + oob = &(at._oobs[k]); + if (oob->reallen > 0 || + (offset >= strlen(oob->prefix) && + memcmp(oob->prefix, buf + offset - strlen(oob->prefix), + strlen(oob->prefix)) == 0)) { + atpsr_debug("AT! %s\r\n", oob->prefix); + if (oob->postfix == NULL) { + oob->cb(oob->arg, NULL, 0); + memset(buf, 0, offset); + offset = 0; + } else { + if (oob->reallen == 0) { + int len = strlen(oob->prefix) - 1; + len = len > 0 ? len : 0; + memset(oob->oobinputdata, 0, oob->maxlen); + memcpy(oob->oobinputdata, oob->prefix, len); + oob->reallen += len; + } + + if (oob->reallen < oob->maxlen) { + oob->oobinputdata[oob->reallen] = c; + oob->reallen++; + if ((oob->reallen >= + strlen(oob->prefix) + strlen(oob->postfix)) && + (strncmp(oob->oobinputdata + oob->reallen - + strlen(oob->postfix), + oob->postfix, + strlen(oob->postfix)) == 0)) { + /*recv postfix*/ + oob->cb(oob->arg, oob->oobinputdata, oob->reallen); + memset(oob->oobinputdata, 0, oob->reallen); + oob->reallen = 0; + memset(buf, 0, offset); + offset = 0; + } + } else { + atpsr_err("invalid oob %s input , for oversize %s \r\n", + oob->prefix, oob->oobinputdata); + memset(oob->oobinputdata, 0, oob->reallen); + oob->reallen = 0; + memset(buf, 0, offset); + offset = 0; + } + + /*oob data maybe more than buf size */ + if (offset > (RECV_BUFFER_SIZE - 2)) { + memset(buf, 0, offset); + offset = 0; + } + } + continue; + } + } + + *index = offset; + return; +} + +#if AT_SINGLE_TASK +int at_yield(char *replybuf, int bufsize, const atcmd_config_t *atcmdconfig, + int timeout_ms) +{ + int offset = 0; + int ret = 0; + int rsp_prefix_len = 0; + int rsp_success_postfix_len = 0; + int rsp_fail_postfix_len = 0; + int at_reply_begin = 0; + int at_reply_offset = 0; + char c = 0; + char *buf = NULL; + char *rsp_prefix = NULL; + char *rsp_success_postfix = NULL; + char *rsp_fail_postfix = NULL; + + if (!inited) { + atpsr_err("AT parser has not inited!\r\n"); + return -1; + } + + if (replybuf != NULL && bufsize <= 0) { + atpsr_err("buffer size %d unmatched!\r\n", bufsize); + return -1; + } + + buf = at_rx_buf; + if (NULL == buf) { + atpsr_err("AT worker fail to malloc ,task exist \r\n"); + return -1; + } + + memset(buf, 0, RECV_BUFFER_SIZE); + + while (true) { + /* read from uart and store buf */ + ret = at_getc(&c, timeout_ms); + if (ret != 0) { + atpsr_err("at yield timeout break loop"); + break; + } + + if (offset + 1 >= RECV_BUFFER_SIZE) { + atpsr_err("buffer full"); + break; + } + buf[offset++] = c; + buf[offset] = 0; + + at_scan_for_callback(c, buf, &offset); + + if (replybuf == NULL || bufsize <= 0) { + /* if no task, continue recv */ + continue; + } + + if (NULL != atcmdconfig && NULL != atcmdconfig->reply_prefix) { + rsp_prefix = atcmdconfig->reply_prefix; + rsp_prefix_len = strlen(rsp_prefix); + } else { + rsp_prefix = at._default_recv_prefix; + rsp_prefix_len = at._recv_prefix_len; + } + + if (NULL != atcmdconfig && NULL != atcmdconfig->reply_success_postfix) { + rsp_success_postfix = atcmdconfig->reply_success_postfix; + rsp_success_postfix_len = strlen(rsp_success_postfix); + } else { + rsp_success_postfix = at._default_recv_success_postfix; + rsp_success_postfix_len = at._recv_success_postfix_len; + } + + if (NULL != atcmdconfig && NULL != atcmdconfig->reply_fail_postfix) { + rsp_fail_postfix = atcmdconfig->reply_fail_postfix; + rsp_fail_postfix_len = strlen(rsp_fail_postfix); + } else { + rsp_fail_postfix = at._default_recv_fail_postfix; + rsp_fail_postfix_len = at._recv_fail_postfix_len; + } + + if (offset >= rsp_prefix_len && at_reply_begin == 0 && + (strncmp(buf + offset - rsp_prefix_len, rsp_prefix, + rsp_prefix_len) == 0)) { + at_reply_begin = 1; + } + + if (at_reply_begin == 1) { + if (at_reply_offset < bufsize) { + replybuf[at_reply_offset] = c; + at_reply_offset++; + + if ((at_reply_offset >= rsp_success_postfix_len && + strncmp( + replybuf + at_reply_offset - rsp_success_postfix_len, + rsp_success_postfix, rsp_success_postfix_len) == 0) || + (at_reply_offset >= rsp_fail_postfix_len && + strncmp(replybuf + at_reply_offset - rsp_fail_postfix_len, + rsp_fail_postfix, rsp_fail_postfix_len) == 0)) { + return 0; + } + } else { + memset(replybuf, 0, bufsize); + strcpy(replybuf, rsp_fail_postfix); + break; + } + } + + } + + return -1; +} +#else +static void* at_worker(void *arg) +{ + int offset = 0; + int ret = 0; + int at_task_empty = 0; + int at_task_reponse_begin = 0; + int memcpy_size = 0; + int rsp_prefix_len = 0; + int rsp_success_postfix_len = 0; + int rsp_fail_postfix_len = 0; + char c = 0; + at_task_t *tsk; + char *buf = NULL; + char *rsp_prefix = NULL; + char *rsp_success_postfix = NULL; + char *rsp_fail_postfix = NULL; + + atpsr_debug("at_work started."); + + buf = at_rx_buf; + if (NULL == buf) { + atpsr_err("AT worker fail to malloc ,task exist \r\n"); + return NULL; + } + + memset(buf, 0, RECV_BUFFER_SIZE); + inited = 1; + + while (true) { + ret = at_getc(&c, at._timeout); + if (ret != 0) { + continue; + } + + if (offset + 1 >= RECV_BUFFER_SIZE) { + atpsr_err("Fatal error, no one is handling AT uart"); + goto check_buffer; + } + buf[offset++] = c; + buf[offset] = 0; + + at_scan_for_callback(c, buf, &offset); + + HAL_MutexLock(at.task_mutex); + at_task_empty = slist_empty(&at.task_l); + + if (!at_task_empty) { + tsk = slist_first_entry(&at.task_l, at_task_t, next); + } + HAL_MutexUnlock(at.task_mutex); + + /* if no task, continue recv */ + if (at_task_empty) { + atpsr_debug("No task in queue"); + goto check_buffer; + } + + if (NULL != tsk->rsp_prefix && 0 != tsk->rsp_prefix_len) { + rsp_prefix = tsk->rsp_prefix; + rsp_prefix_len = tsk->rsp_prefix_len; + } else { + rsp_prefix = at._default_recv_prefix; + rsp_prefix_len = at._recv_prefix_len; + } + + if (NULL != tsk->rsp_success_postfix && + 0 != tsk->rsp_success_postfix_len) { + rsp_success_postfix = tsk->rsp_success_postfix; + rsp_success_postfix_len = tsk->rsp_success_postfix_len; + } else { + rsp_success_postfix = at._default_recv_success_postfix; + rsp_success_postfix_len = at._recv_success_postfix_len; + } + + if (NULL != tsk->rsp_fail_postfix && 0 != tsk->rsp_fail_postfix_len) { + rsp_fail_postfix = tsk->rsp_fail_postfix; + rsp_fail_postfix_len = tsk->rsp_fail_postfix_len; + } else { + rsp_fail_postfix = at._default_recv_fail_postfix; + rsp_fail_postfix_len = at._recv_fail_postfix_len; + } + + if (offset >= rsp_prefix_len && at_task_reponse_begin == 0 && + (strncmp(buf + offset - rsp_prefix_len, rsp_prefix, + rsp_prefix_len) == 0)) { + at_task_reponse_begin = 1; + } + + if (at_task_reponse_begin == 1) { + if (tsk->rsp_offset < tsk->rsp_len) { + tsk->rsp[tsk->rsp_offset] = c; + tsk->rsp_offset++; + + if ((tsk->rsp_offset >= rsp_success_postfix_len && + strncmp( + tsk->rsp + tsk->rsp_offset - rsp_success_postfix_len, + rsp_success_postfix, rsp_success_postfix_len) == 0) || + (tsk->rsp_offset >= rsp_fail_postfix_len && + strncmp(tsk->rsp + tsk->rsp_offset - rsp_fail_postfix_len, + rsp_fail_postfix, rsp_fail_postfix_len) == 0)) { + HAL_SemaphorePost(tsk->smpr); + at_task_reponse_begin = 0; + memset(buf, 0, offset); + offset = 0; + } + } else { + memset(tsk->rsp, 0, tsk->rsp_len); + strcpy(tsk->rsp, rsp_fail_postfix); + HAL_SemaphorePost(tsk->smpr); + at_task_reponse_begin = 0; + memset(buf, 0, offset); + offset = 0; + } + } + check_buffer: + /* in case buffer is full */ + if (offset > (RECV_BUFFER_SIZE - 2)) { + memcpy_size = rsp_prefix_len > rsp_success_postfix_len + ? rsp_prefix_len + : rsp_success_postfix_len; + memcpy_size = memcpy_size > rsp_fail_postfix_len + ? memcpy_size + : rsp_fail_postfix_len; + memcpy(buf, buf + offset - memcpy_size, memcpy_size); + memset(buf + memcpy_size, 0, offset - memcpy_size); + offset = memcpy_size; + } + } + + return NULL; +} +#endif diff --git a/iotkit-embedded/src/atm/at_parser.h b/iotkit-embedded/src/atm/at_parser.h new file mode 100644 index 0000000..1d2eb16 --- /dev/null +++ b/iotkit-embedded/src/atm/at_parser.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#ifndef _AT_PARSER_H_ +#define _AT_PARSER_H_ + +#include "infra_config.h" + +/* uart config */ +#define AT_UART_PORT 1 +#define AT_UART_LINUX_DEV "/dev/ttyUSB0" +#define AT_UART_BAUDRATE 115200 +#define AT_UART_DATA_WIDTH DATA_WIDTH_8BIT +#define AT_UART_PARITY NO_PARITY +#define AT_UART_STOP_BITS STOP_BITS_1 +#define AT_UART_FLOW_CONTROL FLOW_CONTROL_DISABLED +#define AT_UART_MODE MODE_TX_RX +#define AT_UART_TIMEOUT_MS 1000 + +/* Delimiter */ +#define AT_RECV_PREFIX "\r\n" +#define AT_RECV_SUCCESS_POSTFIX "OK\r\n" +#define AT_RECV_FAIL_POSTFIX "ERROR\r\n" +#define AT_SEND_DELIMITER "\r" + +#if defined(AT_TCP_HAL_SIM800) +#define AT_CMD_DATA_INTERVAL_MS 50 +#endif + +#ifdef PLATFORM_HAS_OS +#define AT_SINGLE_TASK 0 +#else +#define AT_SINGLE_TASK 1 +#endif + +#ifndef bool +#define bool unsigned char +#endif + +#ifndef true +#define true 1 +#endif +#ifndef false +#define false 0 +#endif + +typedef struct { + char *reply_prefix; + char *reply_success_postfix; + char *reply_fail_postfix; +} atcmd_config_t; + +typedef void (*at_recv_cb)(void *arg, char *buf, int buflen); + +/** + * initialization + * Configuration (e.g. AT_UART_PORT, UART_BAUDRATE) can be found + * in above macro + */ +int at_parser_init(void); + +/** + * at send (format: command + delimiter + data) and wait reply + * + * @param cmd at command sending buf. MUST not be NULL. + * @param cmdlen at command length. + * @param delimiter whether sending delimiter, usually value is true + * @param data data sending buf. NULL if no data. + * @param datalen data length. Zero if no data. + * @param replybuf reply buffer. MUST not be NULL. + * @param bufsize reply buffer size + * @param atcmdconfig AT cmd reply format config. Use default if NULL + */ +int at_send_wait_reply(const char *cmd, int cmdlen, bool delimiter, + const char *data, int datalen, + char *replybuf, int bufsize, + const atcmd_config_t *atcmdconfig); + +/** + * at send (format: data + delimiter) and does not wait reply + * + * @param data sending buffer. + * @param datalen sending length. + * @param delimiter whether sending delimiter, usually value is false + */ +int at_send_no_reply(const char *data, int datalen, bool delimiter); + + +/** + * at read for certain bytes of data + * + * @param outbuf output buffer. + * @param readsize read size. + */ +int at_read(char *outbuf, int readsize); + + +/** + * at register callback for recv + * + * @param prefix interested string. Must not be NULL. + * @param postfix intersted postfix. NULL if postfix not provided. + * @param recvbuf recv data buffer provided by caller, NULL if postfix not provided + * @param bufsize buffer size for recv data, zero if postfix not provided + * @param cb callback handle function. Must not be NULL. + * @param arg callback handle function args. NULL if not used. + */ +int at_register_callback(const char *prefix, const char *postfix, char *recvbuf, + int bufsize, at_recv_cb cb, void *arg); + + +/** + * at yield receive function. Only used in single task scenario + * + * @param replybuf reply buffer. + * @param bufsize reply buffer size. + * @param atcmdconfig AT cmd reply format config. Use default if NULL + * @param timeout_ms receive timeout in millisecond + */ +int at_yield(char *replybuf, int bufsize, const atcmd_config_t *atcmdconfig, + int timeout_ms); +#endif + + diff --git a/iotkit-embedded/src/atm/at_tcp.c b/iotkit-embedded/src/atm/at_tcp.c new file mode 100644 index 0000000..fbece6e --- /dev/null +++ b/iotkit-embedded/src/atm/at_tcp.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include + +#include "infra_types.h" +#include "infra_config.h" + +#include "at_conn_mgmt.h" + +#include "at_wrapper.h" + +#ifdef AT_PARSER_ENABLED +#include "at_parser.h" +#endif + +static uint64_t _get_time_ms(void) +{ + return HAL_UptimeMs(); +} + +static uint64_t _time_left(uint64_t t_end, uint64_t t_now) +{ + uint64_t t_left; + + if (t_end > t_now) { + t_left = t_end - t_now; + } else { + t_left = 0; + } + + return t_left; +} + +uintptr_t AT_TCP_Establish(const char *host, uint16_t port) +{ + int fd = 0; + int rc = 0; + char resultip[16]; + + HAL_Printf("establish tcp connection with server(host='%s', port=[%u])\n", host, port); + + if ((rc = at_conn_getaddrinfo(host, resultip)) != 0) { + HAL_Printf("getaddrinfo error(%d), host = '%s', port = [%d]\n", rc, host, port); + return (uintptr_t)(-1); + } + + fd = at_conn_setup(NETCONN_TCP); + if (fd < 0) { + HAL_Printf("create at conn error\n"); + return (uintptr_t)(-1); + } + + if (at_conn_start(fd, resultip, port) == 0) { + rc = fd; + } else { + at_conn_close(fd); + HAL_Printf("connect error\n"); + rc = -1; + } + + if (-1 == rc) { + HAL_Printf("fail to establish tcp\n"); + } else { + HAL_Printf("success to establish tcp, fd=%d\n", rc); + } + + return (uintptr_t)rc; +} + +int AT_TCP_Destroy(uintptr_t fd) +{ + int rc; + + rc = at_conn_close((int) fd); + if (0 != rc) { + HAL_Printf("closesocket error\n"); + return -1; + } + + return 0; +} + +int32_t AT_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms) +{ + int ret; + uint32_t len_sent; + uint64_t t_end; + int net_err = 0; + + t_end = _get_time_ms() + timeout_ms; + len_sent = 0; + ret = 1; /* send one time if timeout_ms is value 0 */ + + do { + ret = at_conn_send(fd, buf + len_sent, len - len_sent); + if (ret > 0) { + len_sent += ret; + } else if (0 == ret) { + HAL_Printf("No data be sent\n"); + } else { + HAL_Printf("send fail, ret = send() = %d\n", ret); + net_err = 1; + break; + } + } while (!net_err && (len_sent < len) && (_time_left(t_end, _get_time_ms()) > 0)); + + if (net_err) { + return -1; + } else { + return len_sent; + } +} + +int32_t AT_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms) +{ + int ret, err_code; + uint32_t len_recv; + uint64_t t_end, t_left; + int empty; + + t_end = _get_time_ms() + timeout_ms; + len_recv = 0; + err_code = 0; + + do { + t_left = _time_left(t_end, _get_time_ms()); + if (0 == t_left) { + break; + } + + while(1) { +#ifdef AT_PARSER_ENABLED +#if AT_SINGLE_TASK + at_yield(NULL, 0, NULL, 100); +#endif +#endif + empty = at_conn_recvbufempty(fd); + if (0 == empty) { + ret = 1; + break; + } else if (empty < 0) { + ret = -1; + } + + t_left = _time_left(t_end, _get_time_ms()); + if (0 == t_left) { + ret = 0; + break; + } + + HAL_SleepMs(10); + } + + if (ret > 0) { + ret = at_conn_recv(fd, buf + len_recv, len - len_recv); + if (ret > 0) { + len_recv += ret; + } else if (0 == ret) { + HAL_Printf("connection is closed\n"); + err_code = -1; + break; + } else { + HAL_Printf("recv fail\n"); + err_code = -2; + break; + } + } else if (0 == ret) { + break; + } else { + HAL_Printf("select-recv fail\n"); + err_code = -2; + break; + } + } while ((len_recv < len)); + + /* priority to return data bytes if any data be received from TCP connection. */ + /* It will get error code on next calling */ + return (0 != len_recv) ? len_recv : err_code; +} + diff --git a/iotkit-embedded/src/atm/at_wrapper.h b/iotkit-embedded/src/atm/at_wrapper.h new file mode 100644 index 0000000..9a35029 --- /dev/null +++ b/iotkit-embedded/src/atm/at_wrapper.h @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#ifndef _AT_WRAPPER_H_ +#define _AT_WRAPPER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include + +#include "infra_config.h" +#include "wrappers_defs.h" + +#ifndef NULL +#define NULL (void *)0 +#endif + +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_MutexCreate(void); +void HAL_MutexDestroy(void *mutex); +void HAL_MutexLock(void *mutex); +void HAL_MutexUnlock(void *mutex); +void HAL_SleepMs(uint32_t ms); + +#ifdef PLATFORM_HAS_OS +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_ThreadCreate( + void **thread_handle, + void *(*work_routine)(void *), + void *arg, + hal_os_thread_param_t *hal_os_thread_param, + int *stack_used); +#endif + +#define HAL_WAIT_FOREVER 0xFFFFFFFFU + + +#if defined(AT_PARSER_ENABLED) +/* + * UART data width + */ +typedef enum { + DATA_WIDTH_5BIT, + DATA_WIDTH_6BIT, + DATA_WIDTH_7BIT, + DATA_WIDTH_8BIT, + DATA_WIDTH_9BIT +} hal_uart_data_width_t; + +/* + * UART stop bits + */ +typedef enum { + STOP_BITS_1, + STOP_BITS_2 +} hal_uart_stop_bits_t; + +/* + * UART flow control + */ +typedef enum { + FLOW_CONTROL_DISABLED, + FLOW_CONTROL_CTS, + FLOW_CONTROL_RTS, + FLOW_CONTROL_CTS_RTS +} hal_uart_flow_control_t; + +/* + * UART parity + */ +typedef enum { + NO_PARITY, + ODD_PARITY, + EVEN_PARITY +} hal_uart_parity_t; + +/* + * UART mode + */ +typedef enum { + MODE_TX, + MODE_RX, + MODE_TX_RX +} hal_uart_mode_t; + +/* + * UART configuration + */ +typedef struct { + uint32_t baud_rate; + hal_uart_data_width_t data_width; + hal_uart_parity_t parity; + hal_uart_stop_bits_t stop_bits; + hal_uart_flow_control_t flow_control; + hal_uart_mode_t mode; +} uart_config_t; + +typedef struct { + uint8_t port; /* uart port */ + uart_config_t config; /* uart config */ + void *priv; /* priv data */ +} uart_dev_t; + +/** + * Initialises a UART interface + * + * + * @param[in] uart the interface which should be initialised + * + * @return 0 : on success, EIO : if an error occurred with any step + */ +int32_t HAL_AT_Uart_Init(uart_dev_t *uart); + +/** + * Deinitialises a UART interface + * + * @param[in] uart the interface which should be deinitialised + * + * @return 0 : on success, EIO : if an error occurred with any step + */ +int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart); + +/** + * Transmit data on a UART interface + * + * @param[in] uart the UART interface + * @param[in] data pointer to the start of data + * @param[in] size number of bytes to transmit + * @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER + * if you want to wait forever + * + * @return 0 : on success, EIO : if an error occurred with any step + */ +int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout); + +/** + * Receive data on a UART interface + * + * @param[in] uart the UART interface + * @param[out] data pointer to the buffer which will store incoming data + * @param[in] expect_size number of bytes to receive + * @param[out] recv_size number of bytes received + * @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER + * if you want to wait forever + * + * @return 0 : on success, EIO : if an error occurred with any step + */ +int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size, + uint32_t *recv_size, uint32_t timeout); +#endif + +#if defined(AT_TCP_ENABLED) +typedef enum { + /* WiFi */ + TCP_SERVER, + TCP_CLIENT, + SSL_CLIENT, + UDP_BROADCAST, + UDP_UNICAST, + /*WiFi end */ + /* Add others hereafter */ +} CONN_TYPE; + +/* Fill necessary fileds according to the socket type. */ +typedef struct { + int fd; /* fd that are used in socket level */ + CONN_TYPE type; + char *addr; /* remote ip or domain */ + int32_t r_port; /* remote port (set to -1 if not used) */ + int32_t l_port; /* local port (set to -1 if not used) */ + uint32_t tcp_keep_alive; /* tcp keep alive value (set to 0 if not used) */ +} at_conn_t; + +struct at_conn_input { + int fd; + void *data; + uint32_t datalen; + char *remote_ip; + uint16_t remote_port; +}; + +/** + * Module low level init so that it's ready to setup socket connection. + * + * @return 0 - success, -1 - failure + */ +int HAL_AT_CONN_Init(void); + + +/** + * Start a socket connection via module. + * + * @param[in] conn - connect parameters which are used to setup + * the socket connection. + * + * @return 0 - success, -1 - failure + */ +int HAL_AT_CONN_Start(at_conn_t *conn); + + +/** + * Send data via module. + * This function does not return until all data sent. + * + * @param[in] fd - the file descripter to operate on. + * @param[in] data - pointer to data to send. + * @param[in] len - length of the data. + * @param[in] remote_ip - remote port number (optional). + * @param[in] remote_port - remote port number (optional). + * + * @return 0 - success, -1 - failure + */ +int HAL_AT_CONN_Send(int fd, uint8_t *data, uint32_t len, char remote_ip[16], + int32_t remote_port, int32_t timeout); + + +/** + * Get IP information of the corresponding domain. + * Currently only one IP string is returned (even when the domain + * coresponses to mutliple IPs). Note: only IPv4 is supported. + * + * @param[in] domain - the domain string. + * @param[out] ip - the place to hold the dot-formatted ip string. + * + * @return 0 - success, -1 - failure + */ +int HAL_AT_CONN_DomainToIp(char *domain, char ip[16]); + + +/** + * Close the socket connection. + * + * @param[in] fd - the file descripter to operate on. + * @param[in] remote_port - remote port number (optional). + * + * @return 0 - success, -1 - failure + */ +int HAL_AT_CONN_Close(int fd, int32_t remote_port); + + +/** + * Destroy SAL or exit low level state if necessary. + * + * @return 0 - success, -1 - failure + */ +int HAL_AT_CONN_Deinit(void); + +#elif defined(AT_MQTT_ENABLED) +#include "mqtt_api.h" + +struct at_mqtt_input { + char *topic; + uint32_t topic_len; + char *message; + uint32_t msg_len; +}; + +int HAL_AT_MQTT_Init(iotx_mqtt_param_t *pInitParams); +int HAL_AT_MQTT_Deinit(void); +int HAL_AT_MQTT_Connect(char *proKey, char *devName, char *devSecret); +int HAL_AT_MQTT_Disconnect(void); +int HAL_AT_MQTT_Subscribe(const char *topic, int qos, unsigned int *mqtt_packet_id, int *mqtt_status, int timeout_ms); +int HAL_AT_MQTT_Unsubscribe(const char *topic, unsigned int *mqtt_packet_id, int *mqtt_status); +int HAL_AT_MQTT_Publish(const char *topic, int qos, const char *message, unsigned int msg_len); +int HAL_AT_MQTT_State(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/iotkit-embedded/src/atm/iot.mk b/iotkit-embedded/src/atm/iot.mk new file mode 100644 index 0000000..0e3647e --- /dev/null +++ b/iotkit-embedded/src/atm/iot.mk @@ -0,0 +1,19 @@ +LIBA_TARGET := libiot_at.a + +HDR_REFS := src/infra + +ifneq (,$(filter -DATM_ENABLED, $(CFLAGS))) +LIB_SRCS_PATTERN += at_api.c + +ifneq (,$(filter -DAT_TCP_ENABLED, $(CFLAGS))) +LIB_SRCS_PATTERN += at_conn_mbox.c at_conn_mgmt.c at_tcp.c +endif + +ifneq (,$(filter -DAT_MQTT_ENABLED, $(CFLAGS))) +LIB_SRCS_PATTERN += at_mqtt.c +endif + +ifneq (,$(filter -DAT_PARSER_ENABLED, $(CFLAGS))) +LIB_SRCS_PATTERN += at_parser.c +endif +endif diff --git a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_cloud_conn.h b/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_cloud_conn.h deleted file mode 100644 index 265bd40..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_cloud_conn.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifdef CMP_VIA_CLOUN_CONN - -#ifndef __CMP_VIA_CLOUD_CONN_H__ -#define __CMP_VIA_CLOUD_CONN_H__ - -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iot_export.h" -#include "iotx_cmp_common.h" - - -int iotx_cmp_cloud_conn_disconnect_handler(iotx_cmp_conntext_pt cmp_pt); -int iotx_cmp_cloud_conn_reconnect_handler(iotx_cmp_conntext_pt cmp_pt); -int iotx_cmp_cloud_conn_register_handler(iotx_cmp_conntext_pt cmp_pt, - char* URI, int result, int is_register); -int iotx_cmp_cloud_conn_response_handler(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_message_info_pt message_info); - -void* iotx_cmp_cloud_conn_init(void* handler, iotx_cmp_init_param_pt pparam); -int iotx_cmp_cloud_conn_register(void* handler, void* connectivity_pt, const char* topic_filter); -int iotx_cmp_cloud_conn_unregister(void* handler, void* connectivity_pt, const char* topic_filter); -int iotx_cmp_cloud_conn_send(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length); -int iotx_cmp_cloud_conn_send_sync(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length); -int iotx_cmp_cloud_conn_yield(void* connectivity_pt, int timeout_ms); -int iotx_cmp_cloud_conn_deinit(void* connectivity_pt); - -#endif /* __CMP_VIA_CLOUD_CONN_H__ */ -#endif - diff --git a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_common.h b/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_common.h deleted file mode 100644 index 7aa7343..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_common.h +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __SRC_CMP_COMMON_H__ -#define __SRC_CMP_COMMON_H__ - -#include "iot_export_cmp.h" - -#ifdef CMP_SUPPORT_MULTI_THREAD -#ifdef CMP_SUPPORT_MULTI_THREAD_VIA_HAL -#include "iot_import.h" -#else -/* multi-thread */ -#include -#endif -#endif - - -#ifdef CMP_SUPPORT_MEMORY_MAGIC -#define CMP_malloc(size) LITE_malloc(size, MEM_MAGIC, "CMP") -#else -#define CMP_malloc(size) LITE_malloc(size) -#endif - - -#ifdef ESP8266 -#include "esp_common.h" -#define CMP_READ_ONLY ICACHE_RODATA_ATTR STORE_ATTR -#else -#define CMP_READ_ONLY -#endif - -#define CMP_INFO(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_INFO_LEVEL, __VA_ARGS__) -#define CMP_WARNING(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_WARNING_LEVEL, __VA_ARGS__) -#define CMP_ERR(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_ERR_LEVEL, __VA_ARGS__) - - -#ifdef CMP_SUPPORT_TOPIC_DISPATCH -#define CMP_MAPPING_USE_POOL -#define CMP_SUPPORT_MAX_MAPPING_SIZE (20) -#endif - -#ifdef CMP_SUPPORT_MULTI_THREAD - -#define CMP_PROCESS_NODE_USE_POOL -#define CMP_SUPPORT_MAX_PROCESS_NODE_SIZE (30) -#endif - - -/* text for log */ -/* error */ -extern const char cmp_log_error_parameter[] CMP_READ_ONLY; -extern const char cmp_log_error_param_1[] CMP_READ_ONLY; -extern const char cmp_log_error_auth[] CMP_READ_ONLY; -extern const char cmp_log_error_memory[] CMP_READ_ONLY; -extern const char cmp_log_error_fail[] CMP_READ_ONLY; -extern const char cmp_log_error_fail_ota[] CMP_READ_ONLY; -extern const char cmp_log_error_fail_1[] CMP_READ_ONLY; -extern const char cmp_log_error_fail_rc[] CMP_READ_ONLY; -extern const char cmp_log_error_status[] CMP_READ_ONLY; -extern const char cmp_log_error_splice_URI[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_URI[] CMP_READ_ONLY; -extern const char cmp_log_error_splice_payload[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_payload[] CMP_READ_ONLY; -extern const char cmp_log_error_get_node[] CMP_READ_ONLY; -extern const char cmp_log_error_push_node[] CMP_READ_ONLY; -extern const char cmp_log_error_process[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_id[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_code[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_data[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_params[] CMP_READ_ONLY; -extern const char cmp_log_error_parse_method[] CMP_READ_ONLY; -extern const char cmp_log_error_type[] CMP_READ_ONLY; -extern const char cmp_log_error_pk[] CMP_READ_ONLY; -extern const char cmp_log_error_dn[] CMP_READ_ONLY; -extern const char cmp_log_error_di[] CMP_READ_ONLY; -extern const char cmp_log_error_secret_1[] CMP_READ_ONLY; -extern const char cmp_log_error_secret_2[] CMP_READ_ONLY; -extern const char cmp_log_error_ret_code[] CMP_READ_ONLY; - -/* warning */ -extern const char cmp_log_warning_ota_started[] CMP_READ_ONLY; -extern const char cmp_log_warning_cloud_disconnected[] CMP_READ_ONLY; -extern const char cmp_log_warning_not_support[] CMP_READ_ONLY; -extern const char cmp_log_warning_not_arrived[] CMP_READ_ONLY; -extern const char cmp_log_warning_not_mapping[] CMP_READ_ONLY; -extern const char cmp_log_warning_not_func[] CMP_READ_ONLY; -extern const char cmp_log_warning_no_list[] CMP_READ_ONLY; -extern const char cmp_log_warning_buffer_overflow[] CMP_READ_ONLY; - -/* info */ -extern const char cmp_log_info_init[] CMP_READ_ONLY; -extern const char cmp_log_info_registered[] CMP_READ_ONLY; -extern const char cmp_log_info_event_id[] CMP_READ_ONLY; -extern const char cmp_log_info_event_type[] CMP_READ_ONLY; -extern const char cmp_log_info_rsp_type[] CMP_READ_ONLY; -extern const char cmp_log_info_cloud_disconnect[] CMP_READ_ONLY; -extern const char cmp_log_info_cloud_reconnect[] CMP_READ_ONLY; -extern const char cmp_log_info_result[] CMP_READ_ONLY; -extern const char cmp_log_info_URI[] CMP_READ_ONLY; -extern const char cmp_log_info_URI_1[] CMP_READ_ONLY; -extern const char cmp_log_info_URI_sys[] CMP_READ_ONLY; -extern const char cmp_log_info_URI_ext[] CMP_READ_ONLY; -extern const char cmp_log_info_URI_undefined[] CMP_READ_ONLY; -extern const char cmp_log_info_URI_length[] CMP_READ_ONLY; -extern const char cmp_log_info_payload_length[] CMP_READ_ONLY; -extern const char cmp_log_info_firmware[] CMP_READ_ONLY; -extern const char cmp_log_info_MQTT_disconnect[] CMP_READ_ONLY; -extern const char cmp_log_info_MQTT_reconnect[] CMP_READ_ONLY; -extern const char cmp_log_info_remove_mapping[] CMP_READ_ONLY; -extern const char cmp_log_info_enter_process_1[] CMP_READ_ONLY; -extern const char cmp_log_info_enter_process_2[] CMP_READ_ONLY; -extern const char cmp_log_info_process_type[] CMP_READ_ONLY; -extern const char cmp_log_info_raw_data[] CMP_READ_ONLY; -extern const char cmp_log_info_auth_req[] CMP_READ_ONLY; -extern const char cmp_log_info_auth_rsp[] CMP_READ_ONLY; -extern const char cmp_log_info_auth_payload_req[] CMP_READ_ONLY; -extern const char cmp_log_info_auth_payload_rsp[] CMP_READ_ONLY; - - -/* The structure of cmp event msg */ -typedef struct { - char *URI; - void *payload; - unsigned int payload_length; -} iotx_cmp_response_info_t, *iotx_cmp_response_info_pt; - -typedef void (*iotx_cmp_response_func_fpt)(void* pcontext, iotx_cmp_message_info_pt msg_info); - - -/* The structure of cloud connection context */ -typedef struct iotx_cmp_mapping_st { - void *next; - char *URI; -#ifdef CMP_MAPPING_USE_POOL - int is_used; -#endif - iotx_cmp_message_types_t type; - iotx_cmp_register_func_fpt func; - void *user_data; - void *mail_box; -} iotx_cmp_mapping_t, *iotx_cmp_mapping_pt; - -#ifdef CMP_SUPPORT_MULTI_THREAD - -typedef enum { - /* cloud process */ - IOTX_CMP_PROCESS_TYPE_CLOUD = 1, - -#ifdef CMP_SUPPORT_LOCAL_CONN_CONN - /* cloud process */ - IOTX_CMP_PROCESS_TYPE_LOCAL = 2, -#endif - - IOTX_CMP_PROCESS_TYPE_MAX -}iotx_cmp_process_types_t; - - -typedef enum { - /* register */ - /* msg is iotx_cmp_process_register_pt */ - IOTX_CMP_PROCESS_CLOUD_REGISTER = 0, - - /* register result */ - /* msg is iotx_cmp_process_register_result_pt */ - IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT, - - /* unregister */ - /* msg is URI */ - IOTX_CMP_PROCESS_CLOUD_UNREGISTER, - - /* unregister result */ - /* msg is iotx_cmp_process_register_result_pt */ - IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT, - - /* send */ - /* msg is iotx_cmp_process_send_pt */ - IOTX_CMP_PROCESS_CLOUD_SEND, - - /* new data */ - /* msg is iotx_mqtt_topic_info_pt or iotx_cloud_connection_msg_rsp_pt */ - IOTX_CMP_PROCESS_CLOUD_NEW_DATA, - - /* cloud disconnect */ - /* msg is null*/ - IOTX_CMP_PROCESS_CLOUD_DISCONNECT, - - /* cloud reconnect */ - /* msg is null*/ - IOTX_CMP_PROCESS_CLOUD_RECONNECT, - - IOTX_CMP_PROCESS_CLOUD_MAX, - - -#ifdef CMP_SUPPORT_LOCAL_CONN_CONN - /* local add device */ - /* todo */ - IOTX_CMP_PROCESS_LOCAL_ADD_DEVICE = IOTX_CMP_PROCESS_CLOUD_MAX + 1, - - /* local remoce device */ - /* todo */ - IOTX_CMP_PROCESS_LOCAL_REMOVE_DEVICE, - - /* register */ - /* msg is iotx_cmp_process_register_pt */ - IOTX_CMP_PROCESS_LOCAL_ADD_SERVICE, - - /* register result */ - /* msg is iotx_cmp_process_register_result_pt */ - IOTX_CMP_PROCESS_LOCAL_ADD_SERVICE_RESULT, - - /* unregister */ - /* msg is URI */ - IOTX_CMP_PROCESS_LOCAL_REMOVE_SERVICE, - - /* unregister result */ - /* msg is iotx_cmp_process_register_result_pt */ - IOTX_CMP_PROCESS_LOCAL_REMOVE_SERVICE_RESULT, - - /* send */ - /* msg is iotx_cmp_process_send_pt */ - IOTX_CMP_PROCESS_LOCAL_SEND, - - /* new data */ - /* msg is iotx_mqtt_topic_info_pt or iotx_cloud_connection_msg_rsp_pt */ - IOTX_CMP_PROCESS_LOCAL_NEW_DATA, - - /* local disconnect */ - /* msg is null*/ - IOTX_CMP_PROCESS_LOCAL_DISCONNECT, - - /* local reconnect */ - /* msg is null*/ - IOTX_CMP_PROCESS_LOCAL_RECONNECT, - -#endif - IOTX_CMP_PROCESS_LOCAL_MAX, - - IOTX_CMP_PROCESS_MAX = 100 -}iotx_cmp_process_node_types_t; - - -typedef struct iotx_cmp_process_register_st { - char* URI; - iotx_cmp_message_types_t type; - iotx_cmp_register_func_fpt register_func; - void *user_data; - void *mail_box; -} iotx_cmp_process_register_t, *iotx_cmp_process_register_pt; - -typedef struct iotx_cmp_process_send_st { - iotx_cmp_send_peer_pt target; - iotx_cmp_message_ack_types_t ack_type; - char* URI; - void* payload; - int payload_length; -} iotx_cmp_process_send_t, *iotx_cmp_process_send_pt; - -typedef struct iotx_cmp_process_register_result_st { - char* URI; - /* 0: success, -1:fail */ - int result; - int is_register; -} iotx_cmp_process_register_result_t, *iotx_cmp_process_register_result_pt; - -typedef struct iotx_cmp_process_list_node_st { - void *next; - void *pre; -#ifdef CMP_PROCESS_NODE_USE_POOL - int is_used; -#endif - iotx_cmp_process_node_types_t type; - void* msg; -} iotx_cmp_process_list_node_t, *iotx_cmp_process_list_node_pt; - -typedef struct iotx_cmp_process_list_st { - iotx_cmp_process_list_node_pt header; - iotx_cmp_process_list_node_pt tailer; - int size; -} iotx_cmp_process_list_t, *iotx_cmp_process_list_pt; - -#endif - -typedef void* (*_init_function)(void* handler, iotx_cmp_init_param_pt pparam); -typedef int (*_connect_function)(void* handler, void* connectivity_pt); -typedef int (*_register_function)(void* handler, void* connectivity_pt, const char* topic_filter); -typedef int (*_unregister_function)(void* handler, void* connectivity_pt, const char* topic_filter); -typedef int (*_send_function)(void* handler, void* connectivity_pt, const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, const void* payload, int payload_length); -typedef int (*_send_sync_function)(void* handler, void* connectivity_pt, const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, const void* payload, int payload_length); -typedef int (*_yield_function)(void* connectivity_pt, int timeout_ms); -typedef int (*_deinit_function)(void* connectivity_pt); - -typedef struct iotx_cmp_connectivity_st { - void* context; - uint8_t is_connected; - _init_function init_func; - _connect_function connect_func; - _register_function register_func; - _unregister_function unregister_func; - _send_function send_func; - _send_sync_function send_sync_func; - _yield_function yield_func; - _deinit_function deinit_func; -} iotx_cmp_connectivity_t, *iotx_cmp_connectivity_pt; - -typedef struct iotx_cmp_connectivity_list_st { - iotx_cmp_connectivity_pt node; - void* next; -} iotx_cmp_connectivity_list_t, *iotx_cmp_connectivity_list_pt; - - -typedef struct iotx_cmp_event_callback_node_st { - iotx_cmp_event_handle_func_fpt event_func; - void *user_data; -}iotx_cmp_event_callback_node_t, *iotx_cmp_event_callback_node_pt; - - -typedef struct iotx_cmp_event_callback_list_st { - iotx_cmp_event_callback_node_pt node; - void* next; -}iotx_cmp_event_callback_list_t, *iotx_cmp_event_callback_list_pt; - -typedef struct iotx_cmp_conntext_st{ -#ifdef CMP_SUPPORT_MULTI_THREAD -#ifdef CMP_SUPPORT_MULTI_THREAD_VIA_HAL - void* pthread_yield; - void* pthread_process; -#else - pthread_t pthread_yield; - pthread_t pthread_process; -#endif - iotx_cmp_process_list_pt process_cloud_list; - void* process_cloud_lock; -#ifdef CMP_SUPPORT_LOCAL_CONN - iotx_cmp_process_list_pt process_local_list; - void* process_local_lock; -#endif - uint8_t thread_stop; - uint8_t thread_is_stoped; -#endif - uint8_t is_connect; - uint64_t cmp_message_id; - iotx_cmp_connectivity_list_pt connectivity_list; - iotx_cmp_mapping_pt mapping_list; - iotx_cmp_response_func_fpt response_func; - iotx_cmp_event_callback_list_pt event_callback_list; -#ifdef SERVICE_OTA_ENABLED - void* ota_handler; - iotx_cmp_fota_handle_func_fpt fota_func; - void *fota_user_context; - iotx_cmp_cota_handle_func_fpt cota_func; - void *cota_user_context; -#endif /* SERVICE_OTA_ENABLED */ -} iotx_cmp_conntext_t, *iotx_cmp_conntext_pt; - -int iotx_cmp_auth(const char *product_key, const char *device_name, const char *client_id); - -void iotx_cmp_free_message_info(iotx_cmp_message_info_pt message_info); - -void iotx_cmp_response_func(void* pcontext, iotx_cmp_message_info_pt message_info); - -int iotx_cmp_parse_payload(void* payload, - int payload_length, - iotx_cmp_message_info_pt msg); - -int iotx_cmp_splice_payload(void* payload, - int* payload_length, - int id, - iotx_cmp_message_info_pt msg); - -int iotx_cmp_parse_URI(char* URI, - int URI_length, - char* URI_param, - iotx_cmp_uri_types_t* uri_type); - -int iotx_cmp_splice_URI(char* URI, - int* URI_length, - const char* URI_param, - iotx_cmp_uri_types_t uri_type); - -int iotx_cmp_add_connectivity(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_connectivity_pt connectivity); - -int iotx_cmp_add_connectivity_all(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_init_param_pt pparam); - -int iotx_cmp_remove_connectivity_all(iotx_cmp_conntext_pt cmp_pt); - -iotx_cmp_mapping_pt iotx_cmp_get_mapping_node(); - -int iotx_cmp_free_mapping_node(iotx_cmp_mapping_pt node); - -int iotx_cmp_add_mapping(iotx_cmp_conntext_pt cmp_pt, - char* URI, - iotx_cmp_message_types_t type, - iotx_cmp_register_func_fpt func, - void* user_data, - void* mail_box); - -int iotx_cmp_remove_mapping(iotx_cmp_conntext_pt cmp_pt, char* URI); - -int iotx_cmp_remove_mapping_all(iotx_cmp_conntext_pt cmp_pt); - -iotx_cmp_mapping_pt iotx_cmp_find_mapping(iotx_cmp_conntext_pt cmp_pt, char* URI, int URI_length); - -int iotx_cmp_register_service(iotx_cmp_conntext_pt cmp_pt, - char* URI, - iotx_cmp_message_types_t type, - iotx_cmp_register_func_fpt register_func, - void* user_data, - void* mail_box); - -int iotx_cmp_unregister_service(iotx_cmp_conntext_pt cmp_pt, char* URI); - -int iotx_cmp_parse_message(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_message_info_pt message_info, - char** URI, - void** payload, - int* payload_length); - -int iotx_cmp_send_data(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_send_peer_pt target, - char* URI, - iotx_cmp_message_ack_types_t ack_type, - void* payload, - int payload_length); - -int iotx_cmp_trigger_event_callback(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_event_msg_pt msg); - -#ifdef CMP_SUPPORT_MULTI_THREAD -iotx_cmp_process_list_node_pt iotx_cmp_get_list_node(iotx_cmp_process_types_t type); -int iotx_cmp_free_list_node(iotx_cmp_process_list_node_pt node); -int iotx_cmp_free_list_node_all(iotx_cmp_conntext_pt cmp_pt); - -/* node is in */ -int iotx_cmp_process_list_push(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_process_types_t type, - iotx_cmp_process_list_node_pt node); - -/* node is out */ -iotx_cmp_process_list_node_pt iotx_cmp_process_list_pop(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_process_types_t type); - -int iotx_cmp_process_list_get_size(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_process_types_t type); - -void* iotx_cmp_cloud_process(void *pclient); - -#ifdef CMP_SUPPORT_LOCAL_CONN -void* iotx_cmp_local_process(void *pclient); -#endif - -#endif - -#endif /* __SRC_CMP_COMMON_H__ */ - - diff --git a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_mqtt_direct.h b/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_mqtt_direct.h deleted file mode 100644 index 79383ee..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_mqtt_direct.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __CMP_VIA_MQTT_DIRECT_H__ -#define __CMP_VIA_MQTT_DIRECT_H__ - -#ifdef CMP_VIA_MQTT_DIRECT - -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iot_export.h" -#include "iotx_cmp_common.h" - - -int iotx_cmp_mqtt_direct_disconnect_handler(iotx_cmp_conntext_pt cmp_pt); -int iotx_cmp_mqtt_direct_reconnect_handler(iotx_cmp_conntext_pt cmp_pt); -int iotx_cmp_mqtt_direct_register_handler(iotx_cmp_conntext_pt cmp_pt, char* URI, int result, int is_register); -int iotx_cmp_mqtt_direct_response_handler(iotx_cmp_conntext_pt cmp_pt, iotx_cmp_message_info_pt message_info); - -void* iotx_cmp_mqtt_direct_init(void* handler, iotx_cmp_init_param_pt pparam); -int iotx_cmp_mqtt_direct_connect(void* handler, void* connectivity_pt); -int iotx_cmp_mqtt_direct_register(void* handler, void* connectivity_pt, const char* topic_filter); -int iotx_cmp_mqtt_direct_unregister(void* handler, void* connectivity_pt, const char* topic_filter); -int iotx_cmp_mqtt_direct_send(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length); -int iotx_cmp_mqtt_direct_send_sync(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length); -int iotx_cmp_mqtt_direct_yield(void* connectivity_pt, int timeout_ms); -int iotx_cmp_mqtt_direct_deinit(void* connectivity_pt); - -#endif /* CMP_VIA_MQTT_DIRECT */ - -#endif /* __CMP_VIA_MQTT_DIRECT_H__ */ - - diff --git a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_ota.h b/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_ota.h deleted file mode 100644 index b018fe6..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/inc/iotx_cmp_ota.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __CMP_OTA_H__ -#define __CMP_OTA_H__ - - -#ifdef SERVICE_OTA_ENABLED -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iot_export.h" -#include "iot_export_ota.h" -#include "iotx_cmp_common.h" - -void* iotx_cmp_ota_init(iotx_cmp_conntext_pt cmp_pt, const char* version); - -int iotx_cmp_ota_yield(iotx_cmp_conntext_pt cmp_pt, iotx_cmp_ota_pt ota_pt); - -int iotx_cmp_ota_deinit(iotx_cmp_conntext_pt cmp_pt); - -int iotx_cmp_ota_request_image(iotx_cmp_conntext_pt cmp_pt, const char* version); - -int iotx_cmp_ota_get_config(iotx_cmp_conntext_pt cmp_pt, const char* configScope, const char* getType, const char* attributeKeys); - -#endif /* SERVICE_OTA_ENABLED */ - - -#endif /* __CMP_OTA_H__ */ - - diff --git a/iotkit-embedded/src/cmp/Link-CMP/iot_export_cmp.h b/iotkit-embedded/src/cmp/Link-CMP/iot_export_cmp.h deleted file mode 100644 index 381e024..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/iot_export_cmp.h +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CMP_H_ -#define SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CMP_H_ - -#include - -#define CMP_PRODUCT_KEY_LEN (20 + 1) -#define CMP_DEVICE_NAME_LEN (32 + 1) -#define CMP_DEVICE_SECRET_LEN (64 + 1) -#define CMP_DEVICE_ID_LEN (64 + 1) - - -/* support mutli thread -#define CMP_SUPPORT_MULTI_THREAD */ - -/* -* CMP: connection manager platform -*/ - - -#define CMP_TOPIC_LEN_MAX 256 - - -/* domain type */ -typedef enum IOTX_CMP_CLOUD_DOMAIN_TYPES { - /* "iot-as-mqtt.cn-shanghai.aliyuncs.com" */ - IOTX_CMP_CLOUD_DOMAIN_SH, - - /* USA */ - IOTX_CMP_CLOUD_DOMAIN_USA, - - /* Maximum number of domain */ - IOTX_CMP_CLOUD_DOMAIN_MAX -}iotx_cmp_cloud_domain_types_t; - - -/* message confirmation type */ -typedef enum IOTX_CMP_MESSAGE_ACK_TYPES { - /* non ACK */ - /* MQTT: QoS is 0 */ - /* CoAP: NON */ - /* default */ - IOTX_CMP_MESSAGE_NO_ACK, - - /* need ACK */ - /* MQTT: QoS is 1 */ - /* CoAP: CON */ - IOTX_CMP_MESSAGE_NEED_ACK, - - /* Maximum number of domain */ - IOTX_CMP_MESSAGE_ACK_MAX -}iotx_cmp_message_ack_types_t; - - -/* event type */ -typedef enum IOTX_CMP_EVENT_TYPES { - /* cloud connected */ - /* event_msg is null */ - IOTX_CMP_EVENT_CLOUD_CONNECTED = 0, - - /* cloud disconnect */ - /* event_msg is null */ - IOTX_CMP_EVENT_CLOUD_DISCONNECT = 1, - - /* cloud reconnect */ - /* event_msg is null */ - IOTX_CMP_EVENT_CLOUD_RECONNECT = 2, - - /* local: found device */ - /* event_msg is iotx_cmp_event_device_pt */ - IOTX_CMP_EVENT_FOUND_DEVICE = 10, - - /* local: remove device */ - /* event_msg is iotx_cmp_event_device_pt */ - IOTX_CMP_EVENT_REMOVE_DEVICE = 11, - - /* register */ - /* event_msg is iotx_cmp_event_result_pt */ - IOTX_CMP_EVENT_REGISTER_RESULT = 20, - - /* unregister */ - /* event_msg is iotx_cmp_event_result_pt */ - IOTX_CMP_EVENT_UNREGISTER_RESULT = 21, - - /* send */ - /* event_msg is iotx_cmp_event_result_pt */ - IOTX_CMP_EVENT_SEND_RESULT = 22, - - /* new data receive */ - /* used by undefined CMP_SUPPORT_TOPIC_DISPATCH */ - /* event_msg is iotx_cmp_ota_parameter_t */ - IOTX_CMP_EVENT_NEW_DATA_RECEIVED = 30, - - /* Maximum number of protocol */ - IOTX_CMP_EVENT_MAX -}iotx_cmp_event_types_t; - - -/* URI type */ -typedef enum IOTX_CMP_URI_TYPES { - /* /sys/product_key/device_name/... */ - IOTX_CMP_URI_SYS = 1, - - /* /ext/product_key/device_name/... */ - IOTX_CMP_URI_EXT = 2, - - /* set by user */ - IOTX_CMP_URI_UNDEFINE = 3, - - /* Maximum number of protocol */ - IOTX_CMP_URI_MAX -}iotx_cmp_uri_types_t; - - -typedef enum IOTX_CMP_PAYLOAD_TYPE { - /* RAW */ - IOTX_CMP_MESSAGE_RAW = 1, - - /* request */ - /* method and parameter is non-value, code is 0 */ - IOTX_CMP_MESSAGE_REQUEST = 2, - - /* response */ - /* code and parameter is non-value, method is NULL */ - /* parameter is for data node */ - IOTX_CMP_MESSAGE_RESPONSE = 3, - - IOTX_CMP_PAYLOAD_MAX -}iotx_cmp_message_types_t; - - -/* message confirmation type */ -typedef enum IOTX_CMP_DEVICE_SECRET_TYPES { - /* 一型一密 */ - IOTX_CMP_DEVICE_SECRET_PRODUCT, - - /* 一机一密 */ - IOTX_CMP_DEVICE_SECRET_DEVICE, - - /* Maximum number of domain */ - IOTX_CMP_DEVICE_SECRET_TYPES_MAX -}iotx_cmp_device_secret_types_t; - - -#ifdef SERVICE_OTA_ENABLED -/* URI type */ -typedef enum IOTX_CMP_OTA_TYPE { - /* FOTA */ - IOTX_CMP_OTA_TYPE_FOTA = 1, - - /* COTA */ - IOTX_CMP_OTA_TYPE_COTA = 2, - - /* Maximum */ - IOTX_CMP_OTA_TYPE_MAX -}iotx_cmp_ota_types_t; -#endif /* SERVICE_OTA_ENABLED */ - - -/* The structure of event for cloud found new device */ -typedef struct { - char product_key[CMP_PRODUCT_KEY_LEN + 1]; - char device_name[CMP_DEVICE_NAME_LEN + 1]; -} iotx_cmp_event_device_t, *iotx_cmp_event_device_pt; - - -/* The structure of event for register/unregister result */ -typedef struct { - /* 0: success, -1:nack */ - int8_t result; - char *URI; - iotx_cmp_uri_types_t URI_type; -} iotx_cmp_event_result_t, *iotx_cmp_event_result_pt; - - - -#ifdef SERVICE_OTA_ENABLED -/* The structure of fota result */ -typedef struct { - uint32_t size_file; /* size of file */ - char *purl; /* point to URL */ - char *version; /* point to string */ -} iotx_cmp_fota_parameter_t, *iotx_cmp_fota_parameter_pt; - - -/* The structure of cota result */ -typedef struct { - char *configId; /* config ID */ - uint32_t configSize; /* config size */ - char *sign; /* sign */ - char *signMethod; /* sign method */ - char *url; /* point to URL */ - char *getType; /* getType */ -} iotx_cmp_cota_parameter_t, *iotx_cmp_cota_parameter_pt; -#endif /* SERVICE_OTA_ENABLED */ - - -/* The structure of cmp event msg */ -typedef struct { - uint8_t event_id; - void* msg; -} iotx_cmp_event_msg_t, *iotx_cmp_event_msg_pt; - - -/* The structure of cmp event msg */ -typedef struct { - /* If it is the IOTX_CMP_MESSAGE_REQUEST in IOT_CMP_Send, this id is no mean. - * If it is the IOTX_CMP_MESSAGE_RESPONSE in IOT_CMP_Send, - * this id is must have value, read in register_callback's IOTX_CMP_MESSAGE_REQUEST. - * If is is the IOTX_CMP_MESSAGE_RESPONSE in register_callback, this id is no mean. - * If is is the IOTX_CMP_MESSAGE_REQUEST in register_callback, this id must be non-null. */ - int id; - iotx_cmp_message_ack_types_t ack_type; - char *URI; - iotx_cmp_uri_types_t URI_type; - unsigned int code; /* [in/out] */ - char *method; - void *parameter; - unsigned int parameter_length; - iotx_cmp_message_types_t message_type; /* response, request or raw */ -} iotx_cmp_message_info_t, *iotx_cmp_message_info_pt; - - -/* The structure of event for cloud found new device */ -typedef struct { - char product_key[CMP_PRODUCT_KEY_LEN + 1]; - char device_name[CMP_DEVICE_NAME_LEN + 1]; -} iotx_cmp_send_peer_t, *iotx_cmp_send_peer_pt; - - -/* The structure of new data */ -typedef struct { - iotx_cmp_send_peer_pt peer; - iotx_cmp_message_info_pt message_info; -} iotx_cmp_new_data_t, *iotx_cmp_new_data_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 user_data : The user_data set by user. - * @param msg : The event message. - * - * @return none - */ -typedef void (*iotx_cmp_event_handle_func_fpt)(void *pcontext, iotx_cmp_event_msg_pt msg, void *user_data); - - -#ifdef SERVICE_OTA_ENABLED -/** - * @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 ota_parameter : The fota parameter. - * @param user_data : The user_data set by user. - * - * @return none - */ -typedef void (*iotx_cmp_fota_handle_func_fpt)(void *pcontext, iotx_cmp_fota_parameter_pt ota_parameter, void *user_data); - -/** - * @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 ota_parameter : The cota parameter. - * @param user_data : The user_data set by user. - * - * @return none - */ -typedef void (*iotx_cmp_cota_handle_func_fpt)(void *pcontext, iotx_cmp_cota_parameter_pt ota_parameter, void *user_data); -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief It define a datatype of function pointer. - * This type of function will be called when received a related resqust. - * - * @param target : The register source. - * @param user_data : The user_data set by user. - * @param msg : The message info. - * - * @return none - */ -typedef void (*iotx_cmp_register_func_fpt)(iotx_cmp_send_peer_pt source, iotx_cmp_message_info_pt msg, void *user_data); - - -/* The structure of CMP param */ -typedef struct { - iotx_cmp_device_secret_types_t secret_type; - iotx_cmp_cloud_domain_types_t domain_type; - iotx_cmp_event_handle_func_fpt event_func; - void *user_data; -} iotx_cmp_init_param_t, *iotx_cmp_init_param_pt; - - -/* The structure of Register param */ -typedef struct { - char *URI; - iotx_cmp_uri_types_t URI_type; - iotx_cmp_message_types_t message_type; - iotx_cmp_register_func_fpt register_func; - void *user_data; - void *mail_box; -} iotx_cmp_register_param_t, *iotx_cmp_register_param_pt; - - -/* The structure of Register param */ -typedef struct { - char *URI; - iotx_cmp_uri_types_t URI_type; -} iotx_cmp_unregister_param_t, *iotx_cmp_unregister_param_pt; - - -#ifdef SERVICE_OTA_ENABLED -typedef struct { - iotx_cmp_ota_types_t ota_type; - /* if there is more data to download, is_more is 1, else is_more is 0 */ - uint8_t is_more; /* [out] */ - /* is_more is 0, result: */ - /* - * Burn firmware file failed -4 - * Check firmware file failed -3 - * Fetch firmware file failed -2 - * Initialized failed -1 - * success 0 - */ - int8_t result; /* [out] */ - int progress; /* [out] */ - void* buffer; /* [in/out] */ - int buffer_length; /* [in/out] */ -} iotx_cmp_ota_t, *iotx_cmp_ota_pt; -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief CMP init - * This function initialize the CMP structures, establish network connection - * If CMP has been initialized, this function will return success directly. - * - * @param pparam, specify the cmp and event handler. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Init(iotx_cmp_init_param_pt pparam, void* option); - - -#ifdef SERVICE_OTA_ENABLED -/** - * @brief Start OTA - * This function use to start OTA, set cur_version and ota_func. - * - * @param cur_version, current version. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_OTA_Start(char* cur_version, void* option); - - -/** -* @brief Set OTA callback -* This function use to set OTA callback. -* -* @param type, fota or cota. -* @param ota_func, ota callback function. -* @param user_context, ota callback user context. -* @param option, reserve. -* -* @return success or fail. -*/ -int IOT_CMP_OTA_Set_Callback(iotx_cmp_ota_types_t type, void* ota_func, void* user_context, void* option); - - -/** -* @brief Get Config -* -* -* @param configScope, device or product. -* @param getType, file or other type. -* @param attributeKeys -* @param option, reserve. -* -* @return success or fail. -*/ -int IOT_CMP_OTA_Get_Config(const char* configScope, const char* getType, const char* attributeKeys, void* option); - - -/** -* @brief Get firmware image -* -* -* @param version, firmware image version. -* @param option, reserve. -* -* @return success or fail. -*/ -int IOT_CMP_OTA_Request_Image(const char* version, void* option); -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief Register service. - * This function used to register some service by different URI, set the URI's callback. - * If it is received a request, will callback the register_cb. - * If there is no match register_cb (user have not register the service set callback), the request will be discard. - * - * @param pparam, register parameter, include URI and register callback. - * @param option, reserve. - * This API not support one URI register twice, if the URI have been register, it will return fail. - * - * @return success or fail. - */ -int IOT_CMP_Register(iotx_cmp_register_param_pt pparam, void* option); - - -/** - * @brief Unregister service. - * This function used to unregister some service by different URI - * - * @param pparam, unregister parameter, include URI. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Unregister(iotx_cmp_unregister_param_pt pparam, void* option); - - -/** - * @brief Send data. - * This function used to send data to target. - * If the target is NULL, the data will broadcast to all the reachable places. - * If the target is not NULL, the data will send to target only. - * If the target's product_key and device_name is itself, the data will send to cloud. - * - * @param target. - * @param message_info. - * @param option, reserve. - * - * @return success or fail. - * - */ -int IOT_CMP_Send(iotx_cmp_send_peer_pt target, iotx_cmp_message_info_pt message_info, void* option); - - -#ifndef CMP_SUPPORT_MULTI_THREAD - -/** - * @brief Send data. - * This function used to send data to target and wait for response. - * If the target is NULL, the data will broadcast to all the reachable places. - * If the target is not NULL, the data will send to target only. - * If the target's product_key and device_name is itself, the data will send to cloud. - * - * @param target. - * @param message_info [in/out]. - * @param option, reserve. - * - * @return success or fail. - * - */ -int IOT_CMP_Send_Sync(iotx_cmp_send_peer_pt target, iotx_cmp_message_info_pt message_info, void* option); - - -/** - * @brief Yield. - * This function used to yield when want to received data. - * This function just need used in CMP_SUPPORT_MULTI_THREAD = n. - * If the CMP_SUPPORT_MULTI_THREAD = y, this function is no need. - * - * @param target. - * @param message_info. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Yield(int timeout_ms, void* option); -#endif /* CMP_SUPPORT_MULTI_THREAD */ - - -/** - * @brief deinit - * - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Deinit(void* option); - -#ifdef SERVICE_OTA_ENABLED -/** - * @brief OTA yield function. - * Set buffer and length yield the ota data. - * - * @param ota_pt, ota yield params. - * - * @return success or fail. - */ -int IOT_CMP_OTA_Yield(iotx_cmp_ota_pt ota_pt); -#endif /* SERVICE_OTA_ENABLED */ - - -#ifdef UT_TEST -int request_inject(int id, char* uri, char* method, void* parameter, int parameter_len); - -int response_inject(int id, char* uri, int code, void* data, int data_length); - -#endif /* UT_TEST */ - - - -#endif /* SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CMP_H_ */ - - diff --git a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_api.c b/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_api.c deleted file mode 100644 index 16de2f7..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_api.c +++ /dev/null @@ -1,786 +0,0 @@ -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iot_export.h" -#include "iotx_cmp_common.h" -#include "iotx_cmp_mqtt_direct.h" -#include "iotx_cmp_cloud_conn.h" -#include "iotx_cmp_ota.h" - - - -static iotx_cmp_conntext_pt g_cmp_cnt = NULL; - -extern void guider_set_domain_type(int domain_type); - - -/** - * @brief CMP init - * This function initialize the CMP structures, establish network connection - * If CMP has been initialized, this function will return success directly. - * - * @param pparam, specify the cmp and event handler. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Init(iotx_cmp_init_param_pt pparam, void* option) -{ - iotx_conn_info_pt pconn_info; - iotx_cmp_event_callback_list_pt event_callback_list = NULL; - iotx_cmp_event_callback_list_pt event_callback = NULL; - iotx_cmp_event_callback_node_pt node = NULL; - iotx_cmp_event_handle_func_fpt user_callback = NULL; - void* user_data = NULL; - - if (NULL == pparam) return FAIL_RETURN; - - if (NULL == g_cmp_cnt) { - char product_key[PRODUCT_KEY_LEN + 1] = {0}; -#ifdef SUPPORT_PRODUCT_SECRET - char product_secret[PRODUCT_SECRET_LEN + 1] = {0}; -#endif - char device_name[DEVICE_NAME_LEN + 1] = {0}; - char device_secret[DEVICE_SECRET_LEN + 1] = {0}; - char device_id[DEVICE_ID_LEN + 1] = {0}; - - HAL_GetProductKey(product_key); - if (strlen(product_key) == 0) { - CMP_ERR(cmp_log_error_pk); - return FAIL_RETURN; - } - - HAL_GetDeviceName(device_name); - if (strlen(device_name) == 0) { - CMP_ERR(cmp_log_error_dn); - return FAIL_RETURN; - } - - HAL_GetDeviceID(device_id); - if (strlen(device_id) == 0) { - CMP_ERR(cmp_log_error_di); - return FAIL_RETURN; - } - -#ifdef SUPPORT_PRODUCT_SECRET - /* 一型一密 */ - if (IOTX_CMP_DEVICE_SECRET_PRODUCT == pparam->secret_type && 0 >= HAL_GetDeviceSecret(device_secret)) { - - HAL_GetProductSecret(product_secret); - if (strlen(product_secret) == 0) { - CMP_ERR(cmp_log_error_secret_1); - return FAIL_RETURN; - } - - /* auth */ - if (FAIL_RETURN == iotx_cmp_auth(product_key, device_name, device_id)) { - CMP_ERR(cmp_log_error_auth); - return FAIL_RETURN; - } - } -#endif /**< SUPPORT_PRODUCT_SECRET*/ - - HAL_GetDeviceSecret(device_secret); - if (strlen(device_secret) == 0) { - CMP_ERR(cmp_log_error_secret_2); - return FAIL_RETURN; - } - - - /* Device AUTH */ -#ifndef MQTT_ID2_AUTH - if (0 != IOT_SetupConnInfo(product_key, device_name, device_secret, (void **)&pconn_info)) { -#else - if (0 != IOT_SetupConnInfoSecure(product_key, device_name, device_secret, (void **)&pconn_info)) { -#endif /**< MQTT_ID2_AUTH*/ - CMP_ERR(cmp_log_error_auth); - return FAIL_RETURN; - } - - CMP_INFO(cmp_log_info_init); - g_cmp_cnt = CMP_malloc(sizeof(iotx_cmp_conntext_t)); - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - memset(g_cmp_cnt, 0x0, sizeof(iotx_cmp_conntext_t)); - - g_cmp_cnt->response_func = iotx_cmp_response_func; - guider_set_domain_type(pparam->domain_type); - } - - user_callback = pparam->event_func; - user_data = pparam->user_data; - - event_callback = CMP_malloc(sizeof(iotx_cmp_event_callback_list_t)); - if (NULL == event_callback) { - CMP_ERR(cmp_log_error_memory); - goto exit; - } - - node = CMP_malloc(sizeof(iotx_cmp_event_callback_node_t)); - if (NULL == node) { - CMP_ERR(cmp_log_error_memory); - goto exit; - } - - node->event_func = user_callback; - node->user_data = user_data; - event_callback->node = node; - event_callback->next = NULL; - - if(NULL == g_cmp_cnt->event_callback_list) { - g_cmp_cnt->event_callback_list = event_callback; - if (FAIL_RETURN == iotx_cmp_add_connectivity_all(g_cmp_cnt, pparam)) goto exit; - - /* create thread */ - #ifdef CMP_SUPPORT_MULTI_THREAD - g_cmp_cnt->thread_is_stoped = 0; - - g_cmp_cnt->process_cloud_lock = HAL_MutexCreate(); - if (NULL == g_cmp_cnt->process_cloud_lock) goto exit; - - #ifdef CMP_SUPPORT_MULTI_THREAD_VIA_HAL - if (0 != HAL_ThreadCreate(&g_cmp_cnt->pthread_process, iotx_cmp_cloud_process, NULL, NULL, NULL)) goto exit; - - #else - if (0 != pthread_create(&g_cmp_cnt->pthread_process, NULL, iotx_cmp_cloud_process, (void*)g_cmp_cnt)) goto exit; - #endif - - #ifdef CMP_SUPPORT_LOCAL_CONN - g_cmp_cnt->process_local_lock = HAL_MutexCreate(); - if (NULL == g_cmp_cnt->process_local_lock) goto exit; - - #ifdef CMP_SUPPORT_MULTI_THREAD_VIA_HAL - if (0 != HAL_ThreadCreate(&g_cmp_cnt->pthread_process, iotx_cmp_local_process, NULL, NULL, NULL)) goto exit; - - #else - if (0 != pthread_create(&g_cmp_cnt->pthread_process, NULL, iotx_cmp_local_process, (void*)g_cmp_cnt)) goto exit; - #endif - #endif - - #endif - } else { - event_callback_list = g_cmp_cnt->event_callback_list; - while(event_callback_list != NULL && event_callback_list->next) { - event_callback_list = event_callback_list->next; - } - event_callback_list->next = event_callback; - } - - if (g_cmp_cnt->connectivity_list && - g_cmp_cnt->connectivity_list->node && - g_cmp_cnt->connectivity_list->node->is_connected) { - iotx_cmp_event_msg_t event_msg = {0}; - event_msg.event_id = IOTX_CMP_EVENT_CLOUD_CONNECTED; - event_msg.msg = NULL; - user_callback(g_cmp_cnt, &event_msg, user_data); - } - - return SUCCESS_RETURN; - -exit: - CMP_ERR(cmp_log_error_fail); - iotx_cmp_remove_connectivity_all(g_cmp_cnt); - -#ifdef SERVICE_OTA_ENABLED - if (g_cmp_cnt->ota_handler) iotx_cmp_ota_deinit(g_cmp_cnt); -#endif /* SERVICE_OTA_ENABLED */ - -#ifdef CMP_SUPPORT_MULTI_THREAD - if (g_cmp_cnt->process_cloud_lock) HAL_MutexDestroy(g_cmp_cnt->process_cloud_lock); -#ifdef CMP_SUPPORT_LOCAL_CONN - if (g_cmp_cnt->process_local_lock) HAL_MutexDestroy(g_cmp_cnt->process_local_lock); -#endif -#endif - - if (node) LITE_free(node); - - if (event_callback) LITE_free(event_callback); - - if (g_cmp_cnt) LITE_free(g_cmp_cnt); - - g_cmp_cnt = 0; - - return FAIL_RETURN; -} - -#ifdef SERVICE_OTA_ENABLED -int IOT_CMP_OTA_Start(char* cur_version, void* option) -{ - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - if (NULL == cur_version) CMP_ERR(cmp_log_error_parameter); - - if (g_cmp_cnt->connectivity_list && - g_cmp_cnt->connectivity_list->node && - 0 == g_cmp_cnt->connectivity_list->node->is_connected) { - CMP_WARNING(cmp_log_warning_cloud_disconnected); - return FAIL_RETURN; - } - - /* ota init */ - if (NULL == g_cmp_cnt->ota_handler) - g_cmp_cnt->ota_handler = iotx_cmp_ota_init(g_cmp_cnt, cur_version); - if (NULL == g_cmp_cnt->ota_handler) return FAIL_RETURN; - - return SUCCESS_RETURN; -} - - -int IOT_CMP_OTA_Set_Callback(iotx_cmp_ota_types_t type, void* ota_func, void* user_context, void* option) -{ - void** _ota_func = NULL; - void** _user_context = NULL; - - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - if (NULL == ota_func) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - switch(type) { - case IOTX_CMP_OTA_TYPE_FOTA: - _ota_func = (void**)&g_cmp_cnt->fota_func; - _user_context = (void**)&g_cmp_cnt->fota_user_context; - break; - - case IOTX_CMP_OTA_TYPE_COTA: - _ota_func = (void**)&g_cmp_cnt->cota_func; - _user_context = (void**)&g_cmp_cnt->cota_user_context; - break; - - default: - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - break; - } - - if (*_ota_func) { - CMP_WARNING(cmp_log_warning_ota_started); - return FAIL_RETURN; - } - - if (g_cmp_cnt->connectivity_list && - g_cmp_cnt->connectivity_list->node && - 0 == g_cmp_cnt->connectivity_list->node->is_connected) { - CMP_WARNING(cmp_log_warning_cloud_disconnected); - return FAIL_RETURN; - } - - *_ota_func = ota_func; - *_user_context = user_context; - - return SUCCESS_RETURN; -} - - -int IOT_CMP_OTA_Get_Config(const char* configScope, const char* getType, const char* attributeKeys, void* option) -{ - if (NULL == g_cmp_cnt || NULL == g_cmp_cnt->ota_handler) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - return iotx_cmp_ota_get_config(g_cmp_cnt, configScope, getType, attributeKeys); -} - - -int IOT_CMP_OTA_Request_Image(const char* version, void* option) -{ - if (NULL == g_cmp_cnt || NULL == g_cmp_cnt->ota_handler) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - return iotx_cmp_ota_request_image(g_cmp_cnt, version); -} -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief Register service. - * This function used to register some service by different URI, set the URI's callback. - * If it is received a request, will callback the register_cb. - * If there is no match register_cb (user have not register the service set callback), the request will be discard. - * - * @param pparam, register parameter, include URI and register callback. - * @param option, reserve. - * - * @return success or fail. - * This API not support one URI register twice, if the URI have been register, it will return fail. - */ -int IOT_CMP_Register(iotx_cmp_register_param_pt pparam, void* option) -{ - char* URI = NULL; - int rc = 0; - int length = CMP_TOPIC_LEN_MAX; - - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - if (NULL == pparam || NULL == pparam->URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - if (pparam->URI_type > IOTX_CMP_URI_UNDEFINE || pparam->URI_type < IOTX_CMP_URI_SYS) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - if (pparam->message_type > IOTX_CMP_MESSAGE_RESPONSE || pparam->message_type < IOTX_CMP_MESSAGE_RAW) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - /* splice URI */ - URI = CMP_malloc(CMP_TOPIC_LEN_MAX); - if (NULL == URI){ - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - memset(URI, 0x0, CMP_TOPIC_LEN_MAX); - - if (FAIL_RETURN == iotx_cmp_splice_URI(URI, &length, pparam->URI, pparam->URI_type)) { - CMP_ERR(cmp_log_error_splice_URI); - return FAIL_RETURN; - } - - if (NULL != iotx_cmp_find_mapping(g_cmp_cnt, URI, length)) { - CMP_INFO(cmp_log_info_registered); - LITE_free(URI); - return FAIL_RETURN; - } - -#ifdef CMP_SUPPORT_MULTI_THREAD -{ - /* send message to itself thread */ - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_pt msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) { - CMP_ERR(cmp_log_error_get_node); - LITE_free(URI); - return FAIL_RETURN; - } - - node->type = IOTX_CMP_PROCESS_CLOUD_REGISTER; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - LITE_free(URI); - iotx_cmp_free_list_node(node); - return FAIL_RETURN; - } - - msg = node->msg; - msg->URI = URI; - msg->type = pparam->message_type; - msg->register_func = pparam->register_func; - msg->user_data = pparam->user_data; - msg->mail_box = pparam->mail_box; - - rc = iotx_cmp_process_list_push(g_cmp_cnt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - CMP_ERR(cmp_log_error_push_node); - LITE_free(URI); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } -} -#else /* CMP_SUPPORT_MULTI_THREAD */ - rc = iotx_cmp_register_service(g_cmp_cnt, URI, pparam->message_type, pparam->register_func, pparam->user_data, pparam->mail_box); - LITE_free(URI); -#endif /* CMP_SUPPORT_MULTI_THREAD */ - - return rc; -} - - -/** - * @brief Unregister service. - * This function used to unregister some service by different URI - * - * @param pparam, unregister parameter, include URI. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Unregister(iotx_cmp_unregister_param_pt pparam, void* option) -{ - char* URI = NULL; - int rc = 0; - int length = CMP_TOPIC_LEN_MAX; - - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - if (NULL == pparam || NULL == pparam->URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - /* splice URI */ - URI = CMP_malloc(CMP_TOPIC_LEN_MAX); - if (NULL == URI){ - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - memset(URI, 0x0, CMP_TOPIC_LEN_MAX); - - if (FAIL_RETURN == iotx_cmp_splice_URI(URI, &length, pparam->URI, pparam->URI_type)) { - CMP_ERR(cmp_log_error_splice_URI); - return FAIL_RETURN; - } - -#ifdef CMP_SUPPORT_MULTI_THREAD -{ - /* send message to itself thread */ - iotx_cmp_process_list_node_pt node = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) { - CMP_ERR(cmp_log_error_get_node); - LITE_free(URI); - return FAIL_RETURN; - } - - node->type = IOTX_CMP_PROCESS_CLOUD_UNREGISTER; - node->msg = (void*)URI; - - rc = iotx_cmp_process_list_push(g_cmp_cnt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - CMP_ERR(cmp_log_error_push_node); - LITE_free(URI); - iotx_cmp_free_list_node(node); - } -} - -#else /* CMP_SUPPORT_MULTI_THREAD */ - rc = iotx_cmp_unregister_service(g_cmp_cnt, URI); - LITE_free(URI); -#endif /* CMP_SUPPORT_MULTI_THREAD */ - - return rc; -} - - -/** - * @brief Send data. - * This function used to send data to target. - * If the target is NULL, the data will broadcast to all the reachable places. - * If the target is not NULL, the data will send to target only. - * If the target's product_key and device_name is itself, the data will send to cloud. - * - * @param target. - * @param message_info. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Send(iotx_cmp_send_peer_pt target, iotx_cmp_message_info_pt message_info, void* option) -{ - int rc = 0; - char* URI; - void* payload; - int payload_length = 0; - - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - if (NULL == message_info || NULL == message_info->URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - -#ifdef CMP_SUPPORT_MULTI_THREAD -{ - /* send message to itself thread */ - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_send_pt msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) { - CMP_ERR(cmp_log_error_get_node); - return FAIL_RETURN; - } - - node->type = IOTX_CMP_PROCESS_CLOUD_SEND; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_send_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return FAIL_RETURN; - } - - msg = node->msg; - if (target) { - msg->target = CMP_malloc(sizeof(iotx_cmp_send_peer_t)); - memset(msg->target, 0x0, sizeof(iotx_cmp_send_peer_t)); - strncpy(msg->target->device_name, target->device_name, strlen(target->device_name)); - strncpy(msg->target->product_key, target->product_key, strlen(target->product_key)); - } else { - msg->target = NULL; - } - - if (FAIL_RETURN == iotx_cmp_parse_message(g_cmp_cnt, message_info, &URI, &payload, &payload_length)) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - if (msg->target) - LITE_free(msg->target); - return FAIL_RETURN; - } - - msg->ack_type = message_info->ack_type; - msg->URI = URI; - msg->payload = payload; - msg->payload_length = payload_length; - - rc = iotx_cmp_process_list_push(g_cmp_cnt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - CMP_ERR(cmp_log_error_push_node); - if (msg->target) LITE_free(msg->target); - if (msg->URI) LITE_free(msg->URI); - if (msg->payload) LITE_free(msg->payload); - if (node->msg) LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } -} -#else /* CMP_SUPPORT_MULTI_THREAD */ - if (FAIL_RETURN == iotx_cmp_parse_message(g_cmp_cnt, message_info, &URI, &payload, &payload_length)) return FAIL_RETURN; - - rc = iotx_cmp_send_data(g_cmp_cnt, target, URI, message_info->ack_type, payload, payload_length); -#endif /* CMP_SUPPORT_MULTI_THREAD */ - - return rc; -} - - -#ifndef CMP_SUPPORT_MULTI_THREAD - -/** - * @brief Send data. - * This function used to send data to target and wait for response. - * If the target is NULL, the data will broadcast to all the reachable places. - * If the target is not NULL, the data will send to target only. - * If the target's product_key and device_name is itself, the data will send to cloud. - * - * @param target. - * @param message_info [in/out]. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Send_Sync(iotx_cmp_send_peer_pt target, iotx_cmp_message_info_pt message_info, void* option) -{ - if (NULL == g_cmp_cnt){ - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - CMP_WARNING(cmp_log_warning_not_support); - - return SUCCESS_RETURN; -} - -/** - * @brief Yield. - * This function used to yield when want to received data. - * This function just need used in CMP_SUPPORT_MULTI_THREAD = n. - * If the CMP_SUPPORT_MULTI_THREAD = y, this function is no need. - * - * @param target. - * @param message_info. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Yield(int timeout_ms, void* option) -{ - iotx_cmp_connectivity_list_pt conn_list = NULL; - - if (NULL == g_cmp_cnt){ - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - conn_list = g_cmp_cnt->connectivity_list; - - while(conn_list) { - if (conn_list->node && conn_list->node->yield_func) { - if (0 == conn_list->node->is_connected) { - conn_list->node->connect_func(g_cmp_cnt, conn_list->node); - if (1 == conn_list->node->is_connected) { - iotx_cmp_event_msg_t event_msg = {0}; - event_msg.event_id = IOTX_CMP_EVENT_CLOUD_CONNECTED; - event_msg.msg = NULL; - iotx_cmp_trigger_event_callback(g_cmp_cnt, &event_msg); - } - } else { - conn_list->node->yield_func(conn_list->node, timeout_ms); - } - } - conn_list = conn_list->next; - } - - return SUCCESS_RETURN; -} -#endif /* CMP_SUPPORT_MULTI_THREAD */ - -/** - * @brief deinit - * - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Deinit(void* option) -{ - if (NULL == g_cmp_cnt){ - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - /* stop thread */ -#ifdef CMP_SUPPORT_MULTI_THREAD - g_cmp_cnt->thread_stop = 1; - while(!g_cmp_cnt->thread_is_stoped) { - HAL_SleepMs(10); - } -#endif - - iotx_cmp_remove_connectivity_all(g_cmp_cnt); - -#ifdef SERVICE_OTA_ENABLED - if (g_cmp_cnt->ota_handler) { - iotx_cmp_ota_deinit(g_cmp_cnt); - } -#endif /* SERVICE_OTA_ENABLED */ - -#ifdef CMP_SUPPORT_MULTI_THREAD - if (g_cmp_cnt->process_cloud_lock) { - HAL_MutexDestroy(g_cmp_cnt->process_cloud_lock); - } -#ifdef CMP_SUPPORT_LOCAL_CONN - if (g_cmp_cnt->process_local_lock) { - HAL_MutexDestroy(g_cmp_cnt->process_local_lock); - } -#endif -#endif - - /* free memory */ -#ifdef CMP_SUPPORT_MULTI_THREAD - iotx_cmp_free_list_node_all(g_cmp_cnt); -#endif - iotx_cmp_remove_mapping_all(g_cmp_cnt); - - if (g_cmp_cnt->event_callback_list) { - iotx_cmp_event_callback_list_pt event_callback = g_cmp_cnt->event_callback_list; - iotx_cmp_event_callback_list_pt pre_event_callback = event_callback; - - while (event_callback) { - LITE_free(event_callback->node); - pre_event_callback = event_callback; - event_callback = event_callback->next; - LITE_free(pre_event_callback); - } - } - - LITE_free(g_cmp_cnt); - g_cmp_cnt = 0; - - return SUCCESS_RETURN; -} - - -#ifdef SERVICE_OTA_ENABLED -int IOT_CMP_OTA_Yield(iotx_cmp_ota_pt ota_pt) -{ - if (NULL == g_cmp_cnt) { - CMP_ERR(cmp_log_error_status); - return FAIL_RETURN; - } - - if (NULL == ota_pt || NULL == ota_pt->buffer) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - return iotx_cmp_ota_yield(g_cmp_cnt, ota_pt); -} -#endif /* SERVICE_OTA_ENABLED */ - - - -#ifdef UT_TEST -int request_inject(int id, char* uri, char* method, void* parameter, int parameter_len) -{ - iotx_cmp_message_info_t message_info = {0}; - - message_info.id = id; - message_info.code = 0; - - message_info.URI = LITE_calloc(1, strlen(uri) + 1, MEM_MAGIC, "CMP"); - strcpy(message_info.URI, uri); - - message_info.URI_type = IOTX_CMP_URI_UNDEFINE; - - message_info.method = LITE_calloc(1, strlen(method) + 1, MEM_MAGIC, "CMP"); - strcpy(message_info.method, method); - - message_info.parameter = LITE_calloc(1, strlen(parameter) + 1, MEM_MAGIC, "CMP"); - strcpy(message_info.parameter, parameter); - - message_info.parameter_length = parameter_len; - message_info.message_type = IOTX_CMP_MESSAGE_REQUEST; - - iotx_cmp_mqtt_direct_response_handler(g_cmp_cnt, &message_info); - return SUCCESS_RETURN; -} - -int response_inject(int id, char* uri, int code, void* data, int data_length) -{ - iotx_cmp_message_info_t message_info = {0}; - - message_info.id = id; - message_info.code = code; - - message_info.URI = LITE_calloc(1, strlen(uri) + 1, MEM_MAGIC, "CMP"); - strcpy(message_info.URI, uri); - - message_info.URI_type = IOTX_CMP_URI_UNDEFINE; - - message_info.method = NULL; - - message_info.parameter = LITE_calloc(1, strlen(data) + 1, MEM_MAGIC, "CMP"); - strcpy(message_info.parameter, data); - - message_info.parameter_length = data_length; - message_info.message_type = IOTX_CMP_MESSAGE_RESPONSE; - - iotx_cmp_mqtt_direct_response_handler(g_cmp_cnt, &message_info); - return SUCCESS_RETURN; -} - -#endif - - - - diff --git a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_cloud_conn.c b/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_cloud_conn.c deleted file mode 100644 index 011a222..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_cloud_conn.c +++ /dev/null @@ -1,693 +0,0 @@ -#ifdef CMP_VIA_CLOUN_CONN - -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iot_export.h" -#include "iotx_cmp_common.h" -#include "iotx_cmp_cloud_conn.h" - - -static void iotx_cmp_cloud_conn_event_callback(void *pcontext, iotx_cloud_connection_event_msg_pt msg) -{ - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)pcontext; - - if (NULL == cmp_pt || NULL == msg) { - CMP_ERR(cmp_log_error_parameter); - return; - } - - CMP_INFO(cmp_log_info_event_id, msg->event_id); - - switch (msg->event_id) { - case IOTX_CLOUD_CONNECTION_EVENT_DISCONNECT: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) { - CMP_ERR(cmp_log_error_get_node); - return; - } - - node->type = IOTX_CMP_PROCESS_CLOUD_DISCONNECT; - node->msg = NULL; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - CMP_ERR(cmp_log_error_push_node); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_cloud_conn_disconnect_handler(cmp_pt); - #endif - } - break; - - case IOTX_CLOUD_CONNECTION_EVENT_RECONNECT: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) { - CMP_ERR(cmp_log_error_get_node); - return; - } - node->type = IOTX_CMP_PROCESS_CLOUD_RECONNECT; - node->msg = NULL; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - CMP_ERR(cmp_log_error_push_node); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_cloud_conn_reconnect_handler(cmp_pt); - #endif - } - break; - - default: - CMP_WARNING(cmp_log_warning_not_arrived); - break; - } -} - - -static void iotx_cmp_cloud_conn_response_callback(void *pcontext, - void *pconnection, - iotx_cloud_connection_msg_rsp_pt msg) -{ - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)pcontext; - - if (NULL == cmp_pt || NULL == pconnection || NULL == msg) { - CMP_ERR(cmp_log_error_parameter); - return; - } - - CMP_INFO(cmp_log_info_rsp_type, msg->rsp_type); - - switch (msg->rsp_type) { - case IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_SUCCESS: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - result_msg->URI = CMP_malloc(strlen(msg->URI) + 1); - if (NULL == result_msg->URI) { - LITE_free(node->msg); - LITE_free(node); - return; - } - memset(result_msg->URI, 0x0, strlen(msg->URI) + 1); - strncpy(result_msg->URI, (msg->URI), strlen(msg->URI) + 1); - result_msg->result = 1; - result_msg->is_register = 1; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - LITE_free(result_msg->URI); - LITE_free(node->msg); - LITE_free(node); - } - } - #else - iotx_cmp_cloud_conn_register_handler(cmp_pt, msg->URI, 1, 1); - #endif - } - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_FAIL: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = CMP_malloc(strlen(msg->URI) + 1); - if (NULL == result_msg->URI) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - memset(result_msg->URI, 0x0, strlen(msg->URI) + 1); - strncpy(result_msg->URI, (msg->URI), strlen(msg->URI) + 1); - - result_msg->result = 0; - result_msg->is_register = 1; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_cloud_conn_register_handler(cmp_pt, msg->URI, 0, 1); - #endif - } - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_SUCCESS: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = CMP_malloc(strlen(msg->URI) + 1); - if (NULL == result_msg->URI) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - memset(result_msg->URI, 0x0, strlen(msg->URI) + 1); - strncpy(result_msg->URI, (msg->URI), strlen(msg->URI) + 1); - result_msg->result = 1; - result_msg->is_register = 0; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_cloud_conn_register_handler(cmp_pt, msg->URI, 1, 0); - #endif - } - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_FAIL: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = CMP_malloc(strlen(msg->URI) + 1); - if (NULL == result_msg->URI) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - memset(result_msg->URI, 0x0, strlen(msg->URI) + 1); - strncpy(result_msg->URI, (msg->URI), strlen(msg->URI) + 1); - result_msg->result = 0; - result_msg->is_register = 0; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_cloud_conn_register_handler(cmp_pt, msg->URI, 0, 0); - #endif - } - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SEND_SUCCESS: - case IOTX_CLOUD_CONNECTION_RESPONSE_SEND_FAIL: - case IOTX_CLOUD_CONNECTION_RESPONSE_NEW_DATA: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_message_info_pt msg_info = NULL; - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - iotx_cmp_mapping_pt mapping = NULL; - #endif - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_NEW_DATA; - node->msg = CMP_malloc(sizeof(iotx_cmp_message_info_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - msg_info = node->msg; - - msg_info->URI = CMP_malloc(msg->URI_length + 1); - if (NULL == msg_info->URI) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - - if (FAIL_RETURN == iotx_cmp_parse_URI((char*)msg->URI, msg->URI_length, msg_info->URI, &msg_info->URI_type)) { - CMP_ERR(cmp_log_error_parse_URI); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - /* find mapping */ - mapping = iotx_cmp_find_mapping(cmp_pt, (char*)msg->URI, msg->URI_length); - if (NULL == mapping) { - CMP_WARNING(cmp_log_warning_not_mapping); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - msg_info->message_type = mapping->type; - #endif - - if (FAIL_RETURN == iotx_cmp_parse_payload((char*)msg->payload, msg->payload_length, msg_info)) { - CMP_ERR(cmp_log_error_parse_payload); - iotx_cmp_free_message_info(msg_info); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - if (FAIL_RETURN == rc) { - iotx_cmp_free_message_info(msg_info); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - break; - } - } - #else - iotx_cmp_message_info_t message_info; - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - iotx_cmp_mapping_pt mapping = NULL; - #endif - - memset(&message_info, 0x0, sizeof(iotx_cmp_message_info_t)); - - message_info.URI = CMP_malloc(msg->URI_length + 1); - if (NULL == message_info.URI) { - CMP_ERR(cmp_log_error_memory); - return; - } - memset(message_info.URI, 0x0, msg->URI_length + 1); - if (FAIL_RETURN == iotx_cmp_parse_URI((char*)msg->URI, msg->URI_length, message_info.URI, &message_info.URI_type)) { - CMP_ERR(cmp_log_error_parse_URI); - iotx_cmp_free_message_info(&message_info); - return; - } - - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - /* find mapping */ - mapping = iotx_cmp_find_mapping(cmp_pt, (char*)msg->URI, msg->URI_length); - if (NULL == mapping) { - CMP_WARNING(cmp_log_warning_not_mapping); - iotx_cmp_free_message_info(&message_info); - return; - } - message_info.message_type = mapping->type; - #endif - - if (FAIL_RETURN == iotx_cmp_parse_payload((char*)msg->payload, msg->payload_length, &message_info)) { - CMP_ERR(cmp_log_error_parse_payload); - iotx_cmp_free_message_info(&message_info); - return; - } - - iotx_cmp_cloud_conn_response_handler(cmp_pt, &message_info); - #endif - } - break; - - default: - CMP_WARNING(cmp_log_warning_not_arrived); - break; - } -} - - -int iotx_cmp_cloud_conn_disconnect_handler(iotx_cmp_conntext_pt cmp_pt) -{ - iotx_cmp_event_msg_t event; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - event.event_id = IOTX_CMP_EVENT_CLOUD_DISCONNECT; - event.msg = NULL; - - CMP_INFO(cmp_log_info_cloud_disconnect); - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - return SUCCESS_RETURN; -} - -int iotx_cmp_cloud_conn_reconnect_handler(iotx_cmp_conntext_pt cmp_pt) -{ - iotx_cmp_event_msg_t event; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - event.event_id = IOTX_CMP_EVENT_CLOUD_RECONNECT; - event.msg = NULL; - - CMP_INFO(cmp_log_info_cloud_reconnect); - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - return SUCCESS_RETURN; -} - -int iotx_cmp_cloud_conn_register_handler(iotx_cmp_conntext_pt cmp_pt, - char* URI, - int result, - int is_register) -{ - iotx_cmp_event_msg_t event; - iotx_cmp_event_result_t result_pt = {0}; - - if (NULL == cmp_pt || NULL == URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - result_pt.result = result; - result_pt.URI = CMP_malloc(CMP_TOPIC_LEN_MAX); - if (NULL == result_pt.URI) { - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - memset(result_pt.URI, 0x0, CMP_TOPIC_LEN_MAX); - - if (FAIL_RETURN == iotx_cmp_parse_URI((char*)URI, strlen(result_pt.URI), result_pt.URI, &result_pt.URI_type)) { - CMP_ERR(cmp_log_error_parse_URI); - LITE_free(result_pt.URI); - return FAIL_RETURN; - } - - if (is_register) - event.event_id = IOTX_CMP_EVENT_REGISTER_RESULT; - else - event.event_id = IOTX_CMP_EVENT_UNREGISTER_RESULT; - - event.msg = (void*)&result_pt; - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - LITE_free(result_pt.URI); - - return SUCCESS_RETURN; -} - - -int iotx_cmp_cloud_conn_response_handler(iotx_cmp_conntext_pt cmp_pt, iotx_cmp_message_info_pt message_info) -{ - if (NULL == cmp_pt || NULL == message_info) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - CMP_INFO(cmp_log_info_URI, (char*)message_info->URI); - - if (cmp_pt->response_func) - cmp_pt->response_func(cmp_pt, message_info); - - /*iotx_cmp_free_message_info(message_info);*/ - - return SUCCESS_RETURN; -} - - -void* iotx_cmp_cloud_conn_init(void* handler, iotx_cmp_init_param_pt pparam) -{ - void* pclient = NULL; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - iotx_cloud_connection_param_t cloud_param = {0}; - iotx_cmp_connectivity_pt connectivity = NULL; - - cloud_param.device_info = HAL_Malloc(sizeof(iotx_deviceinfo_t)); - if (NULL == cloud_param.device_info) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - - strncpy(cloud_param.device_info->product_key, pparam->product_key, strlen(pparam->product_key)); - strncpy(cloud_param.device_info->device_name, pparam->device_name, strlen(pparam->device_name)); - strncpy(cloud_param.device_info->device_secret, pparam->device_secret, strlen(pparam->device_secret)); - strncpy(cloud_param.device_info->device_id, pparam->device_id, strlen(pparam->device_id)); - - cloud_param.clean_session = 0; - cloud_param.keepalive_interval_ms = 60000; - cloud_param.request_timeout_ms = 2000; - -#ifdef CMP_VIA_CLOUD_CONN_MQTT - cloud_param.protocol_type = IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_MQTT; -#else -#ifdef CMP_VIA_CLOUD_CONN_COAP - cloud_param.protocol_type = IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_COAP; -#else - cloud_param.protocol_type = IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_HTTP; -#endif -#endif - - cloud_param.event_handler = iotx_cmp_cloud_conn_event_callback; - cloud_param.event_pcontext = cmp_pt; - - pclient = IOT_Cloud_Connection_Init(&cloud_param); - if (NULL == pclient) { - CMP_ERR(cmp_log_error_fail); - iotx_cmp_cloud_conn_deinit(connectivity); - } - - connectivity = CMP_malloc(sizeof(iotx_cmp_connectivity_t)); - if (NULL == connectivity) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_cloud_conn_deinit(connectivity); - return NULL; - } - - connectivity->context = pclient; - connectivity->init_func = iotx_cmp_cloud_conn_init; - connectivity->register_func = iotx_cmp_cloud_conn_register; - connectivity->unregister_func = iotx_cmp_cloud_conn_unregister; - connectivity->send_func = iotx_cmp_cloud_conn_send; - connectivity->send_sync_func = iotx_cmp_cloud_conn_send_sync; - connectivity->yield_func = iotx_cmp_cloud_conn_yield; - connectivity->deinit_func = iotx_cmp_cloud_conn_deinit; - - return connectivity; -} - - -int iotx_cmp_cloud_conn_register(void* handler, void* connectivity_pt, const char* topic_filter) -{ - int rc = 0; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - iotx_cloud_connection_msg_t msg = {0}; - - if (NULL == connectivity || NULL == topic_filter) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_SUBSCRIBE; - msg.QoS = IOTX_MESSAGE_QOS1; - msg.URI = (char*)topic_filter; - msg.URI_length = strlen(topic_filter); - msg.payload = NULL; - msg.payload_length = 0; - msg.response_handler = iotx_cmp_cloud_conn_response_callback; - msg.response_pcontext = cmp_pt; - rc = IOT_Cloud_Connection_Send_Message(connectivity->context, &msg); - - CMP_INFO(cmp_log_info_result, rc); - - return rc; -} - - -int iotx_cmp_cloud_conn_unregister(void* handler, void* connectivity_pt, const char* topic_filter) -{ - int rc = 0; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - iotx_cloud_connection_msg_t msg = {0}; - - if (NULL == connectivity || NULL == topic_filter) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_UNSUBSCRIBE; - msg.QoS = IOTX_MESSAGE_QOS0; - msg.URI = (char*)topic_filter; - msg.URI_length = strlen(topic_filter); - msg.payload = NULL; - msg.payload_length = 0; - msg.response_handler = iotx_cmp_cloud_conn_response_callback; - msg.response_pcontext = cmp_pt; - rc = IOT_Cloud_Connection_Send_Message(connectivity->context, &msg); - CMP_INFO(cmp_log_info_result, rc); - return rc; -} - - -static iotx_message_qos_t _to_message_qos(iotx_cmp_message_ack_types_t ack_type) -{ - switch (ack_type) { - case IOTX_CMP_MESSAGE_NEED_ACK: - return IOTX_MESSAGE_QOS1; - - case IOTX_CMP_MESSAGE_NO_ACK: - return IOTX_MESSAGE_QOS0; - - default: - return IOTX_MESSAGE_QOS0; - } -} - - -int iotx_cmp_cloud_conn_send(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length) -{ - int rc = 0; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - iotx_cloud_connection_msg_t msg = {0}; - - if (NULL == connectivity || NULL == topic_filter || NULL == payload) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_PUBLISH; - msg.QoS = _to_message_qos(ack_type); - msg.URI = (char*)topic_filter; - msg.URI_length = strlen(topic_filter); - msg.payload = (char*)payload; - msg.payload_length = payload_length; - msg.response_handler = iotx_cmp_cloud_conn_response_callback; - msg.response_pcontext = cmp_pt; - rc = IOT_Cloud_Connection_Send_Message(connectivity->context, &msg); - CMP_INFO(cmp_log_info_result, rc); - - return rc; -} - - -int iotx_cmp_cloud_conn_send_sync(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length) -{ - return FAIL_RETURN; -} - -int iotx_cmp_cloud_conn_yield(void* connectivity_pt, int timeout_ms) -{ - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - - if (NULL == connectivity) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - return IOT_Cloud_Connection_Yield(connectivity->context, timeout_ms); -} - -int iotx_cmp_cloud_conn_deinit(void* connectivity_pt) -{ - int rc = 0; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - - if (NULL == connectivity) - return FAIL_RETURN; - - rc = IOT_Cloud_Connection_Deinit(&(connectivity->context)); - - LITE_free(connectivity); - - return rc; -} - -#endif - diff --git a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_common.c b/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_common.c deleted file mode 100644 index 7647d67..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_common.c +++ /dev/null @@ -1,1986 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "iotx_cmp_common.h" -#include "iotx_cmp_mqtt_direct.h" -#include "iotx_cmp_cloud_conn.h" -#include "utils_httpc.h" -#include "utils_hmac.h" -#include "iot_export.h" -#include "iot_import.h" - -#define IOTX_CMP_MESSAGE_ID_MAX (65535) - - -#ifdef CMP_MAPPING_USE_POOL -static iotx_cmp_mapping_t g_cmp_mapping_list[CMP_SUPPORT_MAX_MAPPING_SIZE]; -#endif - -#ifdef CMP_PROCESS_NODE_USE_POOL -static iotx_cmp_process_list_node_t g_cmp_cloud_process_node_list[CMP_SUPPORT_MAX_PROCESS_NODE_SIZE]; -#endif - -#ifdef CMP_SUPPORT_LOCAL_CONN -#ifdef CMP_PROCESS_NODE_USE_POOL -static iotx_cmp_process_list_node_t g_cmp_local_process_node_list[CMP_SUPPORT_MAX_PROCESS_NODE_SIZE]; -#endif -#endif - - -static const char string_id[] CMP_READ_ONLY = "id"; -static const char string_code[] CMP_READ_ONLY = "code"; -static const char string_data[] CMP_READ_ONLY = "data"; -static const char string_params[] CMP_READ_ONLY = "params"; -static const char string_method[] CMP_READ_ONLY = "method"; -static const char string_pk[] CMP_READ_ONLY = "data.productKey"; -static const char string_dn[] CMP_READ_ONLY = "data.deviceName"; -static const char string_ds[] CMP_READ_ONLY = "data.deviceSecret"; -static const char string_response_format[] CMP_READ_ONLY = "{\"id\":\"%u\",\"code\":%d,\"data\":%s}"; -static const char string_request_format[] CMP_READ_ONLY = "{\"id\":\"%u\",\"version\":\"1.0\",\"params\":%s,\"method\":\"%s\"}"; -static const char string_SYS_URI[] CMP_READ_ONLY = "/sys/%s/%s/"; -static const char string_EXT_URI[] CMP_READ_ONLY = "/ext/%s/%s/"; -static const char string_SYS_URI_1[] CMP_READ_ONLY = "/sys/%s/%s/%s"; -static const char string_EXT_URI_1[] CMP_READ_ONLY = "/ext/%s/%s/%s"; -static const char string_SHA_METHOD[] CMP_READ_ONLY = "hmacsha1"; -static const char string_MD5_METHOD[] CMP_READ_ONLY = "hmacmd5"; -static const char string_TIMESTAMP[] CMP_READ_ONLY = "2524608000000"; -static const char string_AUTH_URL[] CMP_READ_ONLY = "https://iot-auth.cn-shanghai.aliyuncs.com/auth/register/device"; -static const char string_AUTH_CONTENT_TYPE[] CMP_READ_ONLY = "application/x-www-form-urlencoded"; -static const char string_hmac_format[] CMP_READ_ONLY = "deviceName%s" "productKey%s" "random%s"; -static const char string_auth_req_format[] CMP_READ_ONLY = "productKey=%s&" "deviceName=%s&" "signMethod=%s&" "sign=%s&" "version=default&" "clientId=%s&" "random=%s&" "resources=mqtt"; -static const int int_random_length = 15; - -static char* genRandomString(int length) -{ - int flag, i; - char* str; - if ((str = (char*) LITE_malloc(length)) == NULL ) - { - CMP_ERR(cmp_log_error_memory); - return NULL; - } - - for (i = 0; i < length - 1; i++) - { - flag = rand() % 3; - switch (flag) - { - case 0: - str[i] = 'A' + HAL_Random(26); - break; - case 1: - str[i] = 'a' + HAL_Random(26); - break; - case 2: - str[i] = '0' + HAL_Random(10); - break; - default: - str[i] = 'x'; - break; - } - } - str[length - 1] = '\0'; - return str; -} -static int iotx_cmp_get_next_message_id(iotx_cmp_conntext_pt cmp_pt) -{ - if (cmp_pt->cmp_message_id == IOTX_CMP_MESSAGE_ID_MAX) - cmp_pt->cmp_message_id = 1; - - cmp_pt->cmp_message_id++; - - return cmp_pt->cmp_message_id; -} - -#if 1 -int _http_response(char *payload, - const int payload_len, - const char *request_string, - const char *url, - const int port_num, - const char *pkey - ) -{ -#define HTTP_POST_MAX_LEN (1024) -#define HTTP_RESP_MAX_LEN (1024) - - int ret = SUCCESS_RETURN; - char *requ_payload = NULL; - char *resp_payload = NULL; - httpclient_t httpc; - httpclient_data_t httpc_data; - - memset(&httpc, 0, sizeof(httpclient_t)); - memset(&httpc_data, 0, sizeof(httpclient_data_t)); - - /* todo */ - httpc.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n"; - - requ_payload = (char *)CMP_malloc(HTTP_POST_MAX_LEN); - if (NULL == requ_payload) { - CMP_ERR(cmp_log_error_memory); - return ERROR_MALLOC; - } - memset(requ_payload, 0, HTTP_POST_MAX_LEN); - - HAL_Snprintf(requ_payload, - HTTP_POST_MAX_LEN, - "%s", - request_string); - CMP_INFO(cmp_log_info_auth_payload_req, payload); - - resp_payload = (char *)LITE_malloc(HTTP_RESP_MAX_LEN); - if (!resp_payload) { - ret = FAIL_RETURN; - goto RETURN; - } - LITE_ASSERT(resp_payload); - memset(resp_payload, 0, HTTP_RESP_MAX_LEN); - - httpc_data.post_content_type = (char*)string_AUTH_CONTENT_TYPE; - httpc_data.post_buf = requ_payload; - httpc_data.post_buf_len = strlen(requ_payload); - httpc_data.response_buf = resp_payload; - httpc_data.response_buf_len = HTTP_RESP_MAX_LEN; - - ret = httpclient_common(&httpc, - url, - port_num, - pkey, - HTTPCLIENT_POST, - CONFIG_GUIDER_AUTH_TIMEOUT, - &httpc_data); - if (ret != 0) { - ret = FAIL_RETURN; - goto RETURN; - } - - memcpy(payload, httpc_data.response_buf, payload_len); - CMP_INFO(cmp_log_info_auth_payload_rsp, payload); - -RETURN: - if (requ_payload) { - LITE_free(requ_payload); - requ_payload = NULL; - } - if (resp_payload) { - LITE_free(resp_payload); - resp_payload = NULL; - } - - return ret; -} - - -static char *_set_auth_req_str(const char *product_key, const char *device_name, const char *client_id, const char *sign, const char *ts) -{ -#define AUTH_STRING_MAXLEN (1024) - - char *req = NULL; - - req = CMP_malloc(AUTH_STRING_MAXLEN); - memset(req, 0, AUTH_STRING_MAXLEN); - - HAL_Snprintf(req - , AUTH_STRING_MAXLEN - , string_auth_req_format - , product_key - , device_name -#ifdef USING_SHA1_IN_HMAC - , string_SHA_METHOD -#else - , string_MD5_METHOD -#endif - , sign - , client_id - , ts); - return req; -} - -static int _get_device_secret(const char *product_key, const char *device_name, const char *client_id, const char *guider_addr, const char *request_string) -{ - char payload[512] = {0}; - int ret = -1; - int ret_code = 0; - const char *pvalue; - - /* - { - "code" : 200, - "data" : { - "productKey" : "42Ze0mk3556498a1AlTP", - "deviceName" : "0d7fdeb9dc1f4344a2cc0d45edcb0bcb", - "deviceSecret" : "adsfweafdsf" - } - */ - strncpy(payload,request_string,strlen(request_string)); - _http_response(payload, - sizeof(payload), - request_string, - guider_addr, - 443, - iotx_ca_get() - ); - CMP_INFO(cmp_log_info_auth_rsp, payload); - - pvalue = LITE_json_value_of((char*)string_code, payload); - if (!pvalue) { - goto do_exit; - } - - ret_code = atoi(pvalue); - LITE_free(pvalue); - pvalue = NULL; - - if (200 != ret_code) { - log_err(cmp_log_error_ret_code, ret_code); - goto do_exit; - } - - pvalue = LITE_json_value_of((char*)string_pk, payload); - if (NULL == pvalue) { - goto do_exit; - } - if (0 != strncmp(pvalue, product_key, strlen(product_key))) { - LITE_free(pvalue); - goto do_exit; - } - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of((char*)string_dn, payload); - if (NULL == pvalue) { - goto do_exit; - } - if (0 != strncmp(pvalue, device_name, strlen(device_name))) { - LITE_free(pvalue); - goto do_exit; - } - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of((char*)string_ds, payload); - if (NULL == pvalue) { - goto do_exit; - } - HAL_SetDeviceSecret((char*)pvalue); - LITE_free(pvalue); - pvalue = NULL; - - ret = 0; - -do_exit: - if (pvalue) { - LITE_free(pvalue); - pvalue = NULL; - } - - return ret; -} - -static int _calc_hmac_signature( - const char *product_key, - const char *device_name, - char *hmac_sigbuf, - const int hmac_buflen, - const char *random) -{ - char signature[64]; - char hmac_source[512]; - int ret = FAIL_RETURN; - char product_secret[PRODUCT_SECRET_LEN + 1] = {0}; - - memset(signature, 0, sizeof(signature)); - memset(hmac_source, 0, sizeof(hmac_source)); - - HAL_GetProductSecret(product_secret); - - ret = HAL_Snprintf(hmac_source, - sizeof(hmac_source), - string_hmac_format, - device_name, - product_key, - random); - -#ifdef USING_SHA1_IN_HMAC - utils_hmac_sha1(hmac_source, strlen(hmac_source), - signature, - product_secret, - strlen(product_secret)); -#else - utils_hmac_md5(hmac_source, strlen(hmac_source), - signature, - product_secret, - strlen(product_secret)); -#endif - - memset(hmac_sigbuf, 0x0, hmac_buflen); - memcpy(hmac_sigbuf, signature, hmac_buflen); - - return ret; -} -#endif - - -int iotx_cmp_auth(const char *product_key, const char *device_name, const char *client_id) -{ - char *req_str = NULL; - char guider_sign[40+1] = {0}; - char *s_random = NULL; - s_random = genRandomString(int_random_length); - // todo string_TIMESTAMP -> random - _calc_hmac_signature(product_key, device_name, guider_sign, sizeof(guider_sign), s_random); - req_str = _set_auth_req_str(product_key, device_name, client_id, guider_sign, s_random); - CMP_INFO(cmp_log_info_auth_req, req_str); - - if (SUCCESS_RETURN != _get_device_secret(product_key, device_name, client_id, string_AUTH_URL, req_str)) { - if (req_str) LITE_free(req_str); - if (s_random) LITE_free(s_random); - CMP_ERR(cmp_log_error_auth); - return FAIL_RETURN; - } - if (req_str) LITE_free(req_str); - if (s_random) LITE_free(s_random); - return SUCCESS_RETURN; -} - - -#ifdef CMP_SUPPORT_TOPIC_DISPATCH -int iotx_cmp_parse_payload(void* payload, - int payload_length, - iotx_cmp_message_info_pt msg) -{ - char* payload_pt = (char*)payload; - char* node = NULL; - - if (NULL == payload || NULL == msg || 0 == payload_length) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - switch (msg->message_type) { - case IOTX_CMP_MESSAGE_RAW: { - CMP_INFO(cmp_log_info_raw_data); - msg->code = 0; - msg->parameter = CMP_malloc(payload_length + 1); - if (NULL == msg->parameter) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->parameter, 0x0, payload_length); - memcpy(msg->parameter, payload, payload_length); - msg->parameter_length = payload_length; - msg->method = NULL; - msg->id = 0; - return SUCCESS_RETURN; - } - - case IOTX_CMP_MESSAGE_RESPONSE: { - node = LITE_json_value_of((char*)string_id, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_id); - return FAIL_RETURN; - } - - msg->id = atoi(node); - LITE_free(node); - node = NULL; - - /* parse code */ - node = LITE_json_value_of((char*)string_code, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_code); - return FAIL_RETURN; - } - msg->code = atoi(node); - LITE_free(node); - node = NULL; - - /* parse data */ - node = LITE_json_value_of((char*)string_data, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_data); - return FAIL_RETURN; - } - msg->parameter = CMP_malloc(strlen(node) + 1); - if (NULL == msg->parameter) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->parameter, 0x0, strlen(node)); - strncpy(msg->parameter, node, strlen(node)); - msg->parameter_length = strlen(msg->parameter); - LITE_free(node); - node = NULL; - - msg->method = NULL; - return SUCCESS_RETURN; - } - - case IOTX_CMP_MESSAGE_REQUEST: { - node = LITE_json_value_of((char*)string_id, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_id); - return FAIL_RETURN; - } - - msg->id = atoi(node); - LITE_free(node); - node = NULL; - - /* parse params */ - node = LITE_json_value_of((char*)string_params, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_params); - return FAIL_RETURN; - } - - msg->parameter = CMP_malloc(strlen(node) + 1); - if (NULL == msg->parameter) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->parameter, 0x0, strlen(node)); - strncpy(msg->parameter, node, strlen(node)); - msg->parameter_length = strlen(msg->parameter); - LITE_free(node); - node = NULL; - - /* parse method */ - node = LITE_json_value_of((char*)string_method, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_method); - return FAIL_RETURN; - } - msg->method = CMP_malloc(strlen(node) + 1); - if (NULL == msg->method ) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->method , 0x0, strlen(node)); - strncpy(msg->method , node, strlen(node)); - LITE_free(node); - node = NULL; - - msg->code = 0; - return SUCCESS_RETURN; - } - - default: - CMP_ERR(cmp_log_error_type); - return FAIL_RETURN; - } - return SUCCESS_RETURN; -} -#else -int iotx_cmp_parse_payload(void* payload, - int payload_length, - iotx_cmp_message_info_pt msg) -{ - char* payload_pt = (char*)payload; - char* node = NULL; - - if (NULL == payload || NULL == msg || 0 == payload_length) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - node = LITE_json_value_of((char*)string_id, payload_pt); - if (node == NULL) { - msg->message_type = IOTX_CMP_MESSAGE_RAW; - msg->code = 0; - msg->parameter = CMP_malloc(payload_length + 1); - if (NULL == msg->parameter) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->parameter, 0x0, payload_length); - memcpy(msg->parameter, payload, payload_length); - msg->parameter_length = payload_length; - msg->method = NULL; - msg->id = 0; - return SUCCESS_RETURN; - } - - msg->id = atoi(node); - LITE_free(node); - node = NULL; - - /* parse code */ - node = LITE_json_value_of((char*)string_code, payload_pt); - if (node == NULL) { - msg->message_type = IOTX_CMP_MESSAGE_REQUEST; - - /* parse params */ - node = LITE_json_value_of((char*)string_params, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_params); - return FAIL_RETURN; - } - - msg->parameter = CMP_malloc(strlen(node) + 1); - if (NULL == msg->parameter) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->parameter, 0x0, strlen(node)); - strncpy(msg->parameter, node, strlen(node)); - msg->parameter_length = strlen(msg->parameter); - LITE_free(node); - node = NULL; - - /* parse method */ - node = LITE_json_value_of((char*)string_method, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_method); - return FAIL_RETURN; - } - msg->method = CMP_malloc(strlen(node) + 1); - if (NULL == msg->method ) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->method , 0x0, strlen(node)); - strncpy(msg->method , node, strlen(node)); - LITE_free(node); - node = NULL; - - msg->code = 0; - return SUCCESS_RETURN; - } - msg->code = atoi(node); - LITE_free(node); - node = NULL; - - /* parse code */ - node = LITE_json_value_of((char*)string_code, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_code); - return FAIL_RETURN; - } - msg->code = atoi(node); - LITE_free(node); - node = NULL; - - /* parse data */ - node = LITE_json_value_of((char*)string_data, payload_pt); - if (node == NULL) { - CMP_ERR(cmp_log_error_parse_data); - return FAIL_RETURN; - } - msg->parameter = CMP_malloc(strlen(node) + 1); - if (NULL == msg->parameter) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node); - return FAIL_RETURN; - } - memset(msg->parameter, 0x0, strlen(node)); - strncpy(msg->parameter, node, strlen(node)); - msg->parameter_length = strlen(msg->parameter); - LITE_free(node); - node = NULL; - - msg->method = NULL; - return SUCCESS_RETURN; -} -#endif - - -int iotx_cmp_splice_payload(void* payload, - int* payload_length, - int id, - iotx_cmp_message_info_pt msg) -{ - if (NULL == payload || NULL == payload_length || NULL == msg) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - switch(msg->message_type) { - case IOTX_CMP_MESSAGE_RESPONSE: { - HAL_Snprintf(payload, - (*payload_length), - string_response_format, - id, - msg->code, - (char*)msg->parameter); - (*payload_length) = strlen(payload); - } - break; - - case IOTX_CMP_MESSAGE_REQUEST: { - HAL_Snprintf(payload, - (*payload_length), - string_request_format, - id, - (char*)msg->parameter, - msg->method); - (*payload_length) = strlen(payload); - } - break; - - case IOTX_CMP_MESSAGE_RAW: { - memcpy(payload, msg->parameter, msg->parameter_length); - (*payload_length) = msg->parameter_length; - } - break; - - default: - break; - } - - return SUCCESS_RETURN; -} - - -void iotx_cmp_free_message_info(iotx_cmp_message_info_pt message_info) -{ - if (message_info->URI) - LITE_free(message_info->URI); - if (message_info->parameter) - LITE_free(message_info->parameter); - if (message_info->method) - LITE_free(message_info->method); -} - - -void iotx_cmp_response_func(void* pcontext, iotx_cmp_message_info_pt message_info) -{ - iotx_cmp_send_peer_pt peer = NULL; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)pcontext; -#ifdef CMP_SUPPORT_TOPIC_DISPATCH - iotx_cmp_mapping_pt mapping = NULL; -#else - iotx_cmp_event_msg_t msg_event = {0}; - iotx_cmp_new_data_t new_data = {0}; -#endif - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - if (NULL == cmp_pt || NULL == message_info) { - CMP_ERR(cmp_log_error_parameter); - return; - } - -#ifdef CMP_SUPPORT_TOPIC_DISPATCH - /* find mapping */ - mapping = iotx_cmp_find_mapping(cmp_pt, message_info->URI, strlen(message_info->URI)); - - if (NULL == mapping) { - CMP_WARNING(cmp_log_warning_not_mapping); - iotx_cmp_free_message_info(message_info); - return; - } - - if (NULL == mapping->func && NULL== mapping->mail_box) { - CMP_WARNING(cmp_log_warning_not_func); - iotx_cmp_free_message_info(message_info); - return; - } - - peer = CMP_malloc(sizeof(iotx_cmp_send_peer_t)); - if (NULL == peer) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_message_info(message_info); - return; - } - - memset(peer, 0x0, sizeof(iotx_cmp_send_peer_t)); - strncpy(peer->product_key, pdevice_info->product_key, strlen(pdevice_info->product_key)); - strncpy(peer->device_name, pdevice_info->device_name, strlen(pdevice_info->device_name)); - - if (mapping->func) mapping->func(peer, message_info, mapping->user_data); - if (peer) LITE_free(peer); - iotx_cmp_free_message_info(message_info); -#else - peer = CMP_malloc(sizeof(iotx_cmp_send_peer_t)); - if (NULL == peer) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_message_info(message_info); - return; - } - - memset(peer, 0x0, sizeof(iotx_cmp_send_peer_t)); - strncpy(peer->product_key, pdevice_info->product_key, strlen(pdevice_info->product_key)); - strncpy(peer->device_name, pdevice_info->device_name, strlen(pdevice_info->device_name)); - - new_data.message_info = message_info; - new_data.peer = peer; - msg_event.event_id = IOTX_CMP_EVENT_NEW_DATA_RECEIVED; - msg_event.msg = &new_data; - - iotx_cmp_trigger_event_callback(cmp_pt, &msg_event); - - LITE_free(peer); - iotx_cmp_free_message_info(message_info); -#endif -} - - -int iotx_cmp_parse_URI(char* URI, int URI_length, char* URI_param, iotx_cmp_uri_types_t* uri_type) -{ - char pk_dv[CMP_PRODUCT_KEY_LEN + CMP_DEVICE_NAME_LEN + 10] = {0}; - char* temp = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - if (NULL == URI || NULL == URI_param) return FAIL_RETURN; - - if (0 == strlen(URI)) return FAIL_RETURN; - - HAL_Snprintf(pk_dv, - CMP_PRODUCT_KEY_LEN + CMP_DEVICE_NAME_LEN + 10, - string_SYS_URI, - pdevice_info->product_key, - pdevice_info->device_name); - - /* find /sys/product_key/device_name */ - temp = strstr(URI, pk_dv); - - if (temp) { - temp = URI + strlen(pk_dv); - strncpy(URI_param, temp, URI_length - strlen(pk_dv)); - (*uri_type) = IOTX_CMP_URI_SYS; - CMP_INFO(cmp_log_info_URI_sys); - CMP_INFO(cmp_log_info_URI_1, URI_length - strlen(pk_dv), URI_param); - return SUCCESS_RETURN; - } - - memset(pk_dv, 0x0, CMP_PRODUCT_KEY_LEN + CMP_DEVICE_NAME_LEN + 10); - HAL_Snprintf(pk_dv, - CMP_PRODUCT_KEY_LEN + CMP_DEVICE_NAME_LEN + 10, - string_EXT_URI, - pdevice_info->product_key, - pdevice_info->device_name); - - /* find /ext/product_key/device_name */ - temp = strstr(URI, pk_dv); - - if (temp) { - temp = URI + strlen(pk_dv); - strncpy(URI_param, temp, URI_length - strlen(pk_dv)); - (*uri_type) = IOTX_CMP_URI_EXT; - CMP_INFO(cmp_log_info_URI_ext); - CMP_INFO(cmp_log_info_URI_1, URI_length - strlen(pk_dv), URI_param); - return SUCCESS_RETURN; - } - - strncpy(URI_param, URI, URI_length); - (*uri_type) = IOTX_CMP_URI_UNDEFINE; - CMP_INFO(cmp_log_info_URI_undefined); - CMP_INFO(cmp_log_info_URI_1, URI_length, URI_param); - return SUCCESS_RETURN; -} - - -int iotx_cmp_splice_URI(char* URI, int* URI_length, const char* URI_param, iotx_cmp_uri_types_t uri_type) -{ - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - if (NULL == URI || NULL == URI_length) return FAIL_RETURN; - - if (0 == strlen(URI_param)) return FAIL_RETURN; - - memset(URI, 0x0, (*URI_length)); - - switch(uri_type) { - case IOTX_CMP_URI_SYS: { - HAL_Snprintf(URI, - CMP_TOPIC_LEN_MAX, - string_SYS_URI_1, - pdevice_info->product_key, - pdevice_info->device_name, - URI_param); - } - break; - - case IOTX_CMP_URI_EXT: { - HAL_Snprintf(URI, - CMP_TOPIC_LEN_MAX, - string_EXT_URI_1, - pdevice_info->product_key, - pdevice_info->device_name, - URI_param); - } - break; - - default: { - strncpy(URI, URI_param, strlen(URI_param)); - } - break; - } - - (*URI_length) = strlen(URI); - - CMP_INFO(cmp_log_info_URI_length, *URI_length); - CMP_INFO(cmp_log_info_URI, URI); - - return SUCCESS_RETURN; -} - -iotx_cmp_connectivity_pt iotx_cmp_find_connectivity(iotx_cmp_conntext_pt cmp_pt, iotx_cmp_send_peer_pt target) -{ - if (NULL == cmp_pt->connectivity_list) - return NULL; - - if (NULL == target) { - return cmp_pt->connectivity_list->node; - } - - return NULL; -} - -int iotx_cmp_add_connectivity(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_connectivity_pt connectivity) -{ - iotx_cmp_connectivity_list_pt conn = cmp_pt->connectivity_list; - iotx_cmp_connectivity_list_pt new_conn = NULL; - - if (NULL == cmp_pt->connectivity_list) { - - cmp_pt->connectivity_list = CMP_malloc(sizeof(iotx_cmp_connectivity_list_t)); - - if (NULL == cmp_pt->connectivity_list) { - return FAIL_RETURN; - } - memset(cmp_pt->connectivity_list, 0x0, sizeof(iotx_cmp_connectivity_list_t)); - - cmp_pt->connectivity_list->node = connectivity; - cmp_pt->connectivity_list->next = NULL; - return SUCCESS_RETURN; - } - - while(conn->next) { - conn = conn->next; - } - - new_conn = CMP_malloc(sizeof(iotx_cmp_connectivity_list_t)); - if (NULL == cmp_pt->connectivity_list) { - return FAIL_RETURN; - } - memset(new_conn->node, 0x0, sizeof(iotx_cmp_connectivity_list_t)); - new_conn->node = connectivity; - new_conn->next = NULL; - conn->next = new_conn; - - return SUCCESS_RETURN; -} - -int iotx_cmp_add_connectivity_all(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_init_param_pt pparam) -{ - void* connectivity = NULL; - - /* cloud connection */ -#ifdef CMP_VIA_MQTT_DIRECT - connectivity = iotx_cmp_mqtt_direct_init(cmp_pt, pparam); -#else - connectivity = iotx_cmp_cloud_conn_init(cmp_pt, pparam); -#endif - if (NULL == connectivity) return FAIL_RETURN; - - if (FAIL_RETURN == iotx_cmp_add_connectivity(cmp_pt, connectivity)) return FAIL_RETURN; - - /* local connection */ -#ifdef CMP_SUPPORT_LOCAL_CONN - connectivity = iotx_cmp_local_conn_init(cmp_pt, pparam); - if (NULL == connectivity) { - return FAIL_RETURN; - } - - if (NULL == iotx_cmp_add_connectivity(cmp_pt, connectivity)) { - return FAIL_RETURN; - } -#endif - - return SUCCESS_RETURN; -} - -int iotx_cmp_remove_connectivity_all(iotx_cmp_conntext_pt cmp_pt) -{ - iotx_cmp_connectivity_list_pt conn_list = cmp_pt->connectivity_list; - iotx_cmp_connectivity_list_pt curr_conn = NULL; - - if (NULL == cmp_pt->connectivity_list) return SUCCESS_RETURN; - - while(conn_list) { - if (FAIL_RETURN == conn_list->node->deinit_func(conn_list->node)) { - CMP_ERR(cmp_log_error_fail); - } - conn_list->node = NULL; - - curr_conn = conn_list; - conn_list = conn_list->next; - LITE_free(curr_conn); - } - cmp_pt->connectivity_list = NULL; - - return SUCCESS_RETURN; -} - - -iotx_cmp_mapping_pt iotx_cmp_get_mapping_node() -{ -#ifndef CMP_SUPPORT_TOPIC_DISPATCH - return NULL; - -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - -#ifdef CMP_MAPPING_USE_POOL - int i = 0; - for (i = 0; i < CMP_SUPPORT_MAX_MAPPING_SIZE; i++) { - if (g_cmp_mapping_list[i].is_used == 0) { - g_cmp_mapping_list[i].is_used = 1; - return &g_cmp_mapping_list[i]; - } - } - return NULL; -#else - iotx_cmp_mapping_pt node = NULL; - - node = CMP_malloc(sizeof(iotx_cmp_mapping_t)); - if (NULL == node) return NULL; - - memset(node, 0x0, sizeof(iotx_cmp_mapping_t)); - return node; -#endif - -#endif /* CMP_SUPPORT_TOPIC_DISPATCH */ -} - -int iotx_cmp_free_mapping_node(iotx_cmp_mapping_pt node) -{ -#ifndef CMP_SUPPORT_TOPIC_DISPATCH - return SUCCESS_RETURN; -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - if (NULL == node) return FAIL_RETURN; - -#ifdef CMP_MAPPING_USE_POOL - if (node->is_used == 1) { - node->is_used = 0; - memset(node, 0x0, sizeof(iotx_cmp_mapping_t)); - return SUCCESS_RETURN; - } - - return FAIL_RETURN; -#else /* CMP_MAPPING_USE_POOL */ - LITE_free(node); - return SUCCESS_RETURN; -#endif /* CMP_MAPPING_USE_POOL */ - -#endif /* CMP_SUPPORT_TOPIC_DISPATCH */ -} - - -int iotx_cmp_add_mapping(iotx_cmp_conntext_pt cmp_pt, - char* URI, - iotx_cmp_message_types_t type, - iotx_cmp_register_func_fpt func, - void* user_data, - void* mail_box) -{ -#ifndef CMP_SUPPORT_TOPIC_DISPATCH - return SUCCESS_RETURN; -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - iotx_cmp_mapping_pt mapping = NULL; - - if (NULL == cmp_pt || NULL == URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - mapping = iotx_cmp_get_mapping_node(); - if (NULL == mapping) return FAIL_RETURN; - - mapping->URI = CMP_malloc(strlen(URI) + 1); - if (NULL == mapping->URI) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_mapping_node(mapping); - return FAIL_RETURN; - } - memset(mapping->URI, 0x0, strlen(URI) + 1); - strncpy(mapping->URI, URI, strlen(URI)); - - mapping->type = type; - mapping->func = func; - mapping->user_data = user_data; - mapping->mail_box = mail_box; - - mapping->next = cmp_pt->mapping_list; - cmp_pt->mapping_list = mapping; - - return SUCCESS_RETURN; -#endif /* CMP_SUPPORT_TOPIC_DISPATCH */ -} - - -/* remove */ -int iotx_cmp_remove_mapping(iotx_cmp_conntext_pt cmp_pt, char* URI) -{ -#ifndef CMP_SUPPORT_TOPIC_DISPATCH - return SUCCESS_RETURN; -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - iotx_cmp_mapping_pt mapping = NULL; - iotx_cmp_mapping_pt pre_mapping = NULL; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - pre_mapping = mapping = cmp_pt->mapping_list; - - /* first one is match */ - if (0 == strncmp(URI, mapping->URI, strlen(URI))) { - if (NULL == mapping->next) { - cmp_pt->mapping_list = NULL; - } else { - cmp_pt->mapping_list = mapping->next; - } - } - - while (mapping) { - if (0 == strncmp(URI, mapping->URI, strlen(URI))) { - CMP_INFO(cmp_log_info_remove_mapping); - pre_mapping->next = mapping->next; - - LITE_free(mapping->URI); - iotx_cmp_free_mapping_node(mapping); - return SUCCESS_RETURN; - } - - pre_mapping = mapping; - mapping = mapping->next; - } - - return FAIL_RETURN; -#endif /* CMP_SUPPORT_TOPIC_DISPATCH */ -} - - -/* remove all */ -int iotx_cmp_remove_mapping_all(iotx_cmp_conntext_pt cmp_pt) -{ -#ifndef CMP_SUPPORT_TOPIC_DISPATCH - return SUCCESS_RETURN; -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - iotx_cmp_mapping_pt mapping = NULL; - iotx_cmp_mapping_pt next_mapping = NULL; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - next_mapping = mapping = cmp_pt->mapping_list; - - while (mapping) { - next_mapping = mapping->next; - - LITE_free(mapping->URI); - iotx_cmp_free_mapping_node(mapping); - - mapping = next_mapping; - } - - cmp_pt->mapping_list = NULL; - - return FAIL_RETURN; -#endif /* CMP_SUPPORT_TOPIC_DISPATCH */ -} - -iotx_cmp_mapping_pt iotx_cmp_find_mapping(iotx_cmp_conntext_pt cmp_pt, char* URI, int URI_length) -{ -#ifndef CMP_SUPPORT_TOPIC_DISPATCH - return NULL; -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - iotx_cmp_mapping_pt mapping = NULL; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - mapping = cmp_pt->mapping_list; - - while (mapping) { - if ((0 == strncmp(URI, mapping->URI, URI_length)) || (0 != strstr(mapping->URI, URI))) { - return mapping; - } - - mapping = mapping->next; - } - - return NULL; -#endif /* CMP_SUPPORT_TOPIC_DISPATCH */ -} - - -int iotx_cmp_register_service(iotx_cmp_conntext_pt cmp_pt, - char* URI, - iotx_cmp_message_types_t type, - iotx_cmp_register_func_fpt register_func, - void* user_data, - void* mail_box) -{ - iotx_cmp_connectivity_list_pt conn_list = NULL; -#ifdef CMP_SUPPORT_TOPIC_DISPATCH - iotx_cmp_mapping_pt mapping = NULL; -#endif - - if (NULL == cmp_pt || NULL == URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } -#ifdef CMP_SUPPORT_TOPIC_DISPATCH - - if (FAIL_RETURN == iotx_cmp_add_mapping(cmp_pt, URI, type, register_func, user_data, mail_box)) { - iotx_cmp_event_msg_t event; - iotx_cmp_event_result_t result_pt = {0}; - - result_pt.result = -1; - result_pt.URI = URI; - event.event_id = IOTX_CMP_EVENT_REGISTER_RESULT; - event.msg = (void*)&result_pt; - - CMP_ERR(cmp_log_error_fail_1); - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - return FAIL_RETURN; - } - - mapping = iotx_cmp_find_mapping(cmp_pt, URI, strlen(URI)); - - conn_list = cmp_pt->connectivity_list; - - while(conn_list && conn_list->node) { - if (0 == conn_list->node->is_connected) - return FAIL_RETURN; - else if (conn_list->node->register_func) - conn_list->node->register_func(cmp_pt, conn_list->node, mapping->URI); - - conn_list = conn_list->next; - } - -#else /* CMP_SUPPORT_TOPIC_DISPATCH */ - conn_list = cmp_pt->connectivity_list; - - while(conn_list && conn_list->node) { - if (0 == conn_list->node->is_connected) - return FAIL_RETURN; - else if (conn_list->node->register_func) - conn_list->node->register_func(cmp_pt, conn_list->node, URI); - - conn_list = conn_list->next; - } -#endif - - return SUCCESS_RETURN; -} - - -int iotx_cmp_unregister_service(iotx_cmp_conntext_pt cmp_pt, char* URI) -{ - iotx_cmp_connectivity_list_pt conn_list = NULL; - - if (NULL == cmp_pt || NULL == URI) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - conn_list = cmp_pt->connectivity_list; - - while(conn_list) { - if (0 == conn_list->node->is_connected) - return FAIL_RETURN; - else if (conn_list->node->unregister_func) - conn_list->node->unregister_func(cmp_pt, conn_list->node, URI); - - conn_list = conn_list->next; - } - - if (FAIL_RETURN == iotx_cmp_remove_mapping(cmp_pt, URI)) { - CMP_ERR(cmp_log_error_fail); - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - -static int iotx_cmp_send_data_to_cloud(iotx_cmp_conntext_pt cmp_pt, - void* connectivity_pt, - char* URI, - iotx_cmp_message_ack_types_t ack_type, - void* payload, - int payload_length) -{ - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - - if (NULL != connectivity && connectivity->is_connected == 1) { -#ifdef CMP_VIA_MQTT_DIRECT - return iotx_cmp_mqtt_direct_send(cmp_pt, connectivity_pt, URI, ack_type, payload, payload_length); -#else - return iotx_cmp_cloud_conn_send(cmp_pt, connectivity_pt, URI, ack_type, payload, payload_length); -#endif - } - return FAIL_RETURN; -} - -#ifdef CMP_SUPPORT_LOCAL_CONN_CONN - -static int iotx_cmp_send_dispatch(iotx_cmp_send_peer_pt target) -{ - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - if (target == NULL) { - return 1; - } - - if (0 == strncmp(target->product_key, pdevice_info->product_key, strlen(target->product_key)) && - 0 == strncmp(target->device_name, pdevice_info->device_name, strlen(target->device_name))) { - return 2; - } - - return 3; -} - -static int iotx_cmp_send_data_to_local(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_send_peer_pt target, - char* URI, - iotx_cmp_message_ack_types_t ack_type, - void* payload, - int payload_length) -{ - return iotx_cmp_local_conn_send(cmp_pt, URI, ack_type, payload, payload_length); -} - -static int iotx_cmp_send_data_to_all(iotx_cmp_conntext_pt cmp_pt, - char* URI, - iotx_cmp_message_ack_types_t ack_type, - void* payload, - int payload_length) -{ - if (FAIL_RETURN == iotx_cmp_send_data_to_cloud(cmp_pt, - iotx_cmp_find_connectivity(cmp_pt, NULL), - URI, - ack_type, - payload, - payload_length)) { - CMP_ERR(cmp_log_error_fail); - } - - /* iotx_cmp_send_data_to_local */ - return FAIL_RETURN; -} -#endif - -int iotx_cmp_parse_message(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_message_info_pt message_info, - char** URI, - void** payload, - int* payload_length) -{ - int URI_length = CMP_TOPIC_LEN_MAX; - - (*URI) = CMP_malloc(CMP_TOPIC_LEN_MAX); - if (NULL == (*URI)) { - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - - if (FAIL_RETURN == iotx_cmp_splice_URI((*URI), &URI_length, message_info->URI, message_info->URI_type)) { - CMP_ERR(cmp_log_error_splice_payload); - LITE_free((*URI)); - - return FAIL_RETURN; - } - - (*payload_length) = message_info->parameter_length + 10 + - strlen(string_request_format); - - if (message_info->method) - (*payload_length) += strlen(message_info->method); - - CMP_INFO(cmp_log_info_payload_length, (*payload_length)); - - (*payload) = CMP_malloc((*payload_length)); - if (NULL == (*payload)) { - CMP_ERR(cmp_log_error_memory); - LITE_free((*URI)); - LITE_free((*payload)); - return FAIL_RETURN; - } - - if (0 == message_info->id) { - message_info->id = iotx_cmp_get_next_message_id(cmp_pt); - } - - if (FAIL_RETURN == iotx_cmp_splice_payload((*payload), payload_length, message_info->id, message_info)) { - CMP_ERR(cmp_log_error_parse_payload); - LITE_free((*URI)); - LITE_free((*payload)); - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - - -int iotx_cmp_send_data(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_send_peer_pt target, - char* URI, - iotx_cmp_message_ack_types_t ack_type, - void* payload, - int payload_length) -{ - int rc = -1; - -#ifdef CMP_SUPPORT_LOCAL_CONN_CONN - int peer = -1; - peer = iotx_cmp_send_dispatch(target); - switch (peer) { - /* send all */ - case 1: { - rc = iotx_cmp_send_data_to_all(cmp_pt, URI, ack_type, payload, payload_length); - } - break; - - /* send cloud */ - case 2:{ - rc = iotx_cmp_send_data_to_cloud(cmp_pt, - iotx_cmp_find_connectivity(cmp_pt, NULL), - URI, - ack_type, - payload, - payload_length); - } - break; - - case 3:{ - rc = iotx_cmp_send_data_to_local(cmp_pt, target, URI, ack_type, payload, payload_length); - } - break; - default:{ - return FAIL_RETURN; - } - break; - } -#else - rc = iotx_cmp_send_data_to_cloud(cmp_pt, - iotx_cmp_find_connectivity(cmp_pt, NULL), - URI, - ack_type, - payload, - payload_length); -#endif - if (rc < 0) { - iotx_cmp_event_msg_t event; - iotx_cmp_event_result_t result_pt = {0}; - - result_pt.result = -1; - result_pt.URI = URI; - event.event_id = IOTX_CMP_EVENT_SEND_RESULT; - event.msg = (void*)&result_pt; - - CMP_ERR(cmp_log_error_fail_rc, rc); - - /* todo: send fail is not a event */ - iotx_cmp_trigger_event_callback(cmp_pt, &event); - } - - LITE_free(URI); - LITE_free(payload); - return rc < 0 ? FAIL_RETURN : SUCCESS_RETURN; -} - - -int iotx_cmp_trigger_event_callback(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_event_msg_pt msg) -{ - if (cmp_pt->event_callback_list) { - iotx_cmp_event_callback_list_pt event_callback = cmp_pt->event_callback_list; - - while (event_callback) { - if(event_callback->node && event_callback->node->event_func) - event_callback->node->event_func(cmp_pt, msg, event_callback->node->user_data); - event_callback = event_callback->next; - } - } else { - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - - -#ifdef CMP_SUPPORT_MULTI_THREAD - -iotx_cmp_process_list_node_pt iotx_cmp_get_list_node(iotx_cmp_process_types_t type) -{ -#ifdef CMP_PROCESS_NODE_USE_POOL - int i = 0; - iotx_cmp_process_list_node_pt list = NULL; - - if (IOTX_CMP_PROCESS_TYPE_CLOUD == type) { - list = g_cmp_cloud_process_node_list; - } -#ifdef CMP_SUPPORT_LOCAL_CONN - else if (IOTX_CMP_PROCESS_TYPE_LOCAL == type) { - list = g_cmp_local_process_node_list; - } -#endif - else { - return NULL; - } - - for (i = 0; i < CMP_SUPPORT_MAX_PROCESS_NODE_SIZE; i++) { - if (list[i].is_used == 0) { - list[i].is_used = 1; - return &list[i]; - } - } - return NULL; -#else - iotx_cmp_process_list_node_pt node = NULL; - node = CMP_malloc(sizeof(iotx_cmp_process_list_node_t)); - if (NULL == node) { - return NULL; - } - - memset(node, 0x0, sizeof(iotx_cmp_process_list_node_t)); - return node; -#endif -} - -int iotx_cmp_free_list_node(iotx_cmp_process_list_node_pt node) -{ - if (NULL == node) return FAIL_RETURN; - -#ifdef CMP_PROCESS_NODE_USE_POOL - if (node->is_used == 1) { - node->is_used = 0; - memset(node, 0x0, sizeof(iotx_cmp_process_list_node_t)); - return SUCCESS_RETURN; - } - - return FAIL_RETURN; -#else - LITE_free(node); - return SUCCESS_RETURN; -#endif -} - -int iotx_cmp_free_list_node_all(iotx_cmp_conntext_pt cmp_pt) -{ - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_list_node_pt next_node = NULL; - - if (NULL == cmp_pt || NULL == cmp_pt->process_cloud_list) return FAIL_RETURN; - - node = cmp_pt->process_cloud_list->header; - - while (node) { - switch (node->type) - { - case IOTX_CMP_PROCESS_CLOUD_REGISTER: { - iotx_cmp_process_register_pt register_pt = (iotx_cmp_process_register_pt)node->msg; - LITE_free(register_pt->URI); - LITE_free(register_pt); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_UNREGISTER: { - char* URI = (char*)node->msg; - LITE_free(URI); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_SEND: { - iotx_cmp_process_send_pt send_pt = (iotx_cmp_process_send_pt)node->msg; - if (send_pt->URI) - LITE_free(send_pt->URI); - - if (send_pt->payload) - LITE_free(send_pt->payload); - - if (send_pt->target) - LITE_free(send_pt->target); - - LITE_free(send_pt); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT: - case IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT: { - iotx_cmp_process_register_result_pt register_pt = (iotx_cmp_process_register_result_pt)node->msg; - #ifndef CMP_VIA_MQTT_DIRECT - LITE_free(register_pt->URI); - #endif - LITE_free(register_pt); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_NEW_DATA: { - iotx_cmp_message_info_pt message_info = (iotx_cmp_message_info_pt)node->msg; - iotx_cmp_free_message_info(message_info); - LITE_free(message_info); - break; - } - - default: - break; - } - next_node = node->next; - - #ifdef CMP_PROCESS_NODE_USE_POOL - if (node->is_used == 1) { - node->is_used = 0; - memset(node, 0x0, sizeof(iotx_cmp_process_list_node_t)); - } - #else - LITE_free(node); - #endif - - node = next_node; - } - - LITE_free(cmp_pt->process_cloud_list); - -#ifdef CMP_SUPPORT_LOCAL_CONN - node = cmp_pt->process_local_list->header; - - while (node) { - switch (node->type) - { - case IOTX_CMP_PROCESS_LOCAL_ADD_DEVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_REMOVE_DEVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_ADD_SERVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_REMOVE_SERVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_ADD_SERVICE_RESULT: - case IOTX_CMP_PROCESS_LOCAL_REMOVE_SERVICE_RESULT: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_NEW_DATA: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_SEND: { - break; - } - - default: - break; - } - - #ifdef CMP_PROCESS_NODE_USE_POOL - if (node->is_used == 1) { - node->is_used = 0; - memset(node, 0x0, sizeof(iotx_cmp_process_list_node_t)); - } - #else - LITE_free(node); - #endif - node = node->next; - } - - LITE_free(cmp_pt->process_local_list); -#endif - - return SUCCESS_RETURN; -} - -/* node is in */ -int iotx_cmp_process_list_push(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_process_types_t type, - iotx_cmp_process_list_node_pt node) -{ - void* lock = NULL; - iotx_cmp_process_list_pt list = NULL; - - if (NULL == cmp_pt || NULL == node) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - if (IOTX_CMP_PROCESS_TYPE_CLOUD == type) { - lock = cmp_pt->process_cloud_lock; - list = cmp_pt->process_cloud_list; - } -#ifdef CMP_SUPPORT_LOCAL_CONN - else if (IOTX_CMP_PROCESS_TYPE_LOCAL == type) { - lock = cmp_pt->process_local_lock; - list = cmp_pt->process_local_list; - } -#endif - else { - return FAIL_RETURN; - } - - HAL_MutexLock(lock); - - if (NULL == list) { - list = CMP_malloc(sizeof(iotx_cmp_process_list_t)); - - if (NULL == list) { - HAL_MutexUnlock(lock); - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - - list->header = list->tailer = NULL; - list->size = 0; - - if (IOTX_CMP_PROCESS_TYPE_CLOUD == type) { - cmp_pt->process_cloud_list = list; - } - #ifdef CMP_SUPPORT_LOCAL_CONN - else if (IOTX_CMP_PROCESS_TYPE_LOCAL == type) { - cmp_pt->process_local_list = list; - } - #endif - } - - if (list->size == 0) { - list->header = list->tailer = node; - list->size = 1; - } else if (list->size == CMP_SUPPORT_MAX_PROCESS_NODE_SIZE) { - HAL_MutexUnlock(lock); - CMP_ERR(cmp_log_error_process); - return FAIL_RETURN; - } else { - node->pre = list->tailer; - list->tailer->next = node; - list->tailer = node; - list->size++; - } - - HAL_MutexUnlock(lock); - - return SUCCESS_RETURN; -} - - -iotx_cmp_process_list_node_pt iotx_cmp_process_list_pop(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_process_types_t type) -{ - void* lock = NULL; - iotx_cmp_process_list_pt list = NULL; - iotx_cmp_process_list_node_pt node = NULL; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - - if (IOTX_CMP_PROCESS_TYPE_CLOUD == type) { - lock = cmp_pt->process_cloud_lock; - list = cmp_pt->process_cloud_list; - } -#ifdef CMP_SUPPORT_LOCAL_CONN - else if (IOTX_CMP_PROCESS_TYPE_LOCAL == type) { - lock = cmp_pt->process_local_lock; - list = cmp_pt->process_local_list; - } -#endif - - if (NULL == list) { - CMP_ERR(cmp_log_error_status); - return NULL; - } - - HAL_MutexLock(lock); - - if (list->size == 1) { - node = list->header; - list->header = list->tailer = NULL; - list->size = 0; - LITE_free(list); - list = NULL; - if (IOTX_CMP_PROCESS_TYPE_CLOUD == type) { - cmp_pt->process_cloud_list = NULL; - } - #ifdef CMP_SUPPORT_LOCAL_CONN - else if (IOTX_CMP_PROCESS_TYPE_LOCAL == type) { - cmp_pt->process_local_list = NULL; - } - #endif - } else { - node = list->header; - list->header = list->header->next; - list->header->pre = NULL; - list->size--; - } - - HAL_MutexUnlock(lock); - return node; -} - - -int iotx_cmp_process_list_get_size(iotx_cmp_conntext_pt cmp_pt, - iotx_cmp_process_types_t type) -{ - iotx_cmp_process_list_pt list = NULL; - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - if (IOTX_CMP_PROCESS_TYPE_CLOUD == type) { - list = cmp_pt->process_cloud_list; - } -#ifdef CMP_SUPPORT_LOCAL_CONN - else if (IOTX_CMP_PROCESS_TYPE_LOCAL == type) { - list = cmp_pt->process_local_list; - } -#endif - - if (NULL == list) return 0; - - return list->size; -} - - -void* iotx_cmp_cloud_process(void *pclient) -{ - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)pclient; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - - CMP_INFO(cmp_log_info_enter_process_1); - - while (!cmp_pt->thread_stop) { - iotx_cmp_connectivity_pt connectivity = iotx_cmp_find_connectivity(cmp_pt, NULL); - - if (NULL == connectivity) { - HAL_SleepMs(50); - continue; - } - - if (0 == connectivity->is_connected) { - connectivity->connect_func(cmp_pt, connectivity); - if (1 == connectivity->is_connected) { - iotx_cmp_event_msg_t event_msg = {0}; - event_msg.event_id = IOTX_CMP_EVENT_CLOUD_CONNECTED; - event_msg.msg = NULL; - iotx_cmp_trigger_event_callback(cmp_pt, &event_msg); - } - continue; - } - - if (iotx_cmp_process_list_get_size(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD) > 0) { - iotx_cmp_process_list_node_pt node = NULL; - if (NULL != (node = iotx_cmp_process_list_pop(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD))) { - CMP_INFO(cmp_log_info_process_type, node->type); - - switch(node->type) { - case IOTX_CMP_PROCESS_CLOUD_REGISTER: { - iotx_cmp_process_register_pt register_pt = (iotx_cmp_process_register_pt)node->msg; - if (FAIL_RETURN == iotx_cmp_register_service(cmp_pt, register_pt->URI, register_pt->type, register_pt->register_func, - register_pt->user_data, register_pt->mail_box)) { - CMP_ERR(cmp_log_error_fail); - } - - LITE_free(register_pt->URI); - LITE_free(register_pt); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_UNREGISTER: { - char* URI = (char*)node->msg; - if (FAIL_RETURN == iotx_cmp_unregister_service(cmp_pt, URI)) { - CMP_ERR(cmp_log_error_fail); - } - - LITE_free(URI); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_SEND: { - iotx_cmp_process_send_pt send_pt = (iotx_cmp_process_send_pt)node->msg; - if (FAIL_RETURN == iotx_cmp_send_data(cmp_pt, send_pt->target, send_pt->URI, send_pt->ack_type, send_pt->payload, send_pt->payload_length)) { - CMP_ERR(cmp_log_error_fail); - } - - if (send_pt->target) - LITE_free(send_pt->target); - LITE_free(send_pt); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_DISCONNECT: { - #ifdef CMP_VIA_MQTT_DIRECT - iotx_cmp_mqtt_direct_disconnect_handler(cmp_pt); - #else - iotx_cmp_cloud_conn_disconnect_handler(cmp_pt); - #endif - } - break; - - case IOTX_CMP_PROCESS_CLOUD_RECONNECT: { - #ifdef CMP_VIA_MQTT_DIRECT - iotx_cmp_mqtt_direct_reconnect_handler(cmp_pt); - #else - iotx_cmp_cloud_conn_reconnect_handler(cmp_pt); - #endif - } - break; - - case IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT: - case IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT: { - iotx_cmp_process_register_result_pt register_pt = (iotx_cmp_process_register_result_pt)node->msg; - #ifdef CMP_VIA_MQTT_DIRECT - iotx_cmp_mqtt_direct_register_handler(cmp_pt, register_pt->URI, register_pt->result, register_pt->is_register); - #else - iotx_cmp_cloud_conn_register_handler(cmp_pt, register_pt->URI, register_pt->result, register_pt->is_register); - LITE_free(register_pt->URI); - #endif - LITE_free(register_pt); - } - break; - - case IOTX_CMP_PROCESS_CLOUD_NEW_DATA: { - iotx_cmp_message_info_pt message_info = (iotx_cmp_message_info_pt)node->msg; - #ifdef CMP_VIA_MQTT_DIRECT - iotx_cmp_mqtt_direct_response_handler(cmp_pt, message_info); - #else - iotx_cmp_cloud_conn_response_handler(cmp_pt, message_info); - #endif - LITE_free(node->msg); - break; - } - - default: - break; - } - - iotx_cmp_free_list_node(node); - } - } - - /* cloud yield */ - #ifdef CMP_VIA_MQTT_DIRECT - iotx_cmp_mqtt_direct_yield(iotx_cmp_find_connectivity(cmp_pt, NULL), 50); - #else - iotx_cmp_cloud_conn_yield(iotx_cmp_find_connectivity(cmp_pt, NULL), 50); - #endif - } - - cmp_pt->thread_is_stoped = 1; - - return NULL; -} - -#ifdef CMP_SUPPORT_LOCAL_CONN -void* iotx_cmp_local_process(void *pclient) -{ - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)pclient; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - - CMP_INFO(cmp_log_info_enter_process_2); - - while (!cmp_pt->thread_stop) { - if (iotx_cmp_process_list_get_size(cmp_pt, IOTX_CMP_PROCESS_TYPE_LOCAL) > 0) { - iotx_cmp_process_list_node_pt node = NULL; - if (NULL != (node = iotx_cmp_process_list_pop(cmp_pt, IOTX_CMP_PROCESS_TYPE_LOCAL))) { - CMP_INFO(cmp_log_info_process_type, node->type); - - switch(node->type) { - case IOTX_CMP_PROCESS_LOCAL_ADD_DEVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_REMOVE_DEVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_SEND: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_DISCONNECT: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_RECONNECT: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_ADD_SERVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_REMOVE_SERVICE: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_ADD_SERVICE_RESULT: - case IOTX_CMP_PROCESS_LOCAL_REMOVE_SERVICE_RESULT: { - } - break; - - case IOTX_CMP_PROCESS_LOCAL_NEW_DATA: { - break; - } - - default: - break; - } - - iotx_cmp_free_list_node(node); - } - /* local yield */ - - } else { - - /* cloud yield */ - } - } - - return NULL; -} - -#endif - -#endif - - diff --git a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_log.c b/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_log.c deleted file mode 100644 index 62803fa..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_log.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "iotx_cmp_common.h" - - -/* text for log */ -/* error */ -const char cmp_log_error_parameter[] CMP_READ_ONLY = "parameters error!"; -const char cmp_log_error_param_1[] CMP_READ_ONLY = "param error: lack of product_key or device_name or device_secret"; -const char cmp_log_error_auth[] CMP_READ_ONLY = "auth error"; -const char cmp_log_error_memory[] CMP_READ_ONLY = "memory error"; -const char cmp_log_error_fail[] CMP_READ_ONLY = "failed"; -const char cmp_log_error_fail_ota[] CMP_READ_ONLY = "ota failed"; -const char cmp_log_error_fail_1[] CMP_READ_ONLY = "register fail: add mapping fail."; -const char cmp_log_error_fail_rc[] CMP_READ_ONLY = "fail: rc = %d."; -const char cmp_log_error_status[] CMP_READ_ONLY = "status error!"; -const char cmp_log_error_splice_URI[] CMP_READ_ONLY = "splice URI fail!"; -const char cmp_log_error_parse_URI[] CMP_READ_ONLY = "parse URI fail!"; -const char cmp_log_error_splice_payload[] CMP_READ_ONLY = "splice payload fail!"; -const char cmp_log_error_parse_payload[] CMP_READ_ONLY = "parse payload fail!"; -const char cmp_log_error_get_node[] CMP_READ_ONLY = "get list node fail!"; -const char cmp_log_error_push_node[] CMP_READ_ONLY = "push list node fail!"; -const char cmp_log_error_process[] CMP_READ_ONLY = "too many process"; -const char cmp_log_error_parse_id[] CMP_READ_ONLY = "parse id error"; -const char cmp_log_error_parse_code[] CMP_READ_ONLY = "parse code error"; -const char cmp_log_error_parse_data[] CMP_READ_ONLY = "parse data error"; -const char cmp_log_error_parse_params[] CMP_READ_ONLY = "parse params error"; -const char cmp_log_error_parse_method[] CMP_READ_ONLY = "parse method error"; -const char cmp_log_error_type[] CMP_READ_ONLY = "type error"; -const char cmp_log_error_pk[] CMP_READ_ONLY = "product_key is empty"; -const char cmp_log_error_dn[] CMP_READ_ONLY = "device_name is empty"; -const char cmp_log_error_di[] CMP_READ_ONLY = "device_id is empty"; -const char cmp_log_error_ret_code[] CMP_READ_ONLY = "\r\n ret_code = %d (!= 200), abort!\r\n "; -const char cmp_log_error_secret_1[] CMP_READ_ONLY = "secret type is product_secret, but the product_secret is null"; -const char cmp_log_error_secret_2[] CMP_READ_ONLY = "device_secret is null"; - -/* warning */ -const char cmp_log_warning_ota_started[] CMP_READ_ONLY = "ota is started"; -const char cmp_log_warning_cloud_disconnected[] CMP_READ_ONLY = "cloud is not connect"; -const char cmp_log_warning_not_support[] CMP_READ_ONLY = "NOT_SUPPORT"; -const char cmp_log_warning_not_arrived[] CMP_READ_ONLY = "Should NOT arrived here"; -const char cmp_log_warning_not_mapping[] CMP_READ_ONLY = "can not find mapping"; -const char cmp_log_warning_not_func[] CMP_READ_ONLY = "can not find func"; -const char cmp_log_warning_no_list[] CMP_READ_ONLY = "no list"; -const char cmp_log_warning_buffer_overflow[] CMP_READ_ONLY = "buffer overflow, %s"; - -/* info */ -const char cmp_log_info_init[] CMP_READ_ONLY = "cmp context initialize"; -const char cmp_log_info_registered[] CMP_READ_ONLY = "URI have been registered, can not register again"; -const char cmp_log_info_event_id[] CMP_READ_ONLY = "event_id %d"; -const char cmp_log_info_event_type[] CMP_READ_ONLY = "event_type %d"; -const char cmp_log_info_rsp_type[] CMP_READ_ONLY = "rsp_type %d"; -const char cmp_log_info_cloud_disconnect[] CMP_READ_ONLY = "cloud disconnect"; -const char cmp_log_info_cloud_reconnect[] CMP_READ_ONLY = "cloud reconnect"; -const char cmp_log_info_result[] CMP_READ_ONLY = "rc = %d"; -const char cmp_log_info_URI[] CMP_READ_ONLY = "URI = %s"; -const char cmp_log_info_URI_1[] CMP_READ_ONLY = "URI: %.*s"; -const char cmp_log_info_URI_sys[] CMP_READ_ONLY = "URI type: /SYS/ "; -const char cmp_log_info_URI_ext[] CMP_READ_ONLY = "URI type: /EXT/ "; -const char cmp_log_info_URI_undefined[] CMP_READ_ONLY = "URI type: /UNDEFINE/ "; -const char cmp_log_info_URI_length[] CMP_READ_ONLY = "URI length = %d"; -const char cmp_log_info_payload_length[] CMP_READ_ONLY = "payload length = %d"; -const char cmp_log_info_firmware[] CMP_READ_ONLY = "The firmware is valid"; -const char cmp_log_info_MQTT_disconnect[] CMP_READ_ONLY = "MQTT disconnect."; -const char cmp_log_info_MQTT_reconnect[] CMP_READ_ONLY = "MQTT reconnect"; -const char cmp_log_info_remove_mapping[] CMP_READ_ONLY = "find mapping and remove it"; -const char cmp_log_info_enter_process_1[] CMP_READ_ONLY = "enter cloud process"; -const char cmp_log_info_enter_process_2[] CMP_READ_ONLY = "enter local process"; -const char cmp_log_info_process_type[] CMP_READ_ONLY = "process %d"; -const char cmp_log_info_raw_data[] CMP_READ_ONLY = "raw data"; -const char cmp_log_info_auth_req[] CMP_READ_ONLY = "req_str = '%s'"; -const char cmp_log_info_auth_payload_req[] CMP_READ_ONLY = "req_payload: \r\n\r\n%s\r\n"; -const char cmp_log_info_auth_payload_rsp[] CMP_READ_ONLY = "response payload: \r\n\r\n%s\r\n"; -const char cmp_log_info_auth_rsp[] CMP_READ_ONLY = "http response: \r\n\r\n%s\r\n"; - diff --git a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_mqtt_direct.c b/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_mqtt_direct.c deleted file mode 100644 index 008dcd9..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_mqtt_direct.c +++ /dev/null @@ -1,878 +0,0 @@ -#ifdef CMP_VIA_MQTT_DIRECT - -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iot_export.h" -#include "iotx_cmp_common.h" -#include "iot_export_mqtt.h" - -#include "mqtt_instance.h" -#include "iotx_cmp_mqtt_direct.h" - - -#ifdef ESP8266 -#define MQTT_MSGLEN (1024) -#else -#define MQTT_MSGLEN (1024 * 40) -#endif - - -typedef struct iotx_cmp_mqtt_direct_topic_st { - void *next; - char *topic; - int packet_id; -} iotx_cmp_mqtt_direct_topic_t, *iotx_cmp_mqtt_direct_topic_pt; - -typedef struct iotx_cmp_mqtt_direct_st { - char *msg_buf; - char *msg_readbuf; - int list_length; - iotx_cmp_mqtt_direct_topic_pt topic_list; -} iotx_cmp_mqtt_direct_t, *iotx_cmp_mqtt_direct_pt; - -static iotx_cmp_mqtt_direct_pt mqtt_pt = NULL; - -static int _add_topic(const char* topic, int packet_id) -{ - iotx_cmp_mqtt_direct_topic_pt new_pt = NULL; - - new_pt = CMP_malloc(sizeof(iotx_cmp_mqtt_direct_topic_t)); - if (NULL == new_pt) { - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - memset(new_pt, 0x0, sizeof(iotx_cmp_mqtt_direct_topic_t)); - - new_pt->topic = CMP_malloc(strlen(topic) + 1); - if (NULL == new_pt->topic) { - CMP_ERR(cmp_log_error_memory); - LITE_free(new_pt); - return FAIL_RETURN; - } - memset(new_pt->topic, 0x0, strlen(topic) + 1); - strncpy(new_pt->topic, topic, strlen(topic)); - - new_pt->packet_id = packet_id; - - new_pt->next = mqtt_pt->topic_list; - - mqtt_pt->topic_list = new_pt; - - mqtt_pt->list_length++; - - return SUCCESS_RETURN; -} - -static int _delete_topic(unsigned int packet_id) -{ - iotx_cmp_mqtt_direct_topic_pt current = NULL; - iotx_cmp_mqtt_direct_topic_pt pre = NULL; - - if (NULL == mqtt_pt->topic_list) { - CMP_WARNING(cmp_log_warning_no_list); - return FAIL_RETURN; - } - - current = pre = mqtt_pt->topic_list; - - if (current->packet_id == packet_id){ - mqtt_pt->topic_list = mqtt_pt->topic_list->next; - LITE_free(current->topic); - LITE_free(current); - mqtt_pt->list_length--; - if (mqtt_pt->list_length == 0) - mqtt_pt->topic_list = NULL; - return SUCCESS_RETURN; - } - - current = current->next; - - while (current) { - if (current->packet_id == packet_id) { - pre->next = current->next; - LITE_free(current->topic); - LITE_free(current); - - mqtt_pt->list_length--; - - if (mqtt_pt->list_length == 0) - mqtt_pt = NULL; - return SUCCESS_RETURN; - } - pre = current; - current = current->next; - } - - return FAIL_RETURN; -} - - -static char* _find_topic(unsigned int packet_id) -{ - iotx_cmp_mqtt_direct_topic_pt current = NULL; - iotx_cmp_mqtt_direct_topic_pt pre = NULL; - - if (NULL == mqtt_pt || NULL == mqtt_pt->topic_list) { - CMP_WARNING(cmp_log_warning_no_list); - return NULL; - } - - current = pre = mqtt_pt->topic_list; - - while (current) { - if (current->packet_id == packet_id) { - return current->topic; - } - pre = current; - current = current->next; - } - - return NULL; -} - - -static int _find_topic_ex(char* URI) -{ - iotx_cmp_mqtt_direct_topic_pt current = NULL; - iotx_cmp_mqtt_direct_topic_pt pre = NULL; - - if (NULL == mqtt_pt->topic_list) { - CMP_WARNING(cmp_log_warning_no_list); - return FAIL_RETURN; - } - - current = pre = mqtt_pt->topic_list; - - while (current) { - if (0 == strncmp(current->topic, URI, strlen(URI))) { - return current->packet_id; - } - pre = current; - current = current->next; - } - - return FAIL_RETURN; -} - -static void _delete_all() -{ - iotx_cmp_mqtt_direct_topic_pt current = NULL; - iotx_cmp_mqtt_direct_topic_pt next = NULL; - - if (NULL == mqtt_pt->topic_list) { - CMP_WARNING(cmp_log_warning_no_list); - return; - } - - current = next = mqtt_pt->topic_list; - - while (current) { - next = current->next; - LITE_free(current->topic); - LITE_free(current); - current = next; - } - - mqtt_pt->list_length = 0; -} - -static void iotx_cmp_mqtt_direct_event_callback(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)pcontext; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return; - } - - CMP_INFO(cmp_log_info_event_type, msg->event_type); - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_UNDEF: - CMP_WARNING(cmp_log_warning_not_arrived); - break; - - case IOTX_MQTT_EVENT_DISCONNECT: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_DISCONNECT; - node->msg = NULL; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) iotx_cmp_free_list_node(node); - } - #else - iotx_cmp_mqtt_direct_disconnect_handler(cmp_pt); - #endif - } - break; - - case IOTX_MQTT_EVENT_RECONNECT: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_RECONNECT; - node->msg = NULL; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) iotx_cmp_free_list_node(node); - } - #else - iotx_cmp_mqtt_direct_reconnect_handler(cmp_pt); - #endif - } - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: { - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = _find_topic(packet_id); - result_msg->result = 0; - result_msg->is_register = 1; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_mqtt_direct_register_handler(cmp_pt, _find_topic(packet_id), 0, 1); - _delete_topic(packet_id); - #endif - } - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - case IOTX_MQTT_EVENT_SUBCRIBE_NACK:{ - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_REGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = _find_topic(packet_id); - result_msg->result = -1; - result_msg->is_register = 1; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_mqtt_direct_register_handler(cmp_pt, _find_topic(packet_id), -1, 1); - _delete_topic(packet_id); - #endif - } - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS:{ - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = _find_topic(packet_id); - result_msg->result = 0; - result_msg->is_register = 0; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_mqtt_direct_register_handler(cmp_pt, _find_topic(packet_id), 0, 0); - _delete_topic(packet_id); - #endif - } - break; - - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK:{ - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_process_register_result_pt result_msg = NULL; - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_UNREGISTER_RESULT; - node->msg = CMP_malloc(sizeof(iotx_cmp_process_register_result_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - result_msg = node->msg; - - result_msg->URI = _find_topic(packet_id); - result_msg->result = -1; - result_msg->is_register = 0; - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - } - } - #else - iotx_cmp_mqtt_direct_register_handler(cmp_pt, _find_topic(packet_id), -1, 0); - _delete_topic(packet_id); - #endif - } - break; - - case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: - break; - - case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: - case IOTX_MQTT_EVENT_PUBLISH_NACK: - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED:{ - #ifdef CMP_SUPPORT_MULTI_THREAD - { - /* send message to itself thread */ - int rc = 0; - iotx_mqtt_topic_info_pt mqtt_info = (iotx_mqtt_topic_info_pt)msg->msg; - iotx_cmp_process_list_node_pt node = NULL; - iotx_cmp_message_info_pt msg_info = NULL; - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - iotx_cmp_mapping_pt mapping = NULL; - #endif - - node = iotx_cmp_get_list_node(IOTX_CMP_PROCESS_TYPE_CLOUD); - if (NULL == node) return; - - node->type = IOTX_CMP_PROCESS_CLOUD_NEW_DATA; - node->msg = CMP_malloc(sizeof(iotx_cmp_message_info_t)); - if (NULL == node->msg) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_free_list_node(node); - return; - } - - msg_info = node->msg; - - msg_info->URI = CMP_malloc(mqtt_info->topic_len + 1); - if (NULL == msg_info->URI) { - CMP_ERR(cmp_log_error_memory); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - if (FAIL_RETURN == iotx_cmp_parse_URI((char*)mqtt_info->ptopic, mqtt_info->topic_len, msg_info->URI, &msg_info->URI_type)) { - CMP_ERR(cmp_log_error_parse_URI); - iotx_cmp_free_message_info(msg_info); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - /* find mapping */ - mapping = iotx_cmp_find_mapping(cmp_pt, (char*)mqtt_info->ptopic, mqtt_info->topic_len); - if (NULL == mapping) { - CMP_ERR(cmp_log_warning_not_mapping); - iotx_cmp_free_message_info(msg_info); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - msg_info->message_type = mapping->type; - #endif - - if (FAIL_RETURN == iotx_cmp_parse_payload((char*)mqtt_info->payload, mqtt_info->payload_len, msg_info)) { - CMP_ERR(cmp_log_error_parse_payload); - iotx_cmp_free_message_info(msg_info); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - return; - } - - rc = iotx_cmp_process_list_push(cmp_pt, IOTX_CMP_PROCESS_TYPE_CLOUD, node); - - if (FAIL_RETURN == rc) { - iotx_cmp_free_message_info(msg_info); - LITE_free(node->msg); - iotx_cmp_free_list_node(node); - break; - } - } - #else - iotx_mqtt_topic_info_pt mqtt_info = (iotx_mqtt_topic_info_pt)msg->msg; - iotx_cmp_message_info_t message_info; - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - iotx_cmp_mapping_pt mapping = NULL; - #endif - - memset(&message_info, 0x0, sizeof(iotx_cmp_message_info_t)); - - message_info.URI = CMP_malloc(mqtt_info->topic_len + 1); - if (NULL == message_info.URI) { - CMP_ERR(cmp_log_error_memory); - return; - } - memset(message_info.URI, 0x0, mqtt_info->topic_len + 1); - if (FAIL_RETURN == iotx_cmp_parse_URI((char*)mqtt_info->ptopic, mqtt_info->topic_len, message_info.URI, &message_info.URI_type)) { - CMP_ERR(cmp_log_error_parse_URI); - iotx_cmp_free_message_info(&message_info); - return; - } - - #ifdef CMP_SUPPORT_TOPIC_DISPATCH - /* find mapping */ - mapping = iotx_cmp_find_mapping(cmp_pt, (char*)mqtt_info->ptopic, mqtt_info->topic_len); - if (NULL == mapping) { - CMP_ERR(cmp_log_warning_not_mapping); - iotx_cmp_free_message_info(&message_info); - return; - } - message_info.message_type = mapping->type; - #endif - - if (FAIL_RETURN == iotx_cmp_parse_payload((char*)mqtt_info->payload, mqtt_info->payload_len, &message_info)) { - CMP_ERR(cmp_log_error_parse_payload); - iotx_cmp_free_message_info(&message_info); - return; - } - - iotx_cmp_mqtt_direct_response_handler(cmp_pt, &message_info); - - #endif - } - break; - - case IOTX_MQTT_EVENT_BUFFER_OVERFLOW: - CMP_WARNING(cmp_log_warning_buffer_overflow, msg->msg); - break; - - default: - CMP_WARNING(cmp_log_warning_not_arrived); - break; - } -} - -int iotx_cmp_mqtt_direct_disconnect_handler(iotx_cmp_conntext_pt cmp_pt) -{ - iotx_cmp_event_msg_t event; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - event.event_id = IOTX_CMP_EVENT_CLOUD_DISCONNECT; - event.msg = NULL; - - CMP_INFO(cmp_log_info_MQTT_disconnect); - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - return SUCCESS_RETURN; -} - -int iotx_cmp_mqtt_direct_reconnect_handler(iotx_cmp_conntext_pt cmp_pt) -{ - iotx_cmp_event_msg_t event; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - event.event_id = IOTX_CMP_EVENT_CLOUD_RECONNECT; - event.msg = NULL; - - CMP_INFO(cmp_log_info_MQTT_reconnect); - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - return SUCCESS_RETURN; - -} - - -int iotx_cmp_mqtt_direct_register_handler(iotx_cmp_conntext_pt cmp_pt, char* URI, int result, int is_register) -{ - iotx_cmp_event_msg_t event; - iotx_cmp_event_result_t result_pt = {0}; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - result_pt.result = result; - result_pt.URI = CMP_malloc(CMP_TOPIC_LEN_MAX); - if (NULL == result_pt.URI) { - CMP_ERR(cmp_log_error_memory); - return FAIL_RETURN; - } - memset(result_pt.URI, 0x0, CMP_TOPIC_LEN_MAX); - - if (FAIL_RETURN == iotx_cmp_parse_URI(URI, CMP_TOPIC_LEN_MAX, result_pt.URI, &result_pt.URI_type)) { - CMP_ERR(cmp_log_error_parse_URI); - LITE_free(result_pt.URI); - return FAIL_RETURN; - } - - if (is_register) - event.event_id = IOTX_CMP_EVENT_REGISTER_RESULT; - else - event.event_id = IOTX_CMP_EVENT_UNREGISTER_RESULT; - - event.msg = (void*)&result_pt; - - iotx_cmp_trigger_event_callback(cmp_pt, &event); - - _delete_topic(_find_topic_ex(result_pt.URI)); - - LITE_free(result_pt.URI); - - return SUCCESS_RETURN; -} - -int iotx_cmp_mqtt_direct_response_handler(iotx_cmp_conntext_pt cmp_pt, iotx_cmp_message_info_pt message_info) -{ - if (NULL == cmp_pt || NULL == message_info) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - CMP_INFO(cmp_log_info_URI, (char*)message_info->URI); - - if (cmp_pt->response_func) - cmp_pt->response_func(cmp_pt, message_info); - - iotx_cmp_free_message_info(message_info); - - return SUCCESS_RETURN; -} - -int iotx_cmp_mqtt_direct_connect(void* handler, void* connectivity_pt) -{ - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - iotx_mqtt_param_t mqtt_params; - iotx_conn_info_pt pconn_info = iotx_conn_info_get(); - void *pclient = NULL; - - if (NULL == cmp_pt || NULL == connectivity) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = mqtt_pt->msg_readbuf; - mqtt_params.read_buf_size = MQTT_MSGLEN; - mqtt_params.pwrite_buf = mqtt_pt->msg_buf; - mqtt_params.write_buf_size = MQTT_MSGLEN; - - mqtt_params.handle_event.h_fp = iotx_cmp_mqtt_direct_event_callback; - mqtt_params.handle_event.pcontext = cmp_pt; - - /* Construct a MQTT client with specify parameter */ -#ifndef MQTT_ID2_AUTH - pclient = IOT_MQTT_Construct(&mqtt_params); -#else - pclient = IOT_MQTT_ConstructSecure(&mqtt_params); -#endif /**< MQTT_ID2_AUTH*/ - if (NULL == pclient) { - CMP_ERR(cmp_log_error_fail); - connectivity->is_connected = 0; - return FAIL_RETURN; - } - - mqtt_set_instance(pclient); - - connectivity->context = pclient; - connectivity->is_connected = 1; - - return SUCCESS_RETURN; -} - - -void* iotx_cmp_mqtt_direct_init(void* handler, iotx_cmp_init_param_pt pparam) -{ - iotx_cmp_connectivity_pt connectivity = NULL; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - - if (NULL == cmp_pt || NULL == pparam) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - - mqtt_pt = CMP_malloc(sizeof(iotx_cmp_mqtt_direct_t)); - if (NULL == mqtt_pt){ - CMP_ERR(cmp_log_error_memory); - mqtt_pt = NULL; - return NULL; - } - memset(mqtt_pt, 0x0, sizeof(iotx_cmp_mqtt_direct_t)); - - if (NULL == (mqtt_pt->msg_buf = (char *)CMP_malloc(MQTT_MSGLEN))) { - LITE_free(mqtt_pt); - CMP_ERR(cmp_log_error_memory); - mqtt_pt = NULL; - return NULL; - } - memset(mqtt_pt->msg_buf, 0x0, MQTT_MSGLEN); - - if (NULL == (mqtt_pt->msg_readbuf = (char *)CMP_malloc(MQTT_MSGLEN))) { - CMP_ERR(cmp_log_error_memory); - LITE_free(mqtt_pt->msg_buf); - LITE_free(mqtt_pt); - mqtt_pt = NULL; - return NULL; - } - memset(mqtt_pt->msg_readbuf, 0x0, MQTT_MSGLEN); - - connectivity = CMP_malloc(sizeof(iotx_cmp_connectivity_t)); - if (NULL == connectivity) { - CMP_ERR(cmp_log_error_memory); - iotx_cmp_mqtt_direct_deinit(connectivity); - return NULL; - } - - iotx_cmp_mqtt_direct_connect(cmp_pt, connectivity); - - connectivity->init_func = iotx_cmp_mqtt_direct_init; - connectivity->connect_func = iotx_cmp_mqtt_direct_connect; - connectivity->register_func = iotx_cmp_mqtt_direct_register; - connectivity->unregister_func = iotx_cmp_mqtt_direct_unregister; - connectivity->send_func = iotx_cmp_mqtt_direct_send; - connectivity->send_sync_func = iotx_cmp_mqtt_direct_send_sync; - connectivity->yield_func = iotx_cmp_mqtt_direct_yield; - connectivity->deinit_func = iotx_cmp_mqtt_direct_deinit; - - return connectivity; -} - -int iotx_cmp_mqtt_direct_register(void* handler, void* connectivity_pt, const char* topic_filter) -{ - int rc = 0; - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)handler; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - - if (NULL == connectivity || NULL == topic_filter) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - rc = IOT_MQTT_Subscribe(connectivity->context, - topic_filter, - IOTX_MQTT_QOS1, - iotx_cmp_mqtt_direct_event_callback, - (void*)cmp_pt); - - if (rc > 0) - _add_topic(topic_filter, rc); - - return rc; -} - -int iotx_cmp_mqtt_direct_unregister(void* handler, void* connectivity_pt, const char* topic_filter) -{ - int rc = 0; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - if (NULL == connectivity || NULL == topic_filter) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - rc = IOT_MQTT_Unsubscribe(connectivity->context, topic_filter); - - if (rc > 0) - _add_topic(topic_filter, rc); - - return rc; -} - - -static iotx_mqtt_qos_t _to_mqtt_qos(iotx_cmp_message_ack_types_t ack_type) -{ - switch (ack_type) { - case IOTX_CMP_MESSAGE_NEED_ACK: - return IOTX_MQTT_QOS1; - - case IOTX_CMP_MESSAGE_NO_ACK: - return IOTX_MQTT_QOS0; - - default: - return IOTX_MQTT_QOS0; - } -} - - - -int iotx_cmp_mqtt_direct_send(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length) -{ - int rc = 0; - iotx_mqtt_topic_info_t topic_msg; - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - - if (NULL == connectivity || NULL == topic_filter || NULL == payload) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - - topic_msg.dup = 0; - topic_msg.qos = _to_mqtt_qos(ack_type); - topic_msg.retain = 0; - topic_msg.payload_len = payload_length; - topic_msg.payload = payload; - topic_msg.ptopic = topic_filter; - topic_msg.topic_len = strlen(topic_filter); - - rc = IOT_MQTT_Publish(connectivity->context, topic_filter, &topic_msg); - - return rc; -} - -int iotx_cmp_mqtt_direct_send_sync(void* handler, - void* connectivity_pt, - const char* topic_filter, - iotx_cmp_message_ack_types_t ack_type, - const void* payload, - int payload_length) -{ - return FAIL_RETURN; -} - - -int iotx_cmp_mqtt_direct_yield(void* connectivity_pt, int timeout_ms) -{ - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - if (NULL == connectivity) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - return IOT_MQTT_Yield(connectivity->context, timeout_ms); -} - -int iotx_cmp_mqtt_direct_deinit(void* connectivity_pt) -{ - iotx_cmp_connectivity_pt connectivity = (iotx_cmp_connectivity_pt)connectivity_pt; - int rc = 0; - - if (NULL == connectivity) - return FAIL_RETURN; - - rc = IOT_MQTT_Destroy(&(connectivity->context)); - - if (mqtt_pt->list_length != 0) - _delete_all(); - - if (mqtt_pt->msg_buf) - LITE_free(mqtt_pt->msg_buf); - - if (mqtt_pt->msg_readbuf) - LITE_free(mqtt_pt->msg_readbuf); - - if (mqtt_pt) - LITE_free(mqtt_pt); - - mqtt_pt = NULL; - - LITE_free(connectivity); - - return rc; -} - -#endif /* CMP_VIA_MQTT_DIRECT */ - diff --git a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_ota.c b/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_ota.c deleted file mode 100644 index dd150b2..0000000 --- a/iotkit-embedded/src/cmp/Link-CMP/src/iotx_cmp_ota.c +++ /dev/null @@ -1,224 +0,0 @@ -#ifdef SERVICE_OTA_ENABLED - -#include -#include -#include - -#include "lite-utils.h" -#include "lite-system.h" - -#include "iotx_cmp_ota.h" -#include "ota_internal.h" -#include "iotx_cmp_common.h" -#include "iot_export_cmp.h" -#include "iot_import.h" - -static int g_cmp_ota_status = 0; - -static void _fota_fetch(void* user_data, int is_fetch, uint32_t size_file, char *purl, char *version) -{ - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)user_data; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return; - } - - /* start */ - if (0 == is_fetch) { - iotx_cmp_fota_parameter_t ota_parameter = {0}; - - ota_parameter.purl = purl; - ota_parameter.size_file = size_file; - ota_parameter.version = version; - - if (cmp_pt->fota_func) - cmp_pt->fota_func(cmp_pt, &ota_parameter, cmp_pt->fota_user_context); - } else { - g_cmp_ota_status = 1; - } -} - - -static void _cota_fetch(void* user_data, int is_fetch, char* configId, uint32_t configSize, char *sign, \ - char *signMethod, char* url, char* getType) -{ - iotx_cmp_conntext_pt cmp_pt = (iotx_cmp_conntext_pt)user_data; - - if (NULL == cmp_pt) { - CMP_ERR(cmp_log_error_parameter); - return; - } - - /* start */ - if (0 == is_fetch) { - iotx_cmp_cota_parameter_t ota_parameter = {0}; - - ota_parameter.configId = configId; - ota_parameter.configSize = configSize; - ota_parameter.sign = sign; - ota_parameter.signMethod = signMethod; - ota_parameter.url = url; - ota_parameter.getType = getType; - - if (cmp_pt->cota_func) - cmp_pt->cota_func(cmp_pt, &ota_parameter, cmp_pt->cota_user_context); - } else { - g_cmp_ota_status = 1; - } -} - -void* iotx_cmp_ota_init(iotx_cmp_conntext_pt cmp_pt, const char* version) -{ - void *h_ota = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - if (NULL == cmp_pt || NULL == version) { - CMP_ERR(cmp_log_error_parameter); - return NULL; - } - - if (!cmp_pt->connectivity_list->node->is_connected) { - CMP_WARNING(cmp_log_warning_cloud_disconnected); - return NULL; - } - - h_ota = IOT_OTA_Init(pdevice_info->product_key, - pdevice_info->device_name, - cmp_pt->connectivity_list->node->context); - if (NULL == h_ota) { - CMP_ERR(cmp_log_error_fail); - return NULL; - } - - cmp_pt->ota_handler = h_ota; - - if (0 != IOT_OTA_ReportVersion(h_ota, version)) { - CMP_ERR(cmp_log_error_fail); - IOT_OTA_Deinit(h_ota); - return NULL; - } - - iotx_ota_set_fetch_callback(h_ota, _fota_fetch, cmp_pt); - iotx_ota_set_cota_fetch_callback(h_ota, _cota_fetch, cmp_pt); - - return h_ota; -} - -int iotx_cmp_ota_yield(iotx_cmp_conntext_pt cmp_pt, iotx_cmp_ota_pt ota_pt) -{ - uint32_t len, size_downloaded, size_file; - uint32_t percent = 0; - static uint32_t pre_percent = 0; - static unsigned long long pre_report_time = 0; - unsigned long long report_time = 0; - - if (NULL == cmp_pt || NULL == cmp_pt->ota_handler || NULL == ota_pt || NULL == ota_pt->buffer) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - len = IOT_OTA_FetchYield(cmp_pt->ota_handler, ota_pt->buffer, ota_pt->buffer_length, 1); - if (len <= 0) { - IOT_OTA_ReportProgress(cmp_pt->ota_handler, IOT_OTAP_FETCH_FAILED, NULL); - ota_pt->is_more = 0; - ota_pt->result = IOT_OTAP_FETCH_FAILED; - ota_pt->progress = IOT_OTAP_FETCH_FAILED; - CMP_ERR(cmp_log_error_fail); - return FAIL_RETURN; - } - - ota_pt->buffer_length = len; - - /* get OTA information */ - IOT_OTA_Ioctl(cmp_pt->ota_handler, IOT_OTAG_FETCHED_SIZE, &size_downloaded, 4); - IOT_OTA_Ioctl(cmp_pt->ota_handler, IOT_OTAG_FILE_SIZE, &size_file, 4); - if (IOTX_CMP_OTA_TYPE_FOTA == ota_pt->ota_type) { - char version[128], md5sum[33]; - IOT_OTA_Ioctl(cmp_pt->ota_handler, IOT_OTAG_MD5SUM, md5sum, 33); - IOT_OTA_Ioctl(cmp_pt->ota_handler, IOT_OTAG_VERSION, version, 128); - } - - percent = (size_downloaded * 100) / size_file; - report_time = HAL_UptimeMs(); - if ((((percent - pre_percent) > 5) && ((report_time - pre_report_time) > 50)) || (percent >= IOT_OTAP_FETCH_PERCENTAGE_MAX) ){ - IOT_OTA_ReportProgress(cmp_pt->ota_handler, percent, NULL); - pre_percent = percent; - pre_report_time = report_time; - } - - if (!IOT_OTA_IsFetchFinish(cmp_pt->ota_handler)) { - ota_pt->is_more = 1; - ota_pt->result = 0; - ota_pt->progress = percent; - } else { - uint32_t firmware_valid; - - ota_pt->is_more = 0; - ota_pt->progress = percent; - /* finished */ - if (1 == g_cmp_ota_status) { - if (IOTX_CMP_OTA_TYPE_FOTA == ota_pt->ota_type) - { - IOT_OTA_Ioctl(cmp_pt->ota_handler, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4); - if (0 == firmware_valid) { - CMP_ERR(cmp_log_error_fail); - ota_pt->result = IOT_OTAP_CHECK_FALIED; - } else { - CMP_INFO(cmp_log_info_firmware); - ota_pt->result = 0; - } - }else if(IOTX_CMP_OTA_TYPE_COTA == ota_pt->ota_type) - { - IOT_OTA_Ioctl(cmp_pt->ota_handler, IOT_OTAG_CHECK_CONFIG, &firmware_valid, 4); - if (0 == firmware_valid) { - CMP_ERR(cmp_log_error_fail); - ota_pt->result = IOT_OTAP_CHECK_FALIED; - } else { - CMP_INFO(cmp_log_info_firmware); - ota_pt->result = 0; - } - } - } else { - CMP_ERR(cmp_log_error_fail_ota); - ota_pt->result = IOT_OTAP_GENERAL_FAILED; - } - } - - return SUCCESS_RETURN; -} - -int iotx_cmp_ota_deinit(iotx_cmp_conntext_pt cmp_pt) -{ - if (NULL == cmp_pt || NULL == cmp_pt->ota_handler) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - return IOT_OTA_Deinit(cmp_pt->ota_handler); -} - - -int iotx_cmp_ota_request_image(iotx_cmp_conntext_pt cmp_pt, const char* version) -{ - if (NULL == cmp_pt || NULL == cmp_pt->ota_handler) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - return IOT_OTA_RequestImage(cmp_pt->ota_handler, version); -} - - -int iotx_cmp_ota_get_config(iotx_cmp_conntext_pt cmp_pt, const char* configScope, const char* getType, const char* attributeKeys) -{ - if (NULL == cmp_pt || NULL == cmp_pt->ota_handler) { - CMP_ERR(cmp_log_error_parameter); - return FAIL_RETURN; - } - - return IOT_OTA_GetConfig(cmp_pt->ota_handler, configScope, getType, attributeKeys); -} - -#endif /* SERVICE_OTA_ENABLED */ - diff --git a/iotkit-embedded/src/cmp/iot.mk b/iotkit-embedded/src/cmp/iot.mk deleted file mode 100644 index e07b810..0000000 --- a/iotkit-embedded/src/cmp/iot.mk +++ /dev/null @@ -1,7 +0,0 @@ -LIBA_TARGET := libiot_cmp.a -HDR_REFS := src - -CFLAGS += -DCMP_SUPPORT_TOPIC_DISPATCH \ - -PKG_SOURCE := Link-CMP.git -PKG_UPSTREAM := git@gitlab.alibaba-inc.com:iot-middleware/Link-CMP.git diff --git a/iotkit-embedded/src/coap/CMakeLists.txt b/iotkit-embedded/src/coap/CMakeLists.txt deleted file mode 100644 index 5afb9c7..0000000 --- a/iotkit-embedded/src/coap/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(coap OBJECT ${C_SOURCES}) diff --git a/iotkit-embedded/src/coap/CoAPPacket/CoAPDeserialize.h b/iotkit-embedded/src/coap/CoAPPacket/CoAPDeserialize.h new file mode 100644 index 0000000..8d0cef6 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/packages/iot-coap-c/CoAPDeserialize.c b/iotkit-embedded/src/coap/CoAPPacket/CoAPDeserialize_common.c similarity index 80% rename from iotkit-embedded/src/packages/iot-coap-c/CoAPDeserialize.c rename to iotkit-embedded/src/coap/CoAPPacket/CoAPDeserialize_common.c index ebf156a..c034a79 100644 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPDeserialize.c +++ b/iotkit-embedded/src/coap/CoAPPacket/CoAPDeserialize_common.c @@ -1,24 +1,13 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + #include -#include "CoAPExport.h" +#include +#include "iotx_coap_internal.h" int CoAPDeserialize_Header(CoAPMessage *msg, unsigned char *buf) { @@ -89,10 +78,10 @@ int CoAPDeserialize_Options(CoAPMessage *msg, unsigned char *buf, int buflen) unsigned short len = 0; unsigned short optdeltas = 0; - msg->optnum = 0; + msg->optcount = 0; while ((count < buflen) && (0xFF != *ptr)) { len = CoAPDeserialize_Option(&msg->options[index], ptr, &optdeltas); - msg->optnum += 1; + msg->optcount += 1; ptr += len; index ++; count += len; diff --git a/iotkit-embedded/src/coap/CoAPPacket/CoAPMessage_common.c b/iotkit-embedded/src/coap/CoAPPacket/CoAPMessage_common.c new file mode 100644 index 0000000..47e6104 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/CoAPPacket/CoAPPlatform.h b/iotkit-embedded/src/coap/CoAPPacket/CoAPPlatform.h new file mode 100644 index 0000000..02f6eca --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/CoAPPacket/CoAPSerialize.h b/iotkit-embedded/src/coap/CoAPPacket/CoAPSerialize.h new file mode 100644 index 0000000..4a8177d --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/packages/iot-coap-c/CoAPSerialize.c b/iotkit-embedded/src/coap/CoAPPacket/CoAPSerialize_common.c similarity index 85% rename from iotkit-embedded/src/packages/iot-coap-c/CoAPSerialize.c rename to iotkit-embedded/src/coap/CoAPPacket/CoAPSerialize_common.c index 3fb3b11..ae2f0d8 100644 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPSerialize.c +++ b/iotkit-embedded/src/coap/CoAPPacket/CoAPSerialize_common.c @@ -1,25 +1,14 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + #include +#include #include "CoAPSerialize.h" -#include "CoAPExport.h" +#include "iotx_coap_internal.h" int CoAPSerialize_Header(CoAPMessage *msg, unsigned char *buf, unsigned short buflen) { @@ -107,7 +96,7 @@ unsigned short CoAPSerialize_Options(CoAPMessage *msg, unsigned char * buf, uns int i = 0; unsigned short count = 0; - for (i = 0; i < msg->optnum; i++) + for (i = 0; i < msg->optcount; i++) { unsigned short len = 0; len = CoAPSerialize_Option(&msg->options[i], &buf[count]); @@ -154,7 +143,7 @@ unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg) int i = 0; unsigned short count = 0; - for (i = 0; i < msg->optnum; i++) + for (i = 0; i < msg->optcount; i++) { unsigned short len = 0; len = CoAPSerialize_OptionLen(&msg->options[i]); @@ -173,7 +162,7 @@ unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg) int CoAPSerialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen) { if(msg->payloadlen + 1 > buflen){ - return -1; + return 0; } if(msg->payloadlen > 0 && NULL != msg->payload) { @@ -221,7 +210,6 @@ int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short b ptr += count; remlen -= count; - count = CoAPSerialize_Options(msg, ptr, remlen); ptr += count; remlen -= count; diff --git a/iotkit-embedded/src/coap/client/Cloud_CoAPExport.h b/iotkit-embedded/src/coap/client/Cloud_CoAPExport.h new file mode 100644 index 0000000..5e0016c --- /dev/null +++ b/iotkit-embedded/src/coap/client/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/iotkit-embedded/src/coap/client/Cloud_CoAPMessage.h b/iotkit-embedded/src/coap/client/Cloud_CoAPMessage.h new file mode 100644 index 0000000..5899698 --- /dev/null +++ b/iotkit-embedded/src/coap/client/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/iotkit-embedded/src/coap/client/Cloud_CoAPNetwork.h b/iotkit-embedded/src/coap/client/Cloud_CoAPNetwork.h new file mode 100644 index 0000000..43ec5b1 --- /dev/null +++ b/iotkit-embedded/src/coap/client/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/iotkit-embedded/src/coap/client/Cloud_CoAPPlatform.h b/iotkit-embedded/src/coap/client/Cloud_CoAPPlatform.h new file mode 100644 index 0000000..8e8da17 --- /dev/null +++ b/iotkit-embedded/src/coap/client/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/iotkit-embedded/src/packages/iot-coap-c/CoAPExport.c b/iotkit-embedded/src/coap/client/CoAPExport.c similarity index 74% rename from iotkit-embedded/src/packages/iot-coap-c/CoAPExport.c rename to iotkit-embedded/src/coap/client/CoAPExport.c index 294ad90..5c9a6de 100644 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPExport.c +++ b/iotkit-embedded/src/coap/client/CoAPExport.c @@ -1,30 +1,16 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ #include #include #include +#include "iotx_coap_internal.h" #include "ctype.h" -#include "iot_import.h" - -#include "CoAPNetwork.h" -#include "CoAPExport.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 */ @@ -33,8 +19,8 @@ #define COAP_DEFAULT_HOST_LEN 128 #define COAP_DEFAULT_WAIT_TIME_MS 2000 -unsigned int CoAPUri_parse(char *p_uri, coap_endpoint_type *p_endpoint_type, - char host[COAP_DEFAULT_HOST_LEN], unsigned short *port) +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; @@ -42,6 +28,7 @@ unsigned int CoAPUri_parse(char *p_uri, coap_endpoint_type *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; @@ -59,6 +46,20 @@ unsigned int CoAPUri_parse(char *p_uri, coap_endpoint_type *p_endpoint_type, --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; @@ -120,21 +121,21 @@ unsigned int CoAPUri_parse(char *p_uri, coap_endpoint_type *p_endpoint_type, } -CoAPContext *CoAPContext_create(CoAPInitParam *param) +Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param) { unsigned int ret = COAP_SUCCESS; - CoAPContext *p_ctx = NULL; + 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(CoAPContext)); + 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(CoAPContext)); + 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); @@ -162,7 +163,7 @@ CoAPContext *CoAPContext_create(CoAPInitParam *param) /*set the endpoint type by uri schema*/ if (NULL != param->url) { - ret = CoAPUri_parse(param->url, &network_param.ep_type, host, &network_param.port); + ret = Cloud_CoAPUri_parse(param->url, &network_param.ep_type, host, &network_param.port); } if (COAP_SUCCESS != ret) { @@ -171,17 +172,18 @@ CoAPContext *CoAPContext_create(CoAPInitParam *param) #ifdef COAP_DTLS_SUPPORT if (COAP_ENDPOINT_DTLS == network_param.ep_type) { - extern const char *iotx_coap_get_ca(void); - network_param.p_ca_cert_pem = (unsigned char *)iotx_coap_get_ca(); + 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) { + 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 = CoAPNetwork_init(&network_param, &p_ctx->network); + ret = Cloud_CoAPNetwork_init(&network_param, &p_ctx->network); if (COAP_SUCCESS != ret) { goto err; @@ -209,17 +211,17 @@ CoAPContext *CoAPContext_create(CoAPInitParam *param) return p_ctx; } -void CoAPContext_free(CoAPContext *p_ctx) +void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx) { + Cloud_CoAPSendNode *cur, *next; + if (NULL == p_ctx) { return; } - CoAPSendNode *cur, *next; - - CoAPNetwork_deinit(&p_ctx->network); + Cloud_CoAPNetwork_deinit(&p_ctx->network); - list_for_each_entry_safe(cur, next, &p_ctx->list.sendlist, sendlist, CoAPSendNode) { + 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); diff --git a/iotkit-embedded/src/coap/client/CoAPMessage.c b/iotkit-embedded/src/coap/client/CoAPMessage.c new file mode 100644 index 0000000..4214d88 --- /dev/null +++ b/iotkit-embedded/src/coap/client/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/iotkit-embedded/src/packages/iot-coap-c/CoAPNetwork.c b/iotkit-embedded/src/coap/client/CoAPNetwork.c similarity index 52% rename from iotkit-embedded/src/packages/iot-coap-c/CoAPNetwork.c rename to iotkit-embedded/src/coap/client/CoAPNetwork.c index d1b9a89..6884707 100644 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPNetwork.c +++ b/iotkit-embedded/src/coap/client/CoAPNetwork.c @@ -1,54 +1,58 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ + + #include #include #include #include -#include "iot_import.h" -#include "CoAPExport.h" -#include "iot_import_coap.h" -#include "iot_import_dtls.h" -#include "CoAPNetwork.h" +#include "iotx_coap_internal.h" +#include "Cloud_CoAPExport.h" +#include "Cloud_CoAPNetwork.h" #ifdef COAP_DTLS_SUPPORT -static void CoAPNetworkDTLS_freeSession(void *p_session); +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 CoAPNetworkDTLS_read(void *p_session, - unsigned char *p_data, - unsigned int *p_datalen, - unsigned int timeout) +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); - CoAPNetworkDTLS_freeSession(context); + COAP_INFO("dtls session read failed, return (0x%04x)", err_code); + Cloud_CoAPNetworkDTLS_freeSession(context); } if (DTLS_SUCCESS == err_code) { return COAP_SUCCESS; @@ -60,9 +64,9 @@ unsigned int CoAPNetworkDTLS_read(void *p_session, return COAP_ERROR_INVALID_PARAM; } -unsigned int CoAPNetworkDTLS_write(void *p_session, - const unsigned char *p_data, - unsigned int *p_datalen) +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) { @@ -76,19 +80,26 @@ unsigned int CoAPNetworkDTLS_write(void *p_session, return COAP_ERROR_INVALID_PARAM; } -static void CoAPNetworkDTLS_freeSession(void *p_session) +static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session) { /* Free the session.*/ HAL_DTLSSession_free((DTLSContext *)p_session); } -void *CoAPNetworkDTLS_createSession(char *p_host, - unsigned short port, - unsigned char *p_ca_cert_pem) +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; @@ -100,18 +111,18 @@ void *CoAPNetworkDTLS_createSession(char *p_host, #endif -unsigned int CoAPNetwork_write(coap_network_t *p_network, - const unsigned char *p_data, - unsigned int datalen) +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 = CoAPNetworkDTLS_write(p_network->context, p_data, &datalen); + rc = Cloud_CoAPNetworkDTLS_write(p_network->context, p_data, &datalen); } else { #endif - rc = HAL_UDP_write((void *)p_network->context, p_data, datalen); + rc = HAL_UDP_write((intptr_t)p_network->context, p_data, datalen); COAP_DEBUG("[CoAP-NWK]: Network write return %d", rc); if (-1 == rc) { @@ -125,29 +136,31 @@ unsigned int CoAPNetwork_write(coap_network_t *p_network, return (unsigned int)rc; } -int CoAPNetwork_read(coap_network_t *network, unsigned char *data, - unsigned int datalen, unsigned int timeout) +int Cloud_CoAPNetwork_read(coap_network_t *network, unsigned char *data, + unsigned int datalen, unsigned int timeout) { - unsigned int len = 0; + int len = 0; #ifdef COAP_DTLS_SUPPORT if (COAP_ENDPOINT_DTLS == network->ep_type) { len = datalen; memset(data, 0x00, datalen); - CoAPNetworkDTLS_read(network->context, data, &len, timeout); + Cloud_CoAPNetworkDTLS_read(network->context, data, (unsigned int *)&len, timeout); } else { #endif memset(data, 0x00, datalen); - len = HAL_UDP_readTimeout((void *)network->context, + len = HAL_UDP_readTimeout((intptr_t)network->context, data, COAP_MSG_MAX_PDU_LEN, timeout); #ifdef COAP_DTLS_SUPPORT } #endif - COAP_TRC("<< CoAP recv %d bytes data", len); + if (len > 0) { + COAP_TRC("<< CoAP recv %d bytes data", len); + } return len; } -unsigned int CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t *p_network) +unsigned int Cloud_CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t *p_network) { unsigned int err_code = COAP_SUCCESS; @@ -160,16 +173,17 @@ unsigned int CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t #ifdef COAP_DTLS_SUPPORT if (COAP_ENDPOINT_DTLS == p_param->ep_type) { - p_network->context = CoAPNetworkDTLS_createSession(p_param->p_host, + 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) { + if (COAP_ENDPOINT_NOSEC == p_param->ep_type + || COAP_ENDPOINT_PSK == p_param->ep_type) { /*Create udp socket*/ - p_network->context = HAL_UDP_create(p_param->p_host, p_param->port); + 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; } @@ -178,18 +192,19 @@ unsigned int CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t } -unsigned int CoAPNetwork_deinit(coap_network_t *p_network) +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) { - CoAPNetworkDTLS_freeSession(p_network->context); + Cloud_CoAPNetworkDTLS_freeSession(p_network->context); p_network->context = NULL; } #endif - if (COAP_ENDPOINT_NOSEC == p_network->ep_type) { - HAL_UDP_close(p_network->context); + 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/iotkit-embedded/src/coap/client/README.md b/iotkit-embedded/src/coap/client/README.md new file mode 100644 index 0000000..1fb7b45 --- /dev/null +++ b/iotkit-embedded/src/coap/client/README.md @@ -0,0 +1,45 @@ +# README.md: coap cloud + +## Contents + +```shell +. +├── aos.mk +├── Cloud_CoAPDeserialize.h +├── Cloud_CoAPExport.h +├── Cloud_CoAPMessage.h +├── Cloud_CoAPNetwork.h +├── Cloud_CoAPPlatform.h +├── Cloud_CoAPSerialize.h +├── CMakeLists.txt +├── CoAPDeserialize.c +├── CoAPExport.c +├── CoAPMessage.c +├── CoAPNetwork.c +├── CoAPSerialize.c +├── Config.in +├── iot.mk +├── iotx_ca_cert.c +└── iotx_coap_api.c + +``` + +## Introduction +Implementation of coap protocol and special customization for connecting alicloud iot platform + + +### Features + + + +### Dependencies + +- **hal**. osal and hal to shield different os and hardware +- **infra**. Authentication, net and so on tool set. + +## API +Please refer to [coap api](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Prog_Guide/API/CoAP_Provides#iot_coap_init) for API details. +## Reference +Please refer to [coap connect](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Prog_Guide/CoAP_Connect) for example details. + + diff --git a/iotkit-embedded/src/coap/client/iotx_coap_api.c b/iotkit-embedded/src/coap/client/iotx_coap_api.c new file mode 100644 index 0000000..2aa5cd4 --- /dev/null +++ b/iotkit-embedded/src/coap/client/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/iotkit-embedded/src/sdk-impl/exports/iot_export_coap.h b/iotkit-embedded/src/coap/coap_api.h similarity index 86% rename from iotkit-embedded/src/sdk-impl/exports/iot_export_coap.h rename to iotkit-embedded/src/coap/coap_api.h index 3e02ad4..2959968 100644 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_coap.h +++ b/iotkit-embedded/src/coap/coap_api.h @@ -1,31 +1,15 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ - - #ifndef __IOTX_COAP_API_H__ #define __IOTX_COAP_API_H__ -#define IOTX_PRODUCT_KEY_LEN (20) /* IoTx product key length */ -#define IOTX_DEVICE_NAME_LEN (32) /* IoTx device name length */ -#define IOTX_DEVICE_ID_LEN (64) /* IoTx device ID length */ -#define IOTX_DEVICE_SECRET_LEN (64) /* IoTx device secret length */ +#if defined(__cplusplus) +extern "C" { +#endif +#include "infra_defs.h" /*iotx return code definition*/ typedef enum { @@ -51,6 +35,8 @@ typedef enum { 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 */ @@ -77,10 +63,17 @@ typedef void (*iotx_event_handle_t)(void *context, iotx_coap_event_t event, void 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_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 { @@ -211,4 +204,7 @@ 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/iotkit-embedded/src/coap/coap_wrapper.h b/iotkit-embedded/src/coap/coap_wrapper.h new file mode 100644 index 0000000..1419f55 --- /dev/null +++ b/iotkit-embedded/src/coap/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); + +int HAL_DTLSHooks_set(dtls_hooks_t *hooks); +DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options); +unsigned int HAL_DTLSSession_write(DTLSContext *context, + const unsigned char *p_data, + unsigned int *p_datalen); +unsigned int HAL_DTLSSession_read(DTLSContext *context, + unsigned char *p_data, + unsigned int *p_datalen, + unsigned int timeout_ms); +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/iotkit-embedded/src/coap/examples/coap_example.c b/iotkit-embedded/src/coap/examples/coap_example.c new file mode 100644 index 0000000..78e71ab --- /dev/null +++ b/iotkit-embedded/src/coap/examples/coap_example.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include +#if !defined(_WIN32) + #include +#endif + +#include "coap_api.h" +#include "coap_wrapper.h" + +#define IOTX_DAILY_DTLS_SERVER_URI "coaps://11.239.164.238:5684" +#define IOTX_DAILY_PSK_SERVER_URI "coap-psk://10.101.83.159:5682" + +#define IOTX_PRE_DTLS_SERVER_URI "coaps://pre.coap.cn-shanghai.link.aliyuncs.com:5684" +#define IOTX_PRE_NOSEC_SERVER_URI "coap://pre.coap.cn-shanghai.link.aliyuncs.com:5683" +#define IOTX_PRE_PSK_SERVER_URI "coap-psk://pre.coap.cn-shanghai.link.aliyuncs.com:5683" + +/* online url */ +#define IOTX_ONLINE_DTLS_SERVER_URL "coaps://%s.coap.cn-shanghai.link.aliyuncs.com:5684" +#define IOTX_ONLINE_NOSEC_SERVER_URI "coap://%s.coap.cn-shanghai.link.aliyuncs.com:5683" +#define IOTX_ONLINE_PSK_SERVER_URL "coap-psk://%s.coap.cn-shanghai.link.aliyuncs.com:5682" + +char m_coap_client_running = 0; +char m_coap_reconnect = 0; + +static void iotx_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); + HAL_Printf("[APPL]: Message response code: 0x%x\r\n", resp_code); + HAL_Printf("[APPL]: Len: %d, Payload: %s\r\n", len, p_payload); +} + +char IOTX_PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0}; +char IOTX_DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0}; +char IOTX_DEVICE_SECRET[IOTX_DEVICE_SECRET_LEN + 1] = {0}; + +int iotx_get_devinfo(iotx_deviceinfo_t *p_devinfo) +{ + if (NULL == p_devinfo) { + return IOTX_ERR_INVALID_PARAM; + } + + memset(p_devinfo, 0x00, sizeof(iotx_deviceinfo_t)); + + /**< get device info*/ + HAL_GetProductKey(p_devinfo->product_key); + HAL_GetDeviceName(p_devinfo->device_name); + HAL_GetDeviceSecret(p_devinfo->device_secret); + memset(p_devinfo->device_id, 0, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2); + 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); + /**< end*/ + + fprintf(stderr, "*****The Product Key : %s *****\r\n", p_devinfo->product_key); + fprintf(stderr, "*****The Device Name : %s *****\r\n", p_devinfo->device_name); + fprintf(stderr, "*****The Device Secret: %s *****\r\n", p_devinfo->device_secret); + fprintf(stderr, "*****The Device ID : %s *****\r\n", p_devinfo->device_id); + return IOTX_SUCCESS; +} + +static void iotx_post_data_to_server(void *param) +{ + char path[IOTX_URI_MAX_LEN + 1] = {0}; + iotx_message_t message; + iotx_deviceinfo_t devinfo; + + memset(&message, 0, sizeof(iotx_message_t)); + memset(&devinfo, 0, sizeof(iotx_deviceinfo_t)); + + message.p_payload = (unsigned char *)"{\"name\":\"hello world\"}"; + message.payload_len = strlen("{\"name\":\"hello world\"}"); + message.resp_callback = iotx_response_handler; + message.msg_type = IOTX_MESSAGE_CON; + message.content_type = IOTX_CONTENT_TYPE_JSON; + iotx_coap_context_t *p_ctx = (iotx_coap_context_t *)param; + + iotx_get_devinfo(&devinfo); + snprintf(path, IOTX_URI_MAX_LEN, "/topic/%s/%s/update/", (char *)devinfo.product_key, + (char *)devinfo.device_name); + + IOT_CoAP_SendMessage(p_ctx, path, &message); +} + +void show_usage() +{ + HAL_Printf("\r\nusage: coap-example [OPTION]...\r\n"); + HAL_Printf("\t-e pre|online|daily\t\tSet the cloud environment.\r\n"); + HAL_Printf("\t-s nosec|dtls|psk \t\tSet the security setting.\r\n"); + HAL_Printf("\t-l \t\tSet the program run loop.\r\n"); + HAL_Printf("\t-r \t\tTesting the DTLS session ticket.\r\n"); + HAL_Printf("\t-h \t\tShow this usage.\r\n"); +} + +int main(int argc, char **argv) +{ + int count = 0; + char secur[32] = {0}; + char env[32] = {0}; + int opt; + iotx_coap_config_t config; + iotx_deviceinfo_t deviceinfo; + + /* set device info use HAL function */ + HAL_GetProductKey(IOTX_PRODUCT_KEY); + HAL_GetDeviceName(IOTX_DEVICE_NAME); + HAL_GetDeviceSecret(IOTX_DEVICE_SECRET); + + IOT_SetLogLevel(IOT_LOG_DEBUG); + +#if !defined(_WIN32) && !defined(BUILD_AOS) + while ((opt = getopt(argc, argv, "e:s:lhr")) != -1) { + switch (opt) { + case 's': { + if (strlen(optarg) > 31) { + memcpy(secur, optarg, 31); + } else { + memcpy(secur, optarg, strlen(optarg)); + } + } + break; + case 'e': { + if (strlen(optarg) > 31) { + memcpy(env, optarg, 31); + } else { + memcpy(env, optarg, strlen(optarg)); + } + } + break; + case 'l': + m_coap_client_running = 1; + break; + case 'r': + m_coap_reconnect = 1; + break; + case 'h': + show_usage(); + return 0; + default: + break; + } + } +#else + /* Just use psk security mode, online environment */ + (void)argc; + (void)argv; + (void)opt; + memcpy(secur, "psk", 4); + memcpy(env, "online", 7); + m_coap_client_running = 1; + m_coap_reconnect = 1; +#endif + + HAL_Printf("[COAP-Client]: Enter Coap Client\r\n"); + memset(&config, 0x00, sizeof(iotx_coap_config_t)); + if (0 == strncmp(env, "pre", strlen("pre"))) { + if (0 == strncmp(secur, "dtls", strlen("dtls"))) { + config.p_url = IOTX_PRE_DTLS_SERVER_URI; + } else if (0 == strncmp(secur, "psk", strlen("psk"))) { + config.p_url = IOTX_PRE_PSK_SERVER_URI; + } else { + config.p_url = IOTX_PRE_NOSEC_SERVER_URI; + } + } else if (0 == strncmp(env, "online", strlen("online"))) { + if (0 == strncmp(secur, "dtls", strlen("dtls"))) { + char url[256] = {0}; + snprintf(url, sizeof(url), IOTX_ONLINE_DTLS_SERVER_URL, IOTX_PRODUCT_KEY); + config.p_url = url; + } else if (0 == strncmp(secur, "psk", strlen("psk"))) { + char url[256] = {0}; + snprintf(url, sizeof(url), IOTX_ONLINE_PSK_SERVER_URL, IOTX_PRODUCT_KEY); + config.p_url = url; + + } else { + HAL_Printf("Online environment must access with DTLS/PSK\r\n"); + IOT_SetLogLevel(IOT_LOG_NONE); + return -1; + } + } else if (0 == strncmp(env, "daily", strlen("daily"))) { + if (0 == strncmp(secur, "dtls", strlen("dtls"))) { + config.p_url = IOTX_DAILY_DTLS_SERVER_URI; + } else if (0 == strncmp(secur, "psk", strlen("psk"))) { + config.p_url = IOTX_DAILY_PSK_SERVER_URI; + + } + } + + iotx_get_devinfo(&deviceinfo); + config.p_devinfo = (iotx_device_info_t *)&deviceinfo; + config.wait_time_ms = 3000; + + iotx_coap_context_t *p_ctx = NULL; + +reconnect: + p_ctx = IOT_CoAP_Init(&config); + if (NULL != p_ctx) { + IOT_CoAP_DeviceNameAuth(p_ctx); + do { + if (count == 11 || 0 == count) { + iotx_post_data_to_server((void *)p_ctx); + count = 1; + } + count ++; + IOT_CoAP_Yield(p_ctx); + } while (m_coap_client_running); + + IOT_CoAP_Deinit(&p_ctx); + } else { + HAL_Printf("IoTx CoAP init failed\r\n"); + } + if (m_coap_reconnect) { + m_coap_reconnect = 0; + goto reconnect; + } + + IOT_DumpMemoryStats(IOT_LOG_DEBUG); + IOT_SetLogLevel(IOT_LOG_NONE); + HAL_Printf("[COAP-Client]: Exit Coap Client\r\n"); + return 0; +} diff --git a/iotkit-embedded/src/coap/iot.mk b/iotkit-embedded/src/coap/iot.mk index 4311632..b53a2ea 100644 --- a/iotkit-embedded/src/coap/iot.mk +++ b/iotkit-embedded/src/coap/iot.mk @@ -1,5 +1,13 @@ -LIBA_TARGET := libiot_coap.a -HDR_REFS := src +LIBA_TARGET := libiot_coap.a +HDR_REFS := src/infra +LIB_SRCS_PATTERN := *.c -LIB_SRCS := $(wildcard $(TOP_DIR)/$(MODULE_NAME)/*.c) -LIB_SRCS += $(wildcard $(PACKAGE_DIR)/iot-coap-c/*.c) +$(call Append_Conditional, LIB_SRCS_PATTERN, client/*.c, COAP_CLIENT) +$(call Append_Conditional, LIB_SRCS_PATTERN, CoAPPacket/*.c, COAP_PACKET) +$(call Append_Conditional, LIB_SRCS_PATTERN, server/*.c, COAP_SERVER) + +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +$(call Append_Conditional, LIB_SRCS_EXCLUDE, examples/coap_example.c, COAP_CLIENT) +$(call Append_Conditional, SRCS_coap-example, examples/coap_example.c, COAP_CLIENT) +$(call Append_Conditional, TARGET, coap-example, COAP_CLIENT) \ No newline at end of file diff --git a/iotkit-embedded/src/coap/iotx_ca_cert.c b/iotkit-embedded/src/coap/iotx_ca_cert.c deleted file mode 100644 index abbf8a9..0000000 --- a/iotkit-embedded/src/coap/iotx_ca_cert.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include - -const char iotx_coap_ca_crt_rsa[] = - "-----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-----"; - - - -const char *iotx_coap_get_ca(void) -{ - return iotx_coap_ca_crt_rsa; -} - diff --git a/iotkit-embedded/src/coap/iotx_coap.h b/iotkit-embedded/src/coap/iotx_coap.h new file mode 100644 index 0000000..e557ef7 --- /dev/null +++ b/iotkit-embedded/src/coap/iotx_coap.h @@ -0,0 +1,2 @@ +#include "CoAPServer.h" +#include "iotx_coap_internal.h" diff --git a/iotkit-embedded/src/coap/iotx_coap_api.c b/iotkit-embedded/src/coap/iotx_coap_api.c deleted file mode 100644 index 03921d3..0000000 --- a/iotkit-embedded/src/coap/iotx_coap_api.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include - -#include "iot_import.h" -#include "iot_export_errno.h" - -#include "lite-utils.h" -#include "utils_hmac.h" -#include "json_parser.h" -#include "CoAPMessage.h" -#include "CoAPExport.h" -#include "lite-system.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) - - -#define IOTX_AUTH_STR "auth" -#define IOTX_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%s" -#define IOTX_AUTH_DEVICENAME_STR "{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\",\"sign\":\"%s\"}" - -#define IOTX_COAP_ONLINE_DTLS_SERVER_URL "coaps://%s.iot-as-coap.cn-shanghai.aliyuncs.com:5684" - - -typedef struct { - char *p_auth_token; - int auth_token_len; - char is_authed; - iotx_deviceinfo_t *p_devinfo; - CoAPContext *p_coap_ctx; - unsigned int coap_token; - 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; -} - -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); - 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)); - LITE_free(p_value); - return IOTX_SUCCESS; - } - - return IOTX_ERR_AUTH_FAILED; -} - -static void iotx_device_name_auth_callback(void *user, void *p_message) -{ - int ret_code = IOTX_SUCCESS; - iotx_coap_t *p_iotx_coap = NULL; - CoAPMessage *message = (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: { - 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, 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; - CoAPContext *p_coap_ctx = NULL; - iotx_coap_t *p_iotx_coap = NULL; - CoAPMessage message; - unsigned char token[8] = {0}; - - p_iotx_coap = (iotx_coap_t *)p_context; - p_coap_ctx = (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, CoAPMessageId_gen(p_coap_ctx)); - len = iotx_get_coap_token(p_iotx_coap, token); - CoAPMessageToken_set(&message, token, len); - 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); - CoAPMessage_send(p_coap_ctx, &message); - CoAPMessage_destory(&message); - return IOTX_SUCCESS; -} - -static void iotx_coap_mid_rsphdl(void *arg, void *p_response) -{ - int p_payload_len = 0; - unsigned char *p_payload = NULL; - char *msg = 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); - log_debug("MID Report: CoAP response code = %d", resp_code); - log_debug("MID Report: CoAP msg_len = %d", p_payload_len); - if (p_payload_len > 0) { - log_debug("MID Report: CoAP msg = '%s'", p_payload); - msg = json_get_value_by_name((char *)p_payload, p_payload_len, "id", &p_payload_len, 0); - if (NULL != msg) { - log_debug("MID Report: CoAP mid_report responseID = '%s'", msg); - } else { - log_warning("MID Report: CoAP mid_report responseID not found in msg"); - } - } else { - log_warning("MID Report: CoAP response payload_len = 0"); - } -} - -/* report ModuleID */ -static int iotx_coap_report_mid(iotx_coap_context_t *p_context) -{ - int ret; - char topic_name[IOTX_URI_MAX_LEN + 1]; - iotx_message_t message; - char requestId[MIDREPORT_REQID_LEN + 1] = {0}; - iotx_coap_t *p_iotx_coap = (iotx_coap_t *)p_context; - char pid[PID_STRLEN_MAX + 1] = {0}; - char mid[MID_STRLEN_MAX + 1] = {0}; - CoAPContext *p_coap_ctx = NULL; - - memset(pid, 0, sizeof(pid)); - memset(mid, 0, sizeof(mid)); - - if (0 == HAL_GetPartnerID(pid)) { - log_debug("PartnerID is Null"); - return SUCCESS_RETURN; - } - if (0 == HAL_GetModuleID(mid)) { - log_debug("ModuleID is Null"); - return SUCCESS_RETURN; - } - if (NULL == p_iotx_coap) { - log_err("Invalid param: p_context is NULL"); - return FAIL_RETURN; - } - - log_debug("MID Report: started in CoAP"); - p_coap_ctx = (CoAPContext *)p_iotx_coap->p_coap_ctx; - - iotx_midreport_reqid(requestId, - p_iotx_coap->p_devinfo->product_key, - p_iotx_coap->p_devinfo->device_name); - /* 1,generate json data */ - char *msg = HAL_Malloc(MIDREPORT_PAYLOAD_LEN); - if (NULL == msg) { - log_err("allocate mem failed"); - return FAIL_RETURN; - } - - iotx_midreport_payload(msg, - requestId, - mid, - pid); - - log_debug("MID Report: json data = '%s'", msg); - - memset(&message, 0, sizeof(iotx_message_t)); - - message.p_payload = (unsigned char *)msg; - message.payload_len = (unsigned short)strlen(msg); - message.resp_callback = iotx_coap_mid_rsphdl; - message.msg_type = IOTX_MESSAGE_NON; - message.content_type = IOTX_CONTENT_TYPE_JSON; - - /* 2,generate topic name */ - ret = iotx_midreport_topic(topic_name, - "/topic", - p_iotx_coap->p_devinfo->product_key, - p_iotx_coap->p_devinfo->device_name); - - log_debug("MID Report: topic name = '%s'", topic_name); - - if (ret < 0) { - log_err("generate topic name of info failed"); - HAL_Free(msg); - return FAIL_RETURN; - } - - if (IOTX_SUCCESS != (ret = IOT_CoAP_SendMessage(p_context, topic_name, &message))) { - log_err("send CoAP msg failed, ret = %d", ret); - HAL_Free(msg); - return FAIL_RETURN; - } - HAL_Free(msg); - log_debug("MID Report: IOT_CoAP_SendMessage() = %d", ret); - - ret = CoAPMessage_recv(p_coap_ctx, CONFIG_COAP_AUTH_TIMEOUT, 1); - log_debug("MID Report: finished, ret = CoAPMessage_recv() = %d", ret); - - return SUCCESS_RETURN; -} - -int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context) -{ - int len = 0; - int ret = COAP_SUCCESS; - CoAPContext *p_coap_ctx = NULL; - iotx_coap_t *p_iotx_coap = NULL; - 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 = (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, CoAPMessageId_gen(p_coap_ctx)); - len = iotx_get_coap_token(p_iotx_coap, token); - CoAPMessageToken_set(&message, token, len); - 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; - } - 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: %p", message.payload); - COAP_DEBUG("Send authentication message to server"); - ret = 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 = 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; - } - - /* report module id */ - ret = iotx_coap_report_mid(p_context); - if (SUCCESS_RETURN != ret) { - COAP_DEBUG("Send ModuleId message to server(CoAP) failed ret = %d", ret); - return IOTX_ERR_SEND_MSG_FAILED; - } - - return IOTX_SUCCESS; -} - -static int iotx_split_path_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 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; -} - -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; - CoAPContext *p_coap_ctx = NULL; - iotx_coap_t *p_iotx_coap = NULL; - CoAPMessage message; - unsigned char token[8] = {0}; - - 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; - } - - - - 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 = (CoAPContext *)p_iotx_coap->p_coap_ctx; - if (p_iotx_coap->is_authed) { - - CoAPMessage_init(&message); - CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_CON); - CoAPMessageCode_set(&message, COAP_MSG_CODE_POST); - CoAPMessageId_set(&message, 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); - 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)); - - CoAPMessagePayload_set(&message, p_message->p_payload, p_message->payload_len); - - ret = CoAPMessage_send(p_coap_ctx, &message); - CoAPMessage_destory(&message); - if (COAP_ERROR_DATA_SIZE == ret) { - return IOTX_ERR_MSG_TOO_LOOG; - } - return IOTX_SUCCESS; - } else { - /* COAP_INFO("The client hasn't auth success"); */ - return IOTX_ERR_NOT_AUTHED; - } -} - - -int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload, int *p_len) -{ - CoAPMessage *message = NULL; - - if (NULL == p_message || NULL == pp_payload || NULL == p_len) { - COAP_ERR("Invalid paramter p_message %p, pp_payload %p, p_len %p", - p_message, pp_payload, p_len); - return IOTX_ERR_INVALID_PARAM; - } - message = (CoAPMessage *)p_message; - *pp_payload = message->payload; - *p_len = message->payloadlen; - - return IOTX_SUCCESS; -} - -int IOT_CoAP_GetMessageCode(void *p_message, iotx_coap_resp_code_t *p_resp_code) -{ - 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 = (CoAPMessage *)p_message; - *p_resp_code = (iotx_coap_resp_code_t) message->header.code; - - return IOTX_SUCCESS; -} - - -iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config) -{ - 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, IOTX_DEVICE_ID_LEN); - strncpy(p_iotx_coap->p_devinfo->product_key, p_config->p_devinfo->product_key, IOTX_PRODUCT_KEY_LEN); - strncpy(p_iotx_coap->p_devinfo->device_secret, p_config->p_devinfo->device_secret, IOTX_DEVICE_SECRET_LEN); - strncpy(p_iotx_coap->p_devinfo->device_name, p_config->p_devinfo->device_name, IOTX_DEVICE_NAME_LEN); - } - - /*Init coap token*/ - p_iotx_coap->coap_token = IOTX_COAP_INIT_TOKEN; - - /*Create coap context*/ - memset(¶m, 0x00, sizeof(CoAPInitParam)); - - if (NULL != p_config->p_url) { - param.url = p_config->p_url; - } else { - HAL_Snprintf(url, sizeof(url), IOTX_COAP_ONLINE_DTLS_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 = (CoAPEventNotifier)iotx_event_notifyer; - param.waittime = p_config->wait_time_ms; - p_iotx_coap->p_coap_ctx = 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; - - 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) { - 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) { - CoAPContext_free(p_iotx_coap->p_coap_ctx); - p_iotx_coap->p_coap_ctx = NULL; - } - coap_free(p_iotx_coap); - *pp_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 CoAPMessage_cycle(p_iotx_coap->p_coap_ctx); -} - diff --git a/iotkit-embedded/src/coap/iotx_coap_config.h b/iotkit-embedded/src/coap/iotx_coap_config.h new file mode 100644 index 0000000..489903e --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/iotx_coap_internal.h b/iotkit-embedded/src/coap/iotx_coap_internal.h new file mode 100644 index 0000000..364634e --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPExport.c b/iotkit-embedded/src/coap/server/CoAPExport.c new file mode 100644 index 0000000..d6e0397 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPExport.h b/iotkit-embedded/src/coap/server/CoAPExport.h new file mode 100644 index 0000000..bf2b9aa --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPInternal.h b/iotkit-embedded/src/coap/server/CoAPInternal.h new file mode 100644 index 0000000..b5441be --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPMessage.c b/iotkit-embedded/src/coap/server/CoAPMessage.c new file mode 100644 index 0000000..69e9631 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPMessage.h b/iotkit-embedded/src/coap/server/CoAPMessage.h new file mode 100644 index 0000000..f5b4350 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPNetwork.c b/iotkit-embedded/src/coap/server/CoAPNetwork.c new file mode 100644 index 0000000..8675544 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPNetwork.h b/iotkit-embedded/src/coap/server/CoAPNetwork.h new file mode 100644 index 0000000..361d640 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPObserve.c b/iotkit-embedded/src/coap/server/CoAPObserve.c new file mode 100644 index 0000000..3445070 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPObserve.h b/iotkit-embedded/src/coap/server/CoAPObserve.h new file mode 100644 index 0000000..8ecc78a --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/CoAPPlatform.c b/iotkit-embedded/src/coap/server/CoAPPlatform.c new file mode 100644 index 0000000..7468cbf --- /dev/null +++ b/iotkit-embedded/src/coap/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) +{ + char 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/iotkit-embedded/src/coap/server/CoAPResource.c b/iotkit-embedded/src/coap/server/CoAPResource.c new file mode 100644 index 0000000..a5872a8 --- /dev/null +++ b/iotkit-embedded/src/coap/server/CoAPResource.c @@ -0,0 +1,242 @@ +/* + * 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 (0 == strncmp((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; +} + +int CoAPResource_topicFilterMatch(const char *filter, const char *topic) +{ + if (filter == NULL || topic == NULL) { + return -1; + } + if (strncmp(filter, topic, strlen(filter) - 1) == 0) { + if (strlen(topic) > strlen(filter) - 1) { + const char *more = topic + (strlen(filter) - 1); + if (strstr(more, "/") == NULL) { + return 0; + } + } + } + return -1; +} + +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; + } + } + + list_for_each_entry(node, &ctx->resource.list, reslist, CoAPResource) { + if (node->path_type == PATH_FILTER && strlen(node->filter_path) > 0) { + if (CoAPResource_topicFilterMatch(node->filter_path, path) == 0) { + HAL_MutexUnlock(ctx->resource.list_mutex); + return node; + } + } + } + HAL_MutexUnlock(ctx->resource.list_mutex); + + return NULL; +} diff --git a/iotkit-embedded/src/coap/server/CoAPResource.h b/iotkit-embedded/src/coap/server/CoAPResource.h new file mode 100644 index 0000000..eee5ed1 --- /dev/null +++ b/iotkit-embedded/src/coap/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_topicFilterMatch(const char *filter, const char *topic); +int CoAPResource_deinit(CoAPContext *context); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/iotkit-embedded/src/coap/server/CoAPServer.c b/iotkit-embedded/src/coap/server/CoAPServer.c new file mode 100644 index 0000000..03b70e8 --- /dev/null +++ b/iotkit-embedded/src/coap/server/CoAPServer.c @@ -0,0 +1,312 @@ +/* + * 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; +} + + +static void *coap_init_mutex = NULL; +CoAPContext *CoAPServer_init() +{ + CoAPInitParam param = {0}; +#ifdef COAP_SERV_MULTITHREAD + int stack_used; + hal_os_thread_param_t task_parms = {0}; +#endif + + if (NULL == coap_init_mutex) { + coap_init_mutex = HAL_MutexCreate(); + + if (NULL == coap_init_mutex) { + return NULL; + } + } + HAL_MutexLock(coap_init_mutex); + + 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"); + HAL_MutexUnlock(coap_init_mutex); + 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; + HAL_MutexUnlock(coap_init_mutex); + 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"); + HAL_MutexUnlock(coap_init_mutex); + 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"); + } + + HAL_MutexUnlock(coap_init_mutex); + return (CoAPContext *)g_context; +} + +void CoAPServer_deinit(CoAPContext *context) +{ + if (context != g_context) { + COAP_INFO("Invalid CoAP Server context"); + return; + } + + if (NULL == coap_init_mutex) { + COAP_ERR("CoAP init mutex is NULL"); + return; + } + + HAL_MutexLock(coap_init_mutex); + + 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; + } + + HAL_MutexUnlock(coap_init_mutex); + HAL_MutexDestroy(coap_init_mutex); + coap_init_mutex = 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/iotkit-embedded/src/coap/server/CoAPServer.h b/iotkit-embedded/src/coap/server/CoAPServer.h new file mode 100644 index 0000000..795ef51 --- /dev/null +++ b/iotkit-embedded/src/coap/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/iotkit-embedded/src/coap/server/README.md b/iotkit-embedded/src/coap/server/README.md new file mode 100644 index 0000000..5929bdf --- /dev/null +++ b/iotkit-embedded/src/coap/server/README.md @@ -0,0 +1,50 @@ +# README.md: coap local + +## Contents + +```shell +. +├── aos.mk +├── CMakeLists.txt +├── CoAPDeserialize.c +├── CoAPDeserialize.h +├── CoAPExport.c +├── CoAPExport.h +├── CoAPInternal.h +├── CoAPMessage.c +├── CoAPMessage.h +├── CoAPNetwork.c +├── CoAPNetwork.h +├── CoAPObserve.c +├── CoAPObserve.h +├── CoAPPlatform.c +├── CoAPPlatform.h +├── CoAPResource.c +├── CoAPResource.h +├── CoAPSerialize.c +├── CoAPSerialize.h +├── CoAPServer.c +├── CoAPServer.h +├── Config.in +├── iot.mk +└── README.md +``` + +## Introduction +Implementation of coap protocol and special customization for alcs and awss + + +### Features + + +### Dependencies + +- **hal**. osal and hal to shield different os and hardware +- **infra**. Authentication, net and so on tool set. + +## API +none +## Reference +none + + diff --git a/iotkit-embedded/src/configs/config.rtthread.gcc b/iotkit-embedded/src/configs/config.rtthread.gcc deleted file mode 100644 index a632c3d..0000000 --- a/iotkit-embedded/src/configs/config.rtthread.gcc +++ /dev/null @@ -1,15 +0,0 @@ -CONFIG_ENV_CFLAGS = -mcpu=arm968e-s -mthumb-interwork -mthumb -ffunction-sections -fdata-sections \ - -D_PLATFORM_IS_RTTHREAD_ -DIOTX_NET_INIT_WITH_PK_EXT - -OVERRIDE_CC = arm-none-eabi-gcc -OVERRIDE_CXX = arm-none-eabi-g++ -OVERRIDE_AS = arm-none-eabi-gcc -OVERRIDE_AR = arm-none-eabi-ar -OVERRIDE_LINK = arm-none-eabi-g++ - -CONFIG_src/platform = -CONFIG_sample = -CONFIG_src/sdk-tests = -CONFIG_src/tls = - -CURRENT_PLATFORM = _PLATFORM_IS_RTTHREAD_ \ No newline at end of file diff --git a/iotkit-embedded/src/configs/config.ubuntu.x86 b/iotkit-embedded/src/configs/config.ubuntu.x86 deleted file mode 100644 index 5ee3719..0000000 --- a/iotkit-embedded/src/configs/config.ubuntu.x86 +++ /dev/null @@ -1,19 +0,0 @@ -CONFIG_ENV_CFLAGS += \ - -Os -Wall -Werror \ - -g3 --coverage \ - -D_PLATFORM_IS_LINUX_ \ - -D__UBUNTU_SDK_DEMO__ \ - -DCONFIG_HTTP_AUTH_TIMEOUT=500 \ - -DCONFIG_MID_HTTP_TIMEOUT=500 \ - -DCONFIG_GUIDER_AUTH_TIMEOUT=500 \ - -DUSING_UTILS_JSON \ - -DIOTX_NET_INIT_WITH_PK_EXT \ - -DUSING_SHA1_IN_HMAC \ - -ifneq (Darwin,$(strip $(shell uname))) -CONFIG_ENV_CFLAGS += -rdynamic -endif - -LDFLAGS += -lpthread - -OVERRIDE_STRIP := strip diff --git a/iotkit-embedded/src/configs/config.win7.mingw32 b/iotkit-embedded/src/configs/config.win7.mingw32 deleted file mode 100644 index be26de7..0000000 --- a/iotkit-embedded/src/configs/config.win7.mingw32 +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_ENV_CFLAGS += \ - -Os -Wall -Werror \ - -D_PLATFORM_IS_WINDOWS_ \ - -DUSING_UTILS_JSON \ - -DIOTX_NET_INIT_WITH_PK_EXT \ - -CROSS_PREFIX := i686-w64-mingw32- - -CONFIG_src/coap := diff --git a/iotkit-embedded/src/configs/default_settings.mk b/iotkit-embedded/src/configs/default_settings.mk deleted file mode 100644 index dc04034..0000000 --- a/iotkit-embedded/src/configs/default_settings.mk +++ /dev/null @@ -1,34 +0,0 @@ -DEFAULT_BLD := src/configs/config.ubuntu.x86 -POST_FINAL_OUT_HOOK := Post_Distro -SUBDIRS := directory-not-exist-actually - -ifeq (Darwin,$(shell uname)) -POST_FINAL_OUT_HOOK := -endif - -FEATURE_MQTT_SHADOW ?= $(FEATURE_MQTT_COMM_ENABLED) -FEATURE_COAP_DTLS_SUPPORT ?= $(FEATURE_COAP_COMM_ENABLED) -FEATURE_MQTT_ID2_AUTH ?= n -FEATURE_MQTT_ID2_CRYPTO ?= n -FEATURE_OTA_ENABLED ?= y -FEATURE_OTA_FETCH_CHANNEL ?= HTTP -FEATURE_OTA_SIGNAL_CHANNEL ?= MQTT -FEATURE_MQTT_ID2_ENV ?= online -FEATURE_MQTT_COMM_ENABLED ?= n -FEATURE_SERVICE_COTA_ENABLED ?= n - -CONFIG_LIB_EXPORT ?= static - -# gateway & subdevice -FEATURE_SUBDEVICE_STATUS ?= gateway -# MQTT & CLOUD_CONN -FEATURE_SUBDEVICE_CHANNEL ?= MQTT - -FEATURE_CMP_VIA_MQTT_DIRECT ?= y -# MQTT & COAP & HTTP -FEATURE_CMP_VIA_CLOUD_CONN ?= MQTT - -FEATURE_SUPPORT_PRODUCT_SECRET ?= n - -#CFLAGS += -DFORCE_SSL_VERIFY - diff --git a/iotkit-embedded/src/cota/CMakeLists.txt b/iotkit-embedded/src/cota/CMakeLists.txt deleted file mode 100644 index bb65553..0000000 --- a/iotkit-embedded/src/cota/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -file(GLOB C_SOURCES "config_ota.c") -add_library(cota STATIC ${C_SOURCES}) - -target_link_libraries(cota iot_sdk) \ No newline at end of file diff --git a/iotkit-embedded/src/cota/config_ota.c b/iotkit-embedded/src/cota/config_ota.c deleted file mode 100644 index 479022d..0000000 --- a/iotkit-embedded/src/cota/config_ota.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * config_ota.c - * - * Created on: 2018313 - * Author: wb-jn347227 - */ - - -#include -#include -#include -#include - -#include "iot_import.h" -#include "class_interface.h" -#include "iot_export_dm.h" -#include "iot_export_cota.h" -#include "iot_export_cmp.h" -#include "iot_export_errno.h" -#include "lite-utils.h" - -static void config_ota_handler(void* pcontext, iotx_cmp_cota_parameter_t* ota_parameter, void* user_data) -{ - iotx_cmp_cota_parameter_t* iotx_cmp_ota_parameter = ota_parameter; - config_ota_t* config_ota = user_data; - - log_info("\n\n%s\n\n", iotx_cmp_ota_parameter->url); - /**< save config*/ - if (config_ota->_rsp_configId) config_ota_lite_free(config_ota->_rsp_configId); - if (config_ota->_rsp_getType) config_ota_lite_free(config_ota->_rsp_getType); - if (config_ota->_rsp_sign) config_ota_lite_free(config_ota->_rsp_sign); - if (config_ota->_rsp_signMethod) config_ota_lite_free(config_ota->_rsp_signMethod); - if (config_ota->_rsp_url) config_ota_lite_free(config_ota->_rsp_url); - - config_ota->_rsp_configId = config_ota_lite_malloc(strlen(iotx_cmp_ota_parameter->configId) + 1); - if (config_ota->_rsp_configId == NULL) { - log_err("rsp_configid malloc fail."); - return; - } - config_ota->_rsp_getType = config_ota_lite_malloc(strlen(iotx_cmp_ota_parameter->getType) + 1); - if (config_ota->_rsp_getType == NULL) { - log_err("_rsp_getType malloc fail."); - return; - } - config_ota->_rsp_sign = config_ota_lite_malloc(strlen(iotx_cmp_ota_parameter->sign) + 1); - if (config_ota->_rsp_sign == NULL) { - log_err("_rsp_sign malloc fail."); - return; - } - config_ota->_rsp_signMethod = config_ota_lite_malloc(strlen(iotx_cmp_ota_parameter->signMethod) + 1); - if (config_ota->_rsp_signMethod == NULL) { - log_err("_rsp_signMethod malloc fail."); - return; - } - config_ota->_rsp_url = config_ota_lite_malloc(strlen(iotx_cmp_ota_parameter->url) + 1); - if (config_ota->_rsp_url == NULL) { - log_err("_rsp_url malloc fail."); - return; - } - strcpy(config_ota->_rsp_configId, iotx_cmp_ota_parameter->configId); - strcpy(config_ota->_rsp_getType, iotx_cmp_ota_parameter->getType); - strcpy(config_ota->_rsp_sign, iotx_cmp_ota_parameter->sign); - strcpy(config_ota->_rsp_signMethod, iotx_cmp_ota_parameter->signMethod); - strcpy(config_ota->_rsp_url, iotx_cmp_ota_parameter->url); - config_ota->_rsp_configSize = ota_parameter->configSize; - /**< end*/ - - - log_debug("_rsp_configId %s", config_ota->_rsp_configId); - log_debug("_rsp_configSize %u", config_ota->_rsp_configSize); - log_debug("_rsp_getType %s", config_ota->_rsp_getType); - log_debug("_rsp_sign %s", config_ota->_rsp_sign); - log_debug("_rsp_signMethod %s", config_ota->_rsp_signMethod); - log_debug("_rsp_url %s", config_ota->_rsp_url); - - /* invoke callback funtions. */ - if (config_ota->_linkkit_callback_fp) { - ((handle_service_cota_callback_fp_t)config_ota->_linkkit_callback_fp)(service_cota_callback_type_new_version_detected, - config_ota->_rsp_configId, - config_ota->_rsp_configSize, - config_ota->_rsp_getType, - config_ota->_rsp_sign, - config_ota->_rsp_signMethod, - config_ota->_rsp_url); - } -} - -static void config_ota_cmp_event_handler(void* pcontext, iotx_cmp_event_msg_t* msg, void* user_data) -{ - config_ota_t* config_ota = user_data; - int ret; - - log_info("\n###\n"); - - if (IOTX_CMP_EVENT_CLOUD_CONNECTED == msg->event_id) { - if (config_ota->_ota_inited == 0) { - if (config_ota->_destructing == 1) return; - - HAL_GetFirmwareVesion(config_ota->_current_verison); - - log_info("Current firmware version: %s", config_ota->_current_verison); - - ret = IOT_CMP_OTA_Start(config_ota->_current_verison, NULL); - if (ret == SUCCESS_RETURN) { - config_ota->_ota_inited = 1; - } - - ret = IOT_CMP_OTA_Set_Callback(IOTX_CMP_OTA_TYPE_COTA, config_ota_handler, config_ota, NULL); - - log_debug("ret = IOT_CMP_OTA_Set_Callback() = %d\n", ret); - } - - log_info("event %d(%s)\n###\n", msg->event_id, "cloud connected"); - } -} -static void* config_ota_ctor(void* _self, va_list* params) -{ - config_ota_t* self = _self; - int ret = 0; - iotx_cmp_init_param_t init_param; - - - - self->_data_buf = NULL; - self->_data_buf_length = 0; - self->_ota_inited = 0; - self->_current_verison = config_ota_lite_malloc(FIRMWARE_VERSION_MAXLEN); - if (self->_current_verison == NULL) return NULL; - memset(self->_current_verison, 0x0, FIRMWARE_VERSION_MAXLEN); - - init_param.secret_type = IOTX_CMP_DEVICE_SECRET_DEVICE; - - init_param.event_func = config_ota_cmp_event_handler; - init_param.user_data = self; - init_param.domain_type = IOTX_CMP_CLOUD_DOMAIN_SH; - - ret = IOT_CMP_Init(&init_param, NULL); - - log_debug("ret = IOT_CMP_Init() = %d\n", ret); - - log_debug("service cota created@%p.", self); - - return self; -} -static void* config_ota_dtor(void* _self) -{ - config_ota_t* self = _self; - - self->_destructing = 1; - self->_data_buf = NULL; - self->_data_buf_length = 0; - if (self->_rsp_configId) config_ota_lite_free(self->_rsp_configId); - if (self->_rsp_getType) config_ota_lite_free(self->_rsp_getType); - if (self->_rsp_sign) config_ota_lite_free(self->_rsp_sign); - if (self->_rsp_signMethod) config_ota_lite_free(self->_rsp_signMethod); - if (self->_rsp_url) config_ota_lite_free(self->_rsp_url); - if (self->_current_verison) config_ota_lite_free(self->_current_verison); - - return self; -} -/**< get config from server;used after ota inited*/ -static int config_ota_get(void* _self,const char* configScope, const char* getType, const char* attributeKeys, void* option) -{ - config_ota_t* self = _self; - self = self; - return IOT_CMP_OTA_Get_Config(configScope,getType,attributeKeys,option); -} -static void config_ota_start(void* _self) -{ - config_ota_t* self = _self; - - self = self; - - HAL_Firmware_Persistence_Start(); -} - -static int config_ota_write(void* _self, void* data, int data_length) -{ - config_ota_t* self = _self; - int ret; - - assert(self->_data_buf_length >= data_length && data_length && self->_data_buf == data); - - self->_data_buf = data; - - ret = HAL_Firmware_Persistence_Write(self->_data_buf, data_length); - - return ret; -} - -static int config_ota_end(void* _self) -{ - config_ota_t* self = _self; - int ret; - - self = self; - - /* this function should not return... */ - ret = HAL_Firmware_Persistence_Stop(); - - log_emerg("OTA end"); - /* update config*/ - return ret; -} - -static int config_ota_perform_ota_service(void* _self, void* _data_buf, int _data_buf_length) -{ - config_ota_t* self = _self; - int ret = -1; - iotx_cmp_ota_t* iotx_cmp_ota; - - assert(_data_buf && _data_buf_length); - - self->_data_buf = _data_buf; - self->_data_buf_length = _data_buf_length; - - iotx_cmp_ota = config_ota_lite_calloc(1, sizeof(iotx_cmp_ota_t)); - - assert(iotx_cmp_ota); - if (iotx_cmp_ota == NULL) return -1; - - iotx_cmp_ota->buffer = self->_data_buf; - iotx_cmp_ota->buffer_length = self->_data_buf_length; - iotx_cmp_ota->ota_type = IOTX_CMP_OTA_TYPE_COTA; - - self->_total_len = 0; - - config_ota_start(self); - - while (1) { - /* reset buffer size every time after fetch */ - iotx_cmp_ota->buffer_length = self->_data_buf_length; - ret = IOT_CMP_OTA_Yield(iotx_cmp_ota); - - assert(iotx_cmp_ota->buffer && iotx_cmp_ota->buffer_length); - - if (ret == 0 && iotx_cmp_ota->buffer && iotx_cmp_ota->buffer_length) { - ret = config_ota_write(self, iotx_cmp_ota->buffer, iotx_cmp_ota->buffer_length); - if (ret == 0) { - self->_total_len += iotx_cmp_ota->buffer_length; - } - log_debug("\nservice cota write flash,\tret=%d,\tbuffer_length=%d,\ttotal len:%d\n", - ret, iotx_cmp_ota->buffer_length, self->_total_len); - if (ret) goto err_handler; - } - - if (ret || iotx_cmp_ota->result) { - log_debug("service cota fail, ret=%d,\tresult=%d", ret, iotx_cmp_ota->result); - goto err_handler; - } - - if (iotx_cmp_ota->is_more) continue; - - if(iotx_cmp_ota->is_more == 0 && iotx_cmp_ota->result == 0) { - ret = 0; - log_debug("\nservice cota complete\n"); - break; - } - } - -err_handler: - if (ret == 0 && iotx_cmp_ota->result == 0) { - ret = config_ota_end(self); - if (ret) { - log_err("service cota invoke end function error, ret=%d", ret); - } - } else { - ret = -1; - } - - if (iotx_cmp_ota) service_ota_lite_free(iotx_cmp_ota); - - return ret; -} - -static void config_ota_install_callback_function(void* _self, handle_service_cota_callback_fp_t linkkit_callback_fp) -{ - config_ota_t* self = _self; - - assert(linkkit_callback_fp); - - self->_linkkit_callback_fp = linkkit_callback_fp; -} - -void* config_ota_lite_calloc(size_t nmemb, size_t size) -{ -#ifdef CMP_SUPPORT_MEMORY_MAGIC - return LITE_calloc(nmemb, size, MEM_MAGIC, SERVICE_COTA_MODULE_NAME); -#else - return LITE_calloc(nmemb, size); -#endif -} - -void* config_ota_lite_malloc(size_t size) -{ -#ifdef CMP_SUPPORT_MEMORY_MAGIC - return LITE_malloc(size, MEM_MAGIC, SERVICE_COTA_MODULE_NAME); -#else - return LITE_malloc(size); -#endif -} - -void config_ota_lite_free_func(void* ptr) -{ - return LITE_free_internal(ptr); -} - -static const cota_t _service_cota_class = { - sizeof(config_ota_t), - "cota_cls", - config_ota_ctor, - config_ota_dtor, - config_ota_get, - config_ota_start, - config_ota_write, - config_ota_end, - config_ota_perform_ota_service, - config_ota_install_callback_function -}; -const void* get_config_ota_class() -{ - return &_service_cota_class; -} diff --git a/iotkit-embedded/src/cota/iot.mk b/iotkit-embedded/src/cota/iot.mk deleted file mode 100644 index 7fee90a..0000000 --- a/iotkit-embedded/src/cota/iot.mk +++ /dev/null @@ -1,2 +0,0 @@ -LIBA_TARGET := libiot_cota.a -HDR_REFS := src \ No newline at end of file diff --git a/iotkit-embedded/src/dev_bind/dev_bind_api.h b/iotkit-embedded/src/dev_bind/dev_bind_api.h new file mode 100644 index 0000000..98b76a0 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/dev_bind_api.h @@ -0,0 +1,43 @@ +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. + **/ +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. + **/ +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. + **/ +int awss_stop_report_reset(void); + +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/iotkit-embedded/src/dev_bind/dev_bind_wrapper.h b/iotkit-embedded/src/dev_bind/dev_bind_wrapper.h new file mode 100644 index 0000000..2e1f3e4 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_bind.c b/iotkit-embedded/src/dev_bind/impl/awss_bind.c new file mode 100644 index 0000000..3931bb8 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/awss_bind.c @@ -0,0 +1,110 @@ +/* + * 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 +int awss_start_bind(); + +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(); + HAL_MutexUnlock(awss_bind_mutex); + +#ifdef DEVICE_MODEL_ENABLED + if(awss_check_reset()) { + return awss_report_reset_to_cloud(); + } +#endif + awss_start_bind(); + return 0; +} + +int awss_start_bind() +{ + static int awss_bind_inited = 0; + + if (awss_bind_mutex == NULL) { + awss_bind_mutex = HAL_MutexCreate(); + if (awss_bind_mutex == NULL) + return -1; + } + + HAL_MutexLock(awss_bind_mutex); + if(awss_bind_inited == 1) { + HAL_MutexUnlock(awss_bind_mutex); + return 0; + } + awss_bind_inited = 1; + + awss_report_token(); + awss_cmp_local_init(AWSS_LC_INIT_BIND); +#ifndef DEV_BIND_DISABLE_NOTIFY + awss_dev_bind_notify_stop(); + awss_dev_bind_notify(); +#endif +#ifdef WIFI_PROVISION_ENABLED +#ifndef AWSS_DISABLE_REGISTRAR + awss_registrar_init(); +#endif + AWSS_DISP_STATIS(); + AWSS_REPORT_STATIS("dev_bind"); +#endif + AWSS_DB_DISP_STATIS(); + AWSS_DB_REPORT_STATIS("dev_bind"); + 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/iotkit-embedded/src/dev_bind/impl/awss_bind_statis.c b/iotkit-embedded/src/dev_bind/impl/awss_bind_statis.c new file mode 100644 index 0000000..a2533cb --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_bind_statis.h b/iotkit-embedded/src/dev_bind/impl/awss_bind_statis.h new file mode 100644 index 0000000..9fb5b7a --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_cmp.h b/iotkit-embedded/src/dev_bind/impl/awss_cmp.h new file mode 100644 index 0000000..0e467d4 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_cmp_coap.c b/iotkit-embedded/src/dev_bind/impl/awss_cmp_coap.c new file mode 100644 index 0000000..5be0625 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_cmp_mqtt.c b/iotkit-embedded/src/dev_bind/impl/awss_cmp_mqtt.c new file mode 100644 index 0000000..f4e57dd --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_event.c b/iotkit-embedded/src/dev_bind/impl/awss_event.c new file mode 100644 index 0000000..399b890 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_event.h b/iotkit-embedded/src/dev_bind/impl/awss_event.h new file mode 100644 index 0000000..f4eaef4 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_info.c b/iotkit-embedded/src/dev_bind/impl/awss_info.c new file mode 100644 index 0000000..f85f01f --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_info.h b/iotkit-embedded/src/dev_bind/impl/awss_info.h new file mode 100644 index 0000000..31c6db6 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_log.h b/iotkit-embedded/src/dev_bind/impl/awss_log.h new file mode 100644 index 0000000..425929b --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_notify.c b/iotkit-embedded/src/dev_bind/impl/awss_notify.c new file mode 100644 index 0000000..a1d1467 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/awss_notify.c @@ -0,0 +1,745 @@ +/* + * 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]; +} + +/** + * @brief alternate bcast addr + * + * @param bcast_addr[out] bcast addr output + * @param mask_level 0 ~ 4(255), 1 ~ 3(255), 2 ~ 2(255), 3 ~ 1(255), others ~ invalid, + */ +static int awss_get_broadcast_addr(platform_netaddr_t *bcast_addr) +{ + static uint8_t mask_level = 3; + char ip[20] = {0}; + uint8_t level = 0; + + if (bcast_addr == NULL) { + return -1; + } + + /* update mask_level */ + if (++mask_level >= 4) { + mask_level = 0; + } + + /* setup port */ + bcast_addr->port = AWSS_NOTIFY_PORT; + + /* setup ip */ + HAL_Wifi_Get_IP(ip, NULL); + + if (ip[0] != '\0' && mask_level != 0) { + uint8_t i = 0; + for (i=0; ihost[i] = ip[i]; + if (ip[i] == '.') { + if (++level == mask_level) { + break; + } + } + } + + if (mask_level == 1) { + if (i + strlen("255.255.255") < 16) { + memcpy(bcast_addr->host + strlen(bcast_addr->host), "255.255.255", strlen("255.255.255")); + return 0; + } + } + else if (mask_level == 2) { + if (i + strlen("255.255") < 16) { + memcpy(bcast_addr->host + strlen(bcast_addr->host), "255.255", strlen("255.255")); + return 0; + } + } + else if (mask_level == 3) { + if (i + strlen("255") < 16) { + memcpy(bcast_addr->host + strlen(bcast_addr->host), "255", strlen("255")); + return 0; + } + } + } + + memcpy(bcast_addr->host, AWSS_NOTIFY_HOST, strlen(AWSS_NOTIFY_HOST)); + return 0; +} + + +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)); + awss_get_broadcast_addr(¬ify_sa); + awss_info("bcast ip = %s\n", notify_sa.host); + + 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 + 1]; + 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)); + + if(id_len > MSG_REQ_ID_LEN) { + goto GET_DEV_INFO_ERR; + } + 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(awss_check_reset()) { + 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/iotkit-embedded/src/dev_bind/impl/awss_notify.h b/iotkit-embedded/src/dev_bind/impl/awss_notify.h new file mode 100644 index 0000000..4b5691a --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_packet.c b/iotkit-embedded/src/dev_bind/impl/awss_packet.c new file mode 100644 index 0000000..11a859e --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_packet.h b/iotkit-embedded/src/dev_bind/impl/awss_packet.h new file mode 100644 index 0000000..45595a9 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_report.c b/iotkit-embedded/src/dev_bind/impl/awss_report.c new file mode 100644 index 0000000..22e1e67 --- /dev/null +++ b/iotkit-embedded/src/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; + + produce_random(aes_random, sizeof(aes_random)); + 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"); + + 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/iotkit-embedded/src/dev_bind/impl/awss_reset.h b/iotkit-embedded/src/dev_bind/impl/awss_reset.h new file mode 100644 index 0000000..c05bbbb --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset.c b/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset.c new file mode 100644 index 0000000..b7b7d05 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset.c @@ -0,0 +1,186 @@ +/* + * 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" + +#ifdef DEV_BIND_ENABLED +extern int awss_start_bind(); +#endif + +static uint8_t awss_report_reset_suc = 0; +static uint16_t awss_report_reset_id = 0; +static void *report_reset_timer = NULL; + +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 + +#ifdef DEV_BIND_ENABLED + awss_start_bind(); +#endif +} + +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(NULL, topic, IOTX_MQTT_QOS0, + (iotx_mqtt_event_handle_func_fpt)awss_report_reset_reply, NULL); + 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 = 0x01; + + awss_report_reset_suc = 0; + + HAL_Kv_Set(AWSS_KV_RST, &rst, sizeof(rst), 0); + + return awss_report_reset_to_cloud(); +} + +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; + } + log_info("[RST]", "need report rst\r\n"); + awss_report_reset_suc = 0; + + return 1; +} + +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/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset.h b/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset.h new file mode 100644 index 0000000..c2b77e0 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __AWSS_DEV_RESET_H__ +#define __AWSS_DEV_RESET_H__ + +#include + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" { +#endif + +int awss_report_reset_to_cloud(); +int awss_report_reset(); +int awss_check_reset(); +int awss_stop_report_reset(); +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif +#endif diff --git a/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset_internal.h b/iotkit-embedded/src/dev_bind/impl/awss_reset/awss_dev_reset_internal.h new file mode 100644 index 0000000..5489edf --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_timer.c b/iotkit-embedded/src/dev_bind/impl/awss_timer.c new file mode 100644 index 0000000..86cb4a2 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_timer.h b/iotkit-embedded/src/dev_bind/impl/awss_timer.h new file mode 100644 index 0000000..f00dc82 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/awss_utils.h b/iotkit-embedded/src/dev_bind/impl/awss_utils.h new file mode 100644 index 0000000..b41303d --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/dev_bind_internal.h b/iotkit-embedded/src/dev_bind/impl/dev_bind_internal.h new file mode 100644 index 0000000..d20f150 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/dev_bind_internal.h @@ -0,0 +1,26 @@ +#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 "infra_compat.h" +#include "awss_packet.h" +#include "awss_notify.h" +#include "awss_cmp.h" +#include "awss_cmp.h" +#include "infra_json_parser.h" +#include "mqtt_api.h" +#include "awss_dev_reset.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/iotkit-embedded/src/dev_bind/impl/iot_import_awss.h b/iotkit-embedded/src/dev_bind/impl/iot_import_awss.h new file mode 100644 index 0000000..4107ce6 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/iot_import_awss.h @@ -0,0 +1,110 @@ +/* + * 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 _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/iotkit-embedded/src/dev_bind/impl/os/os.h b/iotkit-embedded/src/dev_bind/impl/os/os.h new file mode 100644 index 0000000..5fe9a49 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_bind/impl/os/os_misc.c b/iotkit-embedded/src/dev_bind/impl/os/os_misc.c new file mode 100644 index 0000000..5a7ef36 --- /dev/null +++ b/iotkit-embedded/src/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(*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/iotkit-embedded/src/dev_bind/impl/passwd.c b/iotkit-embedded/src/dev_bind/impl/passwd.c new file mode 100644 index 0000000..b58ed6b --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/passwd.c @@ -0,0 +1,126 @@ +/* + * 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}; +#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/iotkit-embedded/src/dev_bind/impl/passwd.h b/iotkit-embedded/src/dev_bind/impl/passwd.h new file mode 100644 index 0000000..665da65 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/impl/passwd.h @@ -0,0 +1,34 @@ +/* + * 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]; + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif + +#endif diff --git a/iotkit-embedded/src/dev_bind/iot.mk b/iotkit-embedded/src/dev_bind/iot.mk new file mode 100644 index 0000000..3071a84 --- /dev/null +++ b/iotkit-embedded/src/dev_bind/iot.mk @@ -0,0 +1,6 @@ +LIBA_TARGET := libiot_dev_bind.a +LIB_SRCS_PATTERN := *.c + +$(call Append_Conditional, LIB_SRCS_PATTERN, impl/*.c, DEV_BIND_ENABLED) +$(call Append_Conditional, LIB_SRCS_PATTERN, impl/os/*.c, DEV_BIND_ENABLED) +$(call Append_Conditional, LIB_SRCS_PATTERN, impl/awss_reset/*.c, DEV_BIND_ENABLED) diff --git a/iotkit-embedded/src/dev_model/alcs/README.md b/iotkit-embedded/src/dev_model/alcs/README.md new file mode 100644 index 0000000..b9583a6 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/README.md @@ -0,0 +1,49 @@ +# README.md: alcs + +## Contents + +```shell +. +├── alcs_adapter.c +├── alcs_adapter.h +├── alcs_api.c +├── alcs_api.h +├── alcs_api_internal.h +├── alcs_client.c +├── alcs_coap.c +├── alcs_coap.h +├── alcs_localsetup.c +├── alcs_localsetup.h +├── alcs_mqtt.c +├── alcs_mqtt.h +├── alcs_server.c +├── aos.mk +├── CMakeLists.txt +├── Config.in +├── iot.mk +├── iotx_alcs_config.h +├── iotx_alcs.h +└── README.md + +``` + +## Introduction +Implementation of ICA local communication service. + + +### Features + + + +### Dependencies + +- **hal**. osal and hal to shield different os and hardware +- **infra**. Authentication, net and so on tool set. +- **coap local**. for local communication +- **mqtt**. get token form cloud over mqtt +## API +none +## Reference +none + + diff --git a/iotkit-embedded/src/dev_model/alcs/alcs_adapter.c b/iotkit-embedded/src/dev_model/alcs/alcs_adapter.c new file mode 100644 index 0000000..f589550 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_adapter.h b/iotkit-embedded/src/dev_model/alcs/alcs_adapter.h new file mode 100644 index 0000000..dabfca5 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_api.c b/iotkit-embedded/src/dev_model/alcs/alcs_api.c new file mode 100644 index 0000000..f15e378 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/alcs_api.c @@ -0,0 +1,725 @@ +/* + * 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" + +LIST_HEAD(secure_resource_cb_head); + +static bool is_inited = 0; +#ifdef SUPPORT_MULTI_DEVICES +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 + if (is_inited == 0) { + return; + } + is_inited = 0; + + 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); + node->lst_auth.list_mutex = NULL; + } + } +#else + if (_device.lst_auth.list_mutex) { + HAL_MutexDestroy(_device.lst_auth.list_mutex); + _device.lst_auth.list_mutex = NULL; + + } +#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; + } +} \ No newline at end of file diff --git a/iotkit-embedded/src/dev_model/alcs/alcs_api.h b/iotkit-embedded/src/dev_model/alcs/alcs_api.h new file mode 100644 index 0000000..cdeb96e --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_api_internal.h b/iotkit-embedded/src/dev_model/alcs/alcs_api_internal.h new file mode 100644 index 0000000..31adbab --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/utils/digest/utils_base64.c b/iotkit-embedded/src/dev_model/alcs/alcs_base64.c similarity index 71% rename from iotkit-embedded/src/utils/digest/utils_base64.c rename to iotkit-embedded/src/dev_model/alcs/alcs_base64.c index 64c216e..3f4a3d2 100644 --- a/iotkit-embedded/src/utils/digest/utils_base64.c +++ b/iotkit-embedded/src/dev_model/alcs/alcs_base64.c @@ -1,31 +1,13 @@ + /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ - - #include #include - -#include "iot_import.h" -#include "iot_export.h" - -#include "lite-log.h" -#include "utils_base64.h" +#include "infra_types.h" +#include "infra_defs.h" +#include "alcs_base64.h" static int8_t g_encodingTable[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', @@ -57,21 +39,19 @@ static void build_decoding_table() return; } -iotx_err_t utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax, - uint8_t *encodedData, uint32_t *outputLength) +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) { - log_err("pointer of encodedData is NULL!"); return FAIL_RETURN; } *outputLength = 4 * ((inputLength + 2) / 3); if (outputLenMax < *outputLength) { - log_err("the length of output memory is not enough!"); return FAIL_RETURN; } @@ -95,16 +75,20 @@ iotx_err_t utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_ return SUCCESS_RETURN; } -iotx_err_t utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax, - uint8_t *decodedData, uint32_t *outputLength) +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) { - log_err("the input length is error!"); return FAIL_RETURN; } @@ -120,16 +104,9 @@ iotx_err_t utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_ } if (outputLenMax < *outputLength) { - log_err("the length of output memory is not enough!"); return FAIL_RETURN; } - uint32_t sextet_a = 0; - uint32_t sextet_b = 0; - uint32_t sextet_c = 0; - uint32_t sextet_d = 0; - uint32_t triple = 0; - 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++]]; @@ -152,5 +129,4 @@ iotx_err_t utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_ } return SUCCESS_RETURN; -} - +} \ No newline at end of file diff --git a/iotkit-embedded/src/dev_model/alcs/alcs_base64.h b/iotkit-embedded/src/dev_model/alcs/alcs_base64.h new file mode 100644 index 0000000..6912a09 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_client.c b/iotkit-embedded/src/dev_model/alcs/alcs_client.c new file mode 100644 index 0000000..54313bd --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_coap.c b/iotkit-embedded/src/dev_model/alcs/alcs_coap.c new file mode 100644 index 0000000..8cf3fe9 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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; + +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 +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/iotkit-embedded/src/dev_model/alcs/alcs_coap.h b/iotkit-embedded/src/dev_model/alcs/alcs_coap.h new file mode 100644 index 0000000..398d9df --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_internal.h b/iotkit-embedded/src/dev_model/alcs/alcs_internal.h new file mode 100644 index 0000000..de02f28 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_localsetup.c b/iotkit-embedded/src/dev_model/alcs/alcs_localsetup.c new file mode 100644 index 0000000..53a66c7 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_localsetup.h b/iotkit-embedded/src/dev_model/alcs/alcs_localsetup.h new file mode 100644 index 0000000..e3d4171 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_mqtt.c b/iotkit-embedded/src/dev_model/alcs/alcs_mqtt.c new file mode 100644 index 0000000..ac09949 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_mqtt.h b/iotkit-embedded/src/dev_model/alcs/alcs_mqtt.h new file mode 100644 index 0000000..0590253 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/alcs_server.c b/iotkit-embedded/src/dev_model/alcs/alcs_server.c new file mode 100644 index 0000000..068ca2a --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/alcs_server.c @@ -0,0 +1,703 @@ +/* + * 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; + } + memset(item, 0, sizeof(svr_key_item)); + 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; + } + memset(item->keyInfo.secret, 0, strlen(secret) + 1); + 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 (CoAPResource_topicFilterMatch(node->filter_path, path) == 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 (strncmp(node->filter_path, path, strlen(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/iotkit-embedded/src/dev_model/alcs/iotx_alcs.h b/iotkit-embedded/src/dev_model/alcs/iotx_alcs.h new file mode 100644 index 0000000..040a4aa --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/alcs/iotx_alcs_config.h b/iotkit-embedded/src/dev_model/alcs/iotx_alcs_config.h new file mode 100644 index 0000000..5294ac2 --- /dev/null +++ b/iotkit-embedded/src/dev_model/alcs/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/iotkit-embedded/src/dev_model/client/dm_client.c b/iotkit-embedded/src/dev_model/client/dm_client.c new file mode 100644 index 0000000..e0ce83b --- /dev/null +++ b/iotkit-embedded/src/dev_model/client/dm_client.c @@ -0,0 +1,741 @@ +#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) +{ +#ifdef DEV_BIND_ENABLED + static int awss_reported = 0; + if(awss_reported == 0) { + awss_reported = 1; + awss_report_cloud(); + } +#endif + dm_log_info("IOTX_CM_EVENT_CLOUD_CONNECTED"); + 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/iotkit-embedded/src/dev_model/client/dm_client.h b/iotkit-embedded/src/dev_model/client/dm_client.h new file mode 100644 index 0000000..08e138c --- /dev/null +++ b/iotkit-embedded/src/dev_model/client/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/iotkit-embedded/src/dev_model/client/dm_client_adapter.c b/iotkit-embedded/src/dev_model/client/dm_client_adapter.c new file mode 100644 index 0000000..b42197f --- /dev/null +++ b/iotkit-embedded/src/dev_model/client/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/iotkit-embedded/src/dev_model/client/dm_client_adapter.h b/iotkit-embedded/src/dev_model/client/dm_client_adapter.h new file mode 100644 index 0000000..bf82c90 --- /dev/null +++ b/iotkit-embedded/src/dev_model/client/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/iotkit-embedded/src/dev_model/deprecated/impl_gateway.c b/iotkit-embedded/src/dev_model/deprecated/impl_gateway.c new file mode 100644 index 0000000..8f38be4 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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/iotkit-embedded/src/dev_model/deprecated/impl_gateway.h b/iotkit-embedded/src/dev_model/deprecated/impl_gateway.h new file mode 100644 index 0000000..c742223 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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/iotkit-embedded/src/dev_model/deprecated/impl_ntp.c b/iotkit-embedded/src/dev_model/deprecated/impl_ntp.c new file mode 100644 index 0000000..ffb9f94 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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/iotkit-embedded/src/dev_model/deprecated/impl_ntp.h b/iotkit-embedded/src/dev_model/deprecated/impl_ntp.h new file mode 100644 index 0000000..d5f20d0 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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/iotkit-embedded/src/dev_model/deprecated/impl_solo.c b/iotkit-embedded/src/dev_model/deprecated/impl_solo.c new file mode 100644 index 0000000..7cb2a9a --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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/iotkit-embedded/src/dev_model/deprecated/impl_solo.h b/iotkit-embedded/src/dev_model/deprecated/impl_solo.h new file mode 100644 index 0000000..7bebcfd --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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/iotkit-embedded/src/dev_model/deprecated/iot_export_linkkit.h b/iotkit-embedded/src/dev_model/deprecated/iot_export_linkkit.h new file mode 100644 index 0000000..9109681 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len); + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/iotkit-embedded/src/dev_model/deprecated/linkkit_export.h b/iotkit-embedded/src/dev_model/deprecated/linkkit_export.h new file mode 100644 index 0000000..9696176 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/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* + */ +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 + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ + +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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/iotkit-embedded/src/dev_model/deprecated/linkkit_gateway_export.h b/iotkit-embedded/src/dev_model/deprecated/linkkit_gateway_export.h new file mode 100644 index 0000000..f957510 --- /dev/null +++ b/iotkit-embedded/src/dev_model/deprecated/linkkit_gateway_export.h @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef LINKKIT_GATEWAY_EXPORT_H +#define LINKKIT_GATEWAY_EXPORT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#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. + */ +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. + */ +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. + */ +int linkkit_gateway_init(linkkit_params_t *initParams); + +/** + * @brief linkkit deinitialization. + * + * @return 0 when success, < 0 when fail. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +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. + */ +int linkkit_gateway_get_num_devices(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LINKKIT_GATEWAY_EXPORT_H */ diff --git a/iotkit-embedded/src/dev_model/dev_model_api.h b/iotkit-embedded/src/dev_model/dev_model_api.h new file mode 100644 index 0000000..75ffd98 --- /dev/null +++ b/iotkit-embedded/src/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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +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. + * + */ +int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len); + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/iotkit-embedded/src/dev_model/dm_api.c b/iotkit-embedded/src/dev_model/dm_api.c new file mode 100644 index 0000000..d3653e0 --- /dev/null +++ b/iotkit-embedded/src/dev_model/dm_api.c @@ -0,0 +1,2093 @@ +/* + * 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_query(_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 (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; + } + + _dm_api_lock(); + res = dm_mgr_device_query(product_key, device_name, devid); + if (res != SUCCESS_RETURN) { + _dm_api_unlock(); + return FAIL_RETURN; + } + _dm_api_unlock(); + return SUCCESS_RETURN; +} + +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/iotkit-embedded/src/dev_model/dm_cota.c b/iotkit-embedded/src/dev_model/dm_cota.c new file mode 100644 index 0000000..ed8aeee --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_cota.h b/iotkit-embedded/src/dev_model/dm_cota.h new file mode 100644 index 0000000..c5f54d0 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_fota.c b/iotkit-embedded/src/dev_model/dm_fota.c new file mode 100644 index 0000000..0ca4cbc --- /dev/null +++ b/iotkit-embedded/src/dev_model/dm_fota.c @@ -0,0 +1,218 @@ +/* + * 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; + + 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; + } + + /* 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"); + HAL_Firmware_Persistence_Stop(); + ctx->is_report_new_config = 0; + return FAIL_RETURN; + } + + /* 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_FIRMWARE, &file_isvalid, 4); + if (file_isvalid == 0) { + HAL_Firmware_Persistence_Stop(); + IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_CHECK_FALIED, NULL); + 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/iotkit-embedded/src/dev_model/dm_fota.h b/iotkit-embedded/src/dev_model/dm_fota.h new file mode 100644 index 0000000..d75157a --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_intf.h b/iotkit-embedded/src/dev_model/dm_intf.h new file mode 100644 index 0000000..1d26f06 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_ipc.c b/iotkit-embedded/src/dev_model/dm_ipc.c new file mode 100644 index 0000000..44a5126 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_ipc.h b/iotkit-embedded/src/dev_model/dm_ipc.h new file mode 100644 index 0000000..36ebe1b --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_log_report.c b/iotkit-embedded/src/dev_model/dm_log_report.c new file mode 100644 index 0000000..4bc8ba4 --- /dev/null +++ b/iotkit-embedded/src/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 (unsigned int)-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/iotkit-embedded/src/dev_model/dm_manager.c b/iotkit-embedded/src/dev_model/dm_manager.c new file mode 100644 index 0000000..b19030f --- /dev/null +++ b/iotkit-embedded/src/dev_model/dm_manager.c @@ -0,0 +1,2280 @@ +/* + * 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_query(_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_ctx *ctx = _dm_mgr_get_ctx(); + dm_mgr_dev_node_t *node = NULL; + + /* duplicated parameters check is removed */ + + res = _dm_mgr_search_dev_by_pkdn(product_key, device_name, &node); + if (res == SUCCESS_RETURN) { + if (devid) { + *devid = node->devid; + } + return SUCCESS_RETURN; + } + + return FAIL_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, payload_len, dm_client_thing_model_up_raw_reply); +#ifdef ALCS_ENABLED + res1 = dm_server_send(uri, (unsigned char *)payload, payload_len, 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/iotkit-embedded/src/dev_model/dm_manager.h b/iotkit-embedded/src/dev_model/dm_manager.h new file mode 100644 index 0000000..fc14549 --- /dev/null +++ b/iotkit-embedded/src/dev_model/dm_manager.h @@ -0,0 +1,137 @@ +/* + * 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_query(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ int *devid); +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/iotkit-embedded/src/dev_model/dm_message.c b/iotkit-embedded/src/dev_model/dm_message.c new file mode 100644 index 0000000..0582fd6 --- /dev/null +++ b/iotkit-embedded/src/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 + 21] = {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 + 21, "%s.%s|_v=sdk-c-"IOTX_SDK_VERSION"|", 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/iotkit-embedded/src/dev_model/dm_message.h b/iotkit-embedded/src/dev_model/dm_message.h new file mode 100644 index 0000000..a917440 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_message_cache.c b/iotkit-embedded/src/dev_model/dm_message_cache.c new file mode 100644 index 0000000..7c59913 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_message_cache.h b/iotkit-embedded/src/dev_model/dm_message_cache.h new file mode 100644 index 0000000..d489201 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_msg_process.c b/iotkit-embedded/src/dev_model/dm_msg_process.c new file mode 100644 index 0000000..f0ed9ce --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_msg_process.h b/iotkit-embedded/src/dev_model/dm_msg_process.h new file mode 100644 index 0000000..911949b --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_opt.c b/iotkit-embedded/src/dev_model/dm_opt.c new file mode 100644 index 0000000..75ffa8f --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_opt.h b/iotkit-embedded/src/dev_model/dm_opt.h new file mode 100644 index 0000000..552d846 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_ota.c b/iotkit-embedded/src/dev_model/dm_ota.c new file mode 100644 index 0000000..6a974da --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_ota.h b/iotkit-embedded/src/dev_model/dm_ota.h new file mode 100644 index 0000000..8d25e46 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_shadow.c b/iotkit-embedded/src/dev_model/dm_shadow.c new file mode 100644 index 0000000..0bffa7f --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_shadow.h b/iotkit-embedded/src/dev_model/dm_shadow.h new file mode 100644 index 0000000..3320a8f --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_tsl_alink.c b/iotkit-embedded/src/dev_model/dm_tsl_alink.c new file mode 100644 index 0000000..cf306b8 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_tsl_alink.h b/iotkit-embedded/src/dev_model/dm_tsl_alink.h new file mode 100644 index 0000000..f73adfa --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_utils.c b/iotkit-embedded/src/dev_model/dm_utils.c new file mode 100644 index 0000000..fb1f4ae --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_utils.h b/iotkit-embedded/src/dev_model/dm_utils.h new file mode 100644 index 0000000..e84b9ac --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/dm_wrapper.h b/iotkit-embedded/src/dev_model/dm_wrapper.h new file mode 100644 index 0000000..6a3f0c2 --- /dev/null +++ b/iotkit-embedded/src/dev_model/dm_wrapper.h @@ -0,0 +1,82 @@ +#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]); + +int HAL_SetDeviceName(char *device_name); +int HAL_SetDeviceSecret(char *device_secret); +int HAL_SetProductKey(char *product_key); +int HAL_SetProductSecret(char *product_secret); + +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); +#endif + +#ifdef DEPRECATED_LINKKIT +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/iotkit-embedded/src/dm/src/cJSON.c b/iotkit-embedded/src/dev_model/examples/cJSON.c similarity index 56% rename from iotkit-embedded/src/dm/src/cJSON.c rename to iotkit-embedded/src/dev_model/examples/cJSON.c index cd2ac6f..47fb5c3 100644 --- a/iotkit-embedded/src/dm/src/cJSON.c +++ b/iotkit-embedded/src/dev_model/examples/cJSON.c @@ -1,57 +1,39 @@ /* - 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. +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. */ -/* disable warnings about old C89 functions in MSVC */ -#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) - #define _CRT_SECURE_NO_DEPRECATE -#endif - #ifdef __GNUC__ #pragma GCC visibility push(default) #endif -#if defined(_MSC_VER) - #pragma warning (push) - /* disable warning about single line comments in system headers */ - #pragma warning (disable : 4001) -#endif #include #include +#include #include #include #include #include #include +#include -#ifdef ENABLE_LOCALES - #include -#endif - -#if defined(_MSC_VER) - #pragma warning (pop) -#endif #ifdef __GNUC__ #pragma GCC visibility pop #endif @@ -63,142 +45,102 @@ #define false ((cJSON_bool)0) typedef struct { - const unsigned char* json; + const unsigned char *json; size_t position; } error; static error global_error = { NULL, 0 }; -CJSON_PUBLIC(const char*) cJSON_GetErrorPtr(void) +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { - return (const char*)(global_error.json + global_error.position); + 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 != 6) || (CJSON_VERSION_PATCH != 0) +#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) +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; } -#ifndef CJSON_STRING_ZEROCOPY + /* 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) +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) { - if ((string1 == NULL) || (string2 == NULL)) + if ((string1 == NULL) || (string2 == NULL)) { return 1; + } - if (string1 == string2) + if (string1 == string2) { return 0; + } for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { - if (*string1 == '\0') + if (*string1 == '\0') { return 0; + } } return tolower(*string1) - tolower(*string2); } -#endif + typedef struct internal_hooks { - void* (*allocate)(size_t size); - void (*deallocate)(void* pointer); - void* (*reallocate)(void* pointer, size_t size); + void *(*allocate)(uint32_t size); + void(*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); } internal_hooks; -#if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ -static void* internal_malloc(size_t size) -{ - return malloc(size); -} -static void internal_free(void* pointer) -{ - free(pointer); -} -static void* internal_realloc(void* pointer, size_t size) -{ - return realloc(pointer, size); -} -#else -#define internal_malloc malloc -#define internal_free free -#define internal_realloc realloc -#endif - -static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; +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) +static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) { size_t length = 0; - unsigned char* copy = NULL; + unsigned char *copy = NULL; - if (string == NULL) + if (string == NULL) { return NULL; + } - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) + length = strlen((const char *)string) + sizeof(""); + if (!(copy = (unsigned char *)hooks->allocate(length))) { return NULL; + } memcpy(copy, string, length); return copy; } -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (hooks == NULL) { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - global_hooks.allocate = hooks->malloc_fn; - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - global_hooks.deallocate = hooks->free_fn; - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - global_hooks.reallocate = realloc; -} - /* Internal constructor. */ -static cJSON* cJSON_New_Item(const internal_hooks* const hooks) +static cJSON *cJSON_New_Item(const internal_hooks *const hooks) { - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) + 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_PUBLIC(void) cJSON_Delete(cJSON *item) { - cJSON* next = NULL; + cJSON *next = NULL; while (item != NULL) { next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { cJSON_Delete(item->child); + } if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { -#ifndef CJSON_STRING_ZEROCOPY global_hooks.deallocate(item->valuestring); -#endif } if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { -#ifndef CJSON_STRING_ZEROCOPY global_hooks.deallocate(item->string); -#endif } global_hooks.deallocate(item); item = next; @@ -208,16 +150,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON* item) /* 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 + struct lconv *lconv = localeconv(); + return (unsigned char)lconv->decimal_point[0]; } typedef struct { - const unsigned char* content; + 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. */ @@ -226,6 +164,7 @@ typedef struct { /* 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)) @@ -233,51 +172,52 @@ typedef struct { #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) +static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { double number = 0; - unsigned char* after_end = NULL; + 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)) + 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 */ + * 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 '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; + case '.': + number_c_string[i] = decimal_point; + break; - default: - goto loop_end; + default: + goto loop_end; } } loop_end: number_c_string[i] = '\0'; - number = strtod((const char*)number_c_string, (char**)&after_end); + number = strtod((const char *)number_c_string, (char **)&after_end); if (number_c_string == after_end) { return false; /* parse_error */ } @@ -285,12 +225,13 @@ static cJSON_bool parse_number(cJSON* const item, parse_buffer* const input_buff item->valuedouble = number; /* use saturation in case of overflow */ - if (number >= INT_MAX) + if (number >= INT_MAX) { item->valueint = INT_MAX; - else if (number <= INT_MIN) + } else if (number <= INT_MIN) { item->valueint = INT_MIN; - else + } else { item->valueint = (int)number; + } item->type = cJSON_Number; @@ -299,20 +240,21 @@ static cJSON_bool parse_number(cJSON* const item, parse_buffer* const input_buff } /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON* object, double number) +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) { - if (number >= INT_MAX) + if (number >= INT_MAX) { object->valueint = INT_MAX; - else if (number <= INT_MIN) + } else if (number <= INT_MIN) { object->valueint = INT_MIN; - else + } else { object->valueint = (int)number; + } return object->valuedouble = number; } typedef struct { - unsigned char* buffer; + unsigned char *buffer; size_t length; size_t offset; size_t depth; /* current nesting depth (for formatted printing) */ @@ -322,13 +264,14 @@ typedef struct { } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer* const p, size_t needed) +static unsigned char *ensure(printbuffer *const p, size_t needed) { - unsigned char* newbuffer = NULL; + unsigned char *newbuffer = NULL; size_t newsize = 0; - if ((p == NULL) || (p->buffer == NULL)) + if ((p == NULL) || (p->buffer == NULL)) { return NULL; + } if ((p->length > 0) && (p->offset >= p->length)) { /* make sure that offset is valid */ @@ -341,35 +284,32 @@ static unsigned char* ensure(printbuffer* const p, size_t needed) } needed += p->offset + 1; - if (needed <= p->length) + if (needed <= p->length) { return p->buffer + p->offset; + } - if (p->noalloc) + 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) + if (needed <= INT_MAX) { newsize = INT_MAX; - else + } else { return NULL; - } else + } + } 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; - } + newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); } else { /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); + newbuffer = (unsigned char *)p->hooks.allocate(newsize); if (!newbuffer) { p->hooks.deallocate(p->buffer); p->length = 0; @@ -377,8 +317,9 @@ static unsigned char* ensure(printbuffer* const p, size_t needed) return NULL; } - if (newbuffer) + if (newbuffer) { memcpy(newbuffer, p->buffer, p->offset + 1); + } p->hooks.deallocate(p->buffer); } p->length = newsize; @@ -388,20 +329,21 @@ static unsigned char* ensure(printbuffer* const p, size_t needed) } /* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer* const buffer) +static void update_offset(printbuffer *const buffer) { - const unsigned char* buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) + 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); + 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) +static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) { - unsigned char* output_pointer = NULL; + unsigned char *output_pointer = NULL; double d = item->valuedouble; int length = 0; size_t i = 0; @@ -409,34 +351,37 @@ static cJSON_bool print_number(const cJSON* const item, printbuffer* const outpu unsigned char decimal_point = get_decimal_point(); double test; - if (output_buffer == NULL) + if (output_buffer == NULL) { return false; + } /* This checks for NaN and Infinity */ - if ((d * 0) != 0) - length = sprintf((char*)number_buffer, "null"); - else { + 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); + 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 ((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); + length = sprintf((char *)number_buffer, "%1.17g", d); } } /* sprintf failed or buffer overrun occured */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + 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) + if (output_pointer == NULL) { return false; + } /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ + * dependent decimal point with '.' */ for (i = 0; i < ((size_t)length); i++) { if (number_buffer[i] == decimal_point) { output_pointer[i] = '.'; @@ -451,23 +396,24 @@ static cJSON_bool print_number(const cJSON* const item, printbuffer* const outpu return true; } -#ifndef CJSON_STRING_ZEROCOPY + /* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char* const input) +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 */ + 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 */ @@ -479,12 +425,13 @@ static unsigned parse_hex4(const unsigned char* const input) } /* 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) +* 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; + const unsigned char *first_sequence = input_pointer; unsigned char utf8_length = 0; unsigned char utf8_position = 0; unsigned char sequence_length = 0; @@ -499,12 +446,13 @@ static unsigned char utf16_literal_to_utf8(const unsigned char* const input_poin first_code = parse_hex4(first_sequence + 2); /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + 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; + const unsigned char *second_sequence = first_sequence + 6; unsigned int second_code = 0; sequence_length = 12; /* \uXXXX\uXXXX */ @@ -535,8 +483,8 @@ static unsigned char utf16_literal_to_utf8(const unsigned char* const input_poin } /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (codepoint < 0x80) { /* normal ascii, encoding 0xxxxxxx */ utf8_length = 1; @@ -564,10 +512,11 @@ static unsigned char utf16_literal_to_utf8(const unsigned char* const input_poin codepoint >>= 6; } /* encode first byte */ - if (utf8_length > 1) + if (utf8_length > 1) { (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - else + } else { (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } *output_pointer += utf8_length; @@ -576,26 +525,23 @@ static unsigned char utf16_literal_to_utf8(const unsigned char* const input_poin fail: return 0; } -#endif + /* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON* const item, parse_buffer* const input_buffer) +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; -#ifndef CJSON_STRING_ZEROCOPY - unsigned char* output_pointer = NULL; -#endif - unsigned char* output = NULL; + 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] != '\"') + if (buffer_at_offset(input_buffer)[0] != '\"') { goto fail; + } { /* calculate approximate size of the output (overestimate) */ -#ifndef CJSON_STRING_ZEROCOPY size_t allocation_length = 0; -#endif size_t skipped_bytes = 0; while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { /* is escape sequence */ @@ -612,61 +558,61 @@ static cJSON_bool parse_string(cJSON* const item, parse_buffer* const input_buff if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { goto fail; /* string ended unexpectedly */ } -#ifndef CJSON_STRING_ZEROCOPY + /* 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("")); + output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); if (output == NULL) { goto fail; /* allocation failure */ } -#endif } -#ifndef CJSON_STRING_ZEROCOPY + output_pointer = output; /* loop through the string literal */ while (input_pointer < input_end) { - if (*input_pointer != '\\') + if (*input_pointer != '\\') { *output_pointer++ = *input_pointer++; + } /* escape sequence */ else { unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) + 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 */ + 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; - } - break; - - default: - goto fail; } input_pointer += sequence_length; } @@ -674,50 +620,48 @@ static cJSON_bool parse_string(cJSON* const item, parse_buffer* const input_buff /* zero terminate the output */ *output_pointer = '\0'; -#else - output = (unsigned char*)input_pointer; -#endif + item->type = cJSON_String; - item->valuestring = (char*)output; -#ifdef CJSON_STRING_ZEROCOPY - item->valuestring_length = input_end - output; -#else -#endif + item->valuestring = (char *)output; + input_buffer->offset = (size_t)(input_end - input_buffer->content); input_buffer->offset++; return true; fail: -#ifndef CJSON_STRING_ZEROCOPY - if (output != NULL) + if (output != NULL) { input_buffer->hooks.deallocate(output); -#endif - if (input_pointer != NULL) + } + + 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) +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; + 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) + if (output_buffer == NULL) { return false; + } /* empty string */ if (input == NULL) { output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) + if (output == NULL) { return false; - strcpy((char*)output, "\"\""); + } + strcpy((char *)output, "\"\""); return true; } @@ -725,29 +669,30 @@ static cJSON_bool print_string_ptr(const unsigned char* const input, printbuffer /* 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; + 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) + if (output == NULL) { return false; + } /* no characters have to be escaped */ if (escape_characters == 0) { @@ -770,32 +715,32 @@ static cJSON_bool print_string_ptr(const unsigned char* const input, printbuffer /* 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; + 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; } } } @@ -806,69 +751,63 @@ static cJSON_bool print_string_ptr(const unsigned char* const input, printbuffer } /* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON* const item, printbuffer* const p) +static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) { - return print_string_ptr((unsigned char*)item->valuestring, 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); +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) +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL)) + if ((buffer == NULL) || (buffer->content == NULL)) { return NULL; + } - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; + } - if (buffer->offset == buffer->length) + 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 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) +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; + cJSON *item = NULL; /* reset error position */ global_error.json = NULL; global_error.position = 0; - if (value == NULL) + if (value == NULL) { goto fail; + } - buffer.content = (const unsigned char*)value; - buffer.length = strlen((const char*)value) + sizeof(""); + 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 */ + if (item == NULL) { /* memory fail */ goto fail; + } - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { + if (!parse_value(item, buffer_skip_whitespace(&buffer))) { /* parse failure. ep is set. */ goto fail; } @@ -876,74 +815,83 @@ CJSON_PUBLIC(cJSON*) cJSON_ParseWithOpts(const char* value, const char** return_ /* 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') + 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); } - if (return_parse_end) - *return_parse_end = (const char*)buffer_at_offset(&buffer); return item; fail: - if (item != NULL) + if (item != NULL) { cJSON_Delete(item); + } if (value != NULL) { error local_error; - local_error.json = (const unsigned char*)value; + local_error.json = (const unsigned char *)value; local_error.position = 0; - if (buffer.offset < buffer.length) + if (buffer.offset < buffer.length) { local_error.position = buffer.offset; - else if (buffer.length > 0) + } 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; - - global_error = local_error; + 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) +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) +static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks) { printbuffer buffer[1]; - unsigned char* printed = NULL; + unsigned char *printed = NULL; memset(buffer, 0, sizeof(buffer)); /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(256); + buffer->buffer = (unsigned char *)hooks->allocate(256); buffer->format = format; buffer->hooks = *hooks; - if (buffer->buffer == NULL) + if (buffer->buffer == NULL) { goto fail; + } /* print the value */ - if (!print_value(item, buffer)) + 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); + printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->length); buffer->buffer = NULL; - if (printed == 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) + 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 */ @@ -954,36 +902,42 @@ static unsigned char* print(const cJSON* const item, cJSON_bool format, const in return printed; fail: - if (buffer->buffer != NULL) + if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); + } - if (printed != NULL) +#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) +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) { - return (char*)print(item, true, &global_hooks); + return (char *)print(item, true, &global_hooks); } -CJSON_PUBLIC(char*) cJSON_PrintUnformatted(const cJSON* item) +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) { - return (char*)print(item, false, &global_hooks); + return (char *)print(item, false, &global_hooks); } -CJSON_PUBLIC(char*) cJSON_PrintBuffered(const cJSON* item, int prebuffer, cJSON_bool fmt) +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) + if (prebuffer < 0) { return NULL; + } - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) + p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) { return NULL; + } p.length = (size_t)prebuffer; p.offset = 0; @@ -992,21 +946,21 @@ CJSON_PUBLIC(char*) cJSON_PrintBuffered(const cJSON* item, int prebuffer, cJSON_ p.hooks = global_hooks; if (!print_value(item, &p)) { - global_hooks.deallocate(p.buffer); return NULL; } - return (char*)p.buffer; + return (char *)p.buffer; } -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON* item, char* buf, const int len, const cJSON_bool fmt) +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) || (buf == NULL)) + if (len < 0) { return false; + } - p.buffer = (unsigned char*)buf; + p.buffer = (unsigned char *)buf; p.length = (size_t)len; p.offset = 0; p.noalloc = true; @@ -1017,7 +971,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON* item, char* buf, const i } /* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON* const item, parse_buffer* const input_buffer) +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 */ @@ -1025,109 +979,120 @@ static cJSON_bool parse_value(cJSON* const item, parse_buffer* const input_buffe /* parse the different types of values */ /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) { + 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)) { + 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)) { + 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] == '\"')) + 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')))) + 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] == '[')) + 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] == '{')) + 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) +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer) { - unsigned char* output = NULL; + unsigned char *output = NULL; - if ((item == NULL) || (output_buffer == 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_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_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_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_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; - } + 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; - } + 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_String: + return print_string(item, output_buffer); - case cJSON_Array: - return print_array(item, output_buffer); + case cJSON_Array: + return print_array(item, output_buffer); - case cJSON_Object: - return print_object(item, output_buffer); + case cJSON_Object: + return print_object(item, output_buffer); - default: - return false; + default: + return false; } } /* Build an array from input text. */ -static cJSON_bool parse_array(cJSON* const item, parse_buffer* const input_buffer) +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; + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ @@ -1157,7 +1122,7 @@ static cJSON_bool parse_array(cJSON* const item, parse_buffer* const input_buffe /* loop through the comma separated array elements */ do { /* allocate next item */ - cJSON* new_item = cJSON_New_Item(&(input_buffer->hooks)); + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { goto fail; /* allocation failure */ } @@ -1197,44 +1162,50 @@ static cJSON_bool parse_array(cJSON* const item, parse_buffer* const input_buffe return true; fail: - if (head != NULL) + 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) +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) { - unsigned char* output_pointer = NULL; + unsigned char *output_pointer = NULL; size_t length = 0; - cJSON* current_element = item->child; + cJSON *current_element = item->child; - if (output_buffer == NULL) + if (output_buffer == NULL) { return false; + } /* Compose the output array. */ /* opening square bracket */ output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) + 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)) + 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) + if (output_pointer == NULL) { return false; + } *output_pointer++ = ','; - if (output_buffer->format) + if (output_buffer->format) { *output_pointer++ = ' '; + } *output_pointer = '\0'; output_buffer->offset += length; } @@ -1242,8 +1213,9 @@ static cJSON_bool print_array(const cJSON* const item, printbuffer* const output } output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) + if (output_pointer == NULL) { return false; + } *output_pointer++ = ']'; *output_pointer = '\0'; output_buffer->depth--; @@ -1252,10 +1224,10 @@ static cJSON_bool print_array(const cJSON* const item, printbuffer* const output } /* Build an object from the text. */ -static cJSON_bool parse_object(cJSON* const item, parse_buffer* const input_buffer) +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer) { - cJSON* head = NULL; /* linked list head */ - cJSON* current_item = NULL; + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ @@ -1283,7 +1255,7 @@ static cJSON_bool parse_object(cJSON* const item, parse_buffer* const input_buff /* loop through the comma separated array elements */ do { /* allocate next item */ - cJSON* new_item = cJSON_New_Item(&(input_buffer->hooks)); + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { goto fail; /* allocation failure */ } @@ -1309,9 +1281,6 @@ static cJSON_bool parse_object(cJSON* const item, parse_buffer* const input_buff /* swap valuestring and string, because we parsed the name */ current_item->string = current_item->valuestring; -#ifdef CJSON_STRING_ZEROCOPY - current_item->string_length = current_item->valuestring_length; -#endif current_item->valuestring = NULL; if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { @@ -1341,74 +1310,87 @@ static cJSON_bool parse_object(cJSON* const item, parse_buffer* const input_buff return true; fail: - if (head != NULL) + 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) +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) { - unsigned char* output_pointer = NULL; + unsigned char *output_pointer = NULL; size_t length = 0; - cJSON* current_item = item->child; + cJSON *current_item = item->child; - if (output_buffer == NULL) + if (output_buffer == NULL) { return false; + } /* Compose the output: */ - length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ + length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) + if (output_pointer == NULL) { return false; + } *output_pointer++ = '{'; output_buffer->depth++; - if (output_buffer->format) + 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) + if (output_pointer == NULL) { return false; - for (i = 0; i < output_buffer->depth; i++) + } + 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)) + 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) + if (output_pointer == NULL) { return false; + } *output_pointer++ = ':'; - if (output_buffer->format) + if (output_buffer->format) { *output_pointer++ = '\t'; + } output_buffer->offset += length; /* print value */ - if (!print_value(current_item, output_buffer)) + 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) + if (output_pointer == NULL) { return false; - if (current_item->next) + } + if (current_item->next) { *output_pointer++ = ','; + } - if (output_buffer->format) + if (output_buffer->format) { *output_pointer++ = '\n'; + } *output_pointer = '\0'; output_buffer->offset += length; @@ -1416,12 +1398,14 @@ static cJSON_bool print_object(const cJSON* const item, printbuffer* const outpu } output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) + if (output_pointer == NULL) { return false; + } if (output_buffer->format) { size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) + for (i = 0; i < (output_buffer->depth - 1); i++) { *output_pointer++ = '\t'; + } } *output_pointer++ = '}'; *output_pointer = '\0'; @@ -1431,32 +1415,27 @@ static cJSON_bool print_object(const cJSON* const item, printbuffer* const outpu } /* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON* array) +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) { - cJSON* child = NULL; - size_t size = 0; - - if (array == NULL) - return 0; - - child = array->child; - - while (child != NULL) { - size++; - child = child->next; + 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)size; + return (int)i; } -static cJSON* get_array_item(const cJSON* array, size_t index) +static cJSON *get_array_item(const cJSON *array, size_t index) { - cJSON* current_child = NULL; + cJSON *current_child = NULL; - if (array == NULL) + if (array == NULL) { return NULL; + } current_child = array->child; while ((current_child != NULL) && (index > 0)) { @@ -1467,32 +1446,31 @@ static cJSON* get_array_item(const cJSON* array, size_t index) return current_child; } -CJSON_PUBLIC(cJSON*) cJSON_GetArrayItem(const cJSON* array, int index) +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) { - if (index < 0) + 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) +static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) { - cJSON* current_element = NULL; + cJSON *current_element = NULL; - if ((object == NULL) || (name == 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)) + while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) { current_element = current_element->next; + } } else { -#ifndef CJSON_STRING_ZEROCOPY - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) -#else - while ((current_element != NULL) && (strncmp((const char*)name, (const char*)(current_element->string), current_element->string_length) != 0)) -#endif - { + while ((current_element != NULL) + && (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) { current_element = current_element->next; } } @@ -1500,53 +1478,50 @@ static cJSON* get_object_item(const cJSON* const object, const char* const name, return current_element; } -CJSON_PUBLIC(cJSON*) cJSON_GetObjectItem(const cJSON* const object, const char* const string) +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) +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) +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) +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) +static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks) { - cJSON* reference = NULL; - if (item == NULL) - return NULL; - - reference = cJSON_New_Item(hooks); - if (reference == NULL) + cJSON *ref = cJSON_New_Item(hooks); + if (!ref) { return NULL; - - memcpy(reference, item, sizeof(cJSON)); - reference->string = NULL; - reference->type |= cJSON_IsReference; - reference->next = reference->prev = NULL; - return reference; + } + 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_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) { - cJSON* child = NULL; + cJSON *child = NULL; - if ((item == NULL) || (array == NULL)) + if ((item == NULL) || (array == NULL)) { return; + } child = array->child; @@ -1555,24 +1530,22 @@ CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON* array, cJSON* item) array->child = item; } else { /* append to the end */ - while (child->next) + while (child->next) { child = child->next; + } suffix_object(child, item); } } -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON* object, const char* string, cJSON* item) +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) { - if (item == NULL) - return; - /* call cJSON_AddItemToObjectCS for code reuse */ - cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item); + cJSON_AddItemToObjectCS(object, (char *)cJSON_strdup((const unsigned char *)string, &global_hooks), item); /* remove cJSON_StringIsConst flag */ item->type &= ~cJSON_StringIsConst; } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) #pragma GCC diagnostic push #endif #ifdef __GNUC__ @@ -1580,40 +1553,37 @@ CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON* object, const char* string, cJSO #endif /* Add an item to an object with constant string as key */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON* object, const char* string, cJSON* item) +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) { - if ((item == NULL) || (string == NULL)) + if (!item) { return; - if (!(item->type & cJSON_StringIsConst) && item->string) + } + if (!(item->type & cJSON_StringIsConst) && item->string) { global_hooks.deallocate(item->string); - item->string = (char*)string; + } + item->string = (char *)string; item->type |= cJSON_StringIsConst; cJSON_AddItemToArray(object, item); } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#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_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) { - if (array == NULL) - return; - cJSON_AddItemToArray(array, create_reference(item, &global_hooks)); } -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON* object, const char* string, cJSON* item) +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) { - if ((object == NULL) || (string == NULL)) - return; - cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks)); } -CJSON_PUBLIC(cJSON*) cJSON_DetachItemViaPointer(cJSON* parent, cJSON* const item) +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) { - if ((parent == NULL) || (item == NULL)) + if ((parent == NULL) || (item == NULL)) { return NULL; + } if (item->prev != NULL) { /* not the first element */ @@ -1635,50 +1605,52 @@ CJSON_PUBLIC(cJSON*) cJSON_DetachItemViaPointer(cJSON* parent, cJSON* const item return item; } -CJSON_PUBLIC(cJSON*) cJSON_DetachItemFromArray(cJSON* array, int which) +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) { - if (which < 0) + 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_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_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) { - cJSON* to_detach = cJSON_GetObjectItem(object, 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_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) { - cJSON* to_detach = cJSON_GetObjectItemCaseSensitive(object, 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_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_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_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) { - cJSON* after_inserted = NULL; + cJSON *after_inserted = NULL; - if (which < 0) + if (which < 0) { return; + } after_inserted = get_array_item(array, (size_t)which); if (after_inserted == NULL) { @@ -1689,29 +1661,35 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON* array, int which, cJSON* newit newitem->next = after_inserted; newitem->prev = after_inserted->prev; after_inserted->prev = newitem; - if (after_inserted == array->child) + if (after_inserted == array->child) { array->child = newitem; - else + } else { newitem->prev->next = newitem; + } } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON* const parent, cJSON* const item, cJSON* replacement) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + if ((parent == NULL) || (replacement == NULL)) { return false; + } - if (replacement == item) + if (replacement == item) { return true; + } replacement->next = item->next; replacement->prev = item->prev; - if (replacement->next != NULL) + if (replacement->next != NULL) { replacement->next->prev = replacement; - if (replacement->prev != NULL) + } + if (replacement->prev != NULL) { replacement->prev->next = replacement; - if (parent->child == item) + } + if (parent->child == item) { parent->child = replacement; + } item->next = NULL; item->prev = NULL; @@ -1720,102 +1698,125 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON* const parent, cJSON* return true; } -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON* array, int which, cJSON* newitem) +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { - if (which < 0) + cJSON *obj = NULL; + + if (which < 0) { return; + } - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); + 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) +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, + cJSON_bool case_sensitive) { - if ((replacement == NULL) || (string == NULL)) + cJSON *obj = NULL; + + if (replacement == NULL) { return false; + } /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { cJSON_free(replacement->string); - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + } + replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); replacement->type &= ~cJSON_StringIsConst; - cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); + 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) +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) +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_PUBLIC(cJSON *) cJSON_CreateNull(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if (item) + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { item->type = cJSON_NULL; + } return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateTrue(void) +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if (item) + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { item->type = cJSON_True; + } return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateFalse(void) +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if (item) + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { item->type = cJSON_False; + } return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateBool(cJSON_bool b) +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) { - cJSON* item = cJSON_New_Item(&global_hooks); - if (item) + 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_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { - cJSON* item = cJSON_New_Item(&global_hooks); + 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) + if (num >= INT_MAX) { item->valueint = INT_MAX; - else if (num <= INT_MIN) + } else if (num <= INT_MIN) { item->valueint = INT_MIN; - else + } else { item->valueint = (int)num; + } } return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateString(const char* string) +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) { - cJSON* item = cJSON_New_Item(&global_hooks); + cJSON *item = cJSON_New_Item(&global_hooks); if (item) { item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); if (!item->valuestring) { cJSON_Delete(item); return NULL; @@ -1825,12 +1826,12 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateString(const char* string) return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateRaw(const char* raw) +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) { - cJSON* item = cJSON_New_Item(&global_hooks); + cJSON *item = cJSON_New_Item(&global_hooks); if (item) { item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); if (!item->valuestring) { cJSON_Delete(item); return NULL; @@ -1840,34 +1841,37 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateRaw(const char* raw) return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateArray(void) +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if (item) + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { item->type = cJSON_Array; + } return item; } -CJSON_PUBLIC(cJSON*) cJSON_CreateObject(void) +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) { - cJSON* item = cJSON_New_Item(&global_hooks); - if (item) + 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) +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) { size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) + if (count < 0) { return NULL; + } a = cJSON_CreateArray(); for (i = 0; a && (i < (size_t)count); i++) { @@ -1876,25 +1880,27 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateIntArray(const int* numbers, int count) cJSON_Delete(a); return NULL; } - if (!i) + if (!i) { a->child = n; - else + } else { suffix_object(p, n); + } p = n; } return a; } -CJSON_PUBLIC(cJSON*) cJSON_CreateFloatArray(const float* numbers, int count) +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) { size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) + if (count < 0) { return NULL; + } a = cJSON_CreateArray(); @@ -1904,25 +1910,27 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateFloatArray(const float* numbers, int count) cJSON_Delete(a); return NULL; } - if (!i) + if (!i) { a->child = n; - else + } else { suffix_object(p, n); + } p = n; } return a; } -CJSON_PUBLIC(cJSON*) cJSON_CreateDoubleArray(const double* numbers, int count) +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) { size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) + if (count < 0) { return NULL; + } a = cJSON_CreateArray(); @@ -1932,25 +1940,27 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateDoubleArray(const double* numbers, int count) cJSON_Delete(a); return NULL; } - if (!i) + if (!i) { a->child = n; - else + } else { suffix_object(p, n); + } p = n; } return a; } -CJSON_PUBLIC(cJSON*) cJSON_CreateStringArray(const char** strings, int count) +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) { size_t i = 0; - cJSON* n = NULL; - cJSON* p = NULL; - cJSON* a = NULL; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; - if ((count < 0) || (strings == NULL)) + if (count < 0) { return NULL; + } a = cJSON_CreateArray(); @@ -1960,10 +1970,11 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateStringArray(const char** strings, int count) cJSON_Delete(a); return NULL; } - if (!i) + if (!i) { a->child = n; - else + } else { suffix_object(p, n); + } p = n; } @@ -1971,43 +1982,50 @@ CJSON_PUBLIC(cJSON*) cJSON_CreateStringArray(const char** strings, int count) } /* Duplication */ -CJSON_PUBLIC(cJSON*) cJSON_Duplicate(const cJSON* item, cJSON_bool recurse) +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) { - cJSON* newitem = NULL; - cJSON* child = NULL; - cJSON* next = NULL; - cJSON* newchild = NULL; + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; /* Bail on bad ptr */ - if (!item) + if (!item) { goto fail; + } /* Create new item */ newitem = cJSON_New_Item(&global_hooks); - if (!newitem) + 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) + 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) + 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) + 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) + if (!newchild) { goto fail; + } if (next != NULL) { /* If newitem->child already set, then crosswire ->prev and ->next and move on */ next->next = newchild; @@ -2024,44 +2042,44 @@ CJSON_PUBLIC(cJSON*) cJSON_Duplicate(const cJSON* item, cJSON_bool recurse) return newitem; fail: - if (newitem != NULL) + if (newitem != NULL) { cJSON_Delete(newitem); + } return NULL; } -CJSON_PUBLIC(void) cJSON_Minify(char* json) +CJSON_PUBLIC(void) cJSON_Minify(char *json) { - unsigned char* into = (unsigned char*)json; - - if (json == NULL) - return; - + unsigned char *into = (unsigned char *)json; while (*json) { - if (*json == ' ') + if (*json == ' ') { json++; - else if (*json == '\t') { + } else if (*json == '\t') { /* Whitespace characters. */ json++; - } else if (*json == '\r') + } else if (*json == '\r') { json++; - else if (*json == '\n') + } else if (*json == '\n') { json++; - else if ((*json == '/') && (json[1] == '/')) { + } else if ((*json == '/') && (json[1] == '/')) { /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) + while (*json && (*json != '\n')) { json++; + } } else if ((*json == '/') && (json[1] == '*')) { /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) + 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 == '\\') + if (*json == '\\') { *into++ = (unsigned char) * json++; + } *into++ = (unsigned char) * json++; } *into++ = (unsigned char) * json++; @@ -2075,189 +2093,191 @@ CJSON_PUBLIC(void) cJSON_Minify(char* json) *into = '\0'; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_Invalid; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_False; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xff) == cJSON_True; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & (cJSON_True | cJSON_False)) != 0; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_NULL; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_Number; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_String; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_Array; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) { - if (item == NULL) + if (item == NULL) { return false; + } return (item->type & 0xFF) == cJSON_Object; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON* const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) { - if (item == NULL) + 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) +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)) + 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; + 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) + 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) + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: return true; - return false; - case cJSON_String: - case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) + case cJSON_Number: + if (a->valuedouble == b->valuedouble) { + return true; + } 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)) + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) { + return true; + } - a_element = a_element->next; - b_element = b_element->next; - } - - /* one of the arrays is longer than the other */ - if (a_element != b_element) return false; - return true; - } + case cJSON_Array: { + cJSON *a_element = a->child; + cJSON *b_element = b->child; - case cJSON_Object: { - cJSON* a_element = NULL; - cJSON* b_element = NULL; - cJSON_ArrayForEach(a_element, a) { - /* TODO This has O(n^2) runtime, which is horrible! */ - b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - return false; + for (; (a_element != NULL) && (b_element != NULL);) { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { + return false; + } - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - return false; + a_element = a_element->next; + b_element = b_element->next; + } + + return true; } - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - return false; + 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(b_element, a_element, case_sensitive)) - return false; - } + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { + return false; + } + } - return true; - } + return true; + } - default: - return false; + default: + return false; } } -CJSON_PUBLIC(void*) cJSON_malloc(size_t size) +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) { return global_hooks.allocate(size); } -CJSON_PUBLIC(void) cJSON_free(void* object) +CJSON_PUBLIC(void) cJSON_free(void *object) { global_hooks.deallocate(object); } diff --git a/iotkit-embedded/src/dev_model/examples/cJSON.h b/iotkit-embedded/src/dev_model/examples/cJSON.h new file mode 100644 index 0000000..2e3715a --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/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/iotkit-embedded/src/dev_model/examples/data/cntdown_tsl.data b/iotkit-embedded/src/dev_model/examples/data/cntdown_tsl.data new file mode 100644 index 0000000..b963e47 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/data/cntdown_tsl.data @@ -0,0 +1,6 @@ +/* + * please modify this string follow as product's TSL. + */ + +static const char TSL_STRING[] = + "{\"schema\":\"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json\",\"profile\":{\"productKey\":\"a1ikrQdGiG8\"},\"services\":[{\"outputData\":[],\"identifier\":\"set\",\"inputData\":[{\"identifier\":\"WIFI_Band\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"电源开关\"},{\"identifier\":\"CountDown\",\"dataType\":{\"specs\":[{\"identifier\":\"IsRunning\",\"dataType\":{\"specs\":{\"0\":\"已停止\",\"1\":\"执行中\"},\"type\":\"bool\"},\"name\":\"运行状态\"},{\"identifier\":\"TimeLeft\",\"dataType\":{\"specs\":{\"unit\":\"s\",\"min\":\"0\",\"unitName\":\"秒\",\"max\":\"86399\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"剩余时间\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"打开\"},\"type\":\"bool\"},\"name\":\"开关动作\"},{\"identifier\":\"Timestamp\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间戳\"}],\"type\":\"struct\"},\"name\":\"本地倒计时\"}],\"method\":\"thing.service.property.set\",\"name\":\"set\",\"required\":true,\"callType\":\"async\",\"desc\":\"属性设置\"},{\"outputData\":[{\"identifier\":\"WIFI_Band\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"电源开关\"},{\"identifier\":\"CountDown\",\"dataType\":{\"specs\":[{\"identifier\":\"IsRunning\",\"dataType\":{\"specs\":{\"0\":\"已停止\",\"1\":\"执行中\"},\"type\":\"bool\"},\"name\":\"运行状态\"},{\"identifier\":\"TimeLeft\",\"dataType\":{\"specs\":{\"unit\":\"s\",\"min\":\"0\",\"unitName\":\"秒\",\"max\":\"86399\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"剩余时间\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"打开\"},\"type\":\"bool\"},\"name\":\"开关动作\"},{\"identifier\":\"Timestamp\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间戳\"}],\"type\":\"struct\"},\"name\":\"本地倒计时\"}],\"identifier\":\"get\",\"inputData\":[\"WIFI_Band\",\"WiFI_RSSI\",\"WIFI_AP_BSSID\",\"WIFI_Channel\",\"WiFI_SNR\",\"PowerSwitch\",\"CountDown\"],\"method\":\"thing.service.property.get\",\"name\":\"get\",\"required\":true,\"callType\":\"async\",\"desc\":\"属性获取\"}],\"properties\":[{\"identifier\":\"WIFI_Band\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"频段\",\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信号强度\",\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\",\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信道\",\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信噪比\",\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"电源开关\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"CountDown\",\"dataType\":{\"specs\":[{\"identifier\":\"IsRunning\",\"dataType\":{\"specs\":{\"0\":\"已停止\",\"1\":\"执行中\"},\"type\":\"bool\"},\"name\":\"运行状态\"},{\"identifier\":\"TimeLeft\",\"dataType\":{\"specs\":{\"unit\":\"s\",\"min\":\"0\",\"unitName\":\"秒\",\"max\":\"86399\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"剩余时间\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"打开\"},\"type\":\"bool\"},\"name\":\"开关动作\"},{\"identifier\":\"Timestamp\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间戳\"}],\"type\":\"struct\"},\"name\":\"本地倒计时\",\"accessMode\":\"rw\",\"required\":false}],\"events\":[{\"outputData\":[{\"identifier\":\"WIFI_Band\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"电源开关\"},{\"identifier\":\"CountDown\",\"dataType\":{\"specs\":[{\"identifier\":\"IsRunning\",\"dataType\":{\"specs\":{\"0\":\"已停止\",\"1\":\"执行中\"},\"type\":\"bool\"},\"name\":\"运行状态\"},{\"identifier\":\"TimeLeft\",\"dataType\":{\"specs\":{\"unit\":\"s\",\"min\":\"0\",\"unitName\":\"秒\",\"max\":\"86399\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"剩余时间\"},{\"identifier\":\"PowerSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"打开\"},\"type\":\"bool\"},\"name\":\"开关动作\"},{\"identifier\":\"Timestamp\",\"dataType\":{\"specs\":{},\"type\":\"date\"},\"name\":\"时间戳\"}],\"type\":\"struct\"},\"name\":\"本地倒计时\"}],\"identifier\":\"post\",\"method\":\"thing.event.property.post\",\"name\":\"post\",\"type\":\"info\",\"required\":true,\"desc\":\"属性上报\"},{\"outputData\":[{\"identifier\":\"ErrorCode\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"故障代码\"}],\"identifier\":\"Error\",\"method\":\"thing.event.Error.post\",\"name\":\"故障上报\",\"type\":\"error\",\"required\":true}]}"; \ No newline at end of file diff --git a/iotkit-embedded/src/dev_model/examples/data/sched_tsl.data b/iotkit-embedded/src/dev_model/examples/data/sched_tsl.data new file mode 100644 index 0000000..1b17be1 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/data/sched_tsl.data @@ -0,0 +1,254 @@ +/* + * please modify this string follow as product's TSL. + */ + +static const char TSL_STRING[] = + "{\"schema\":\"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/" + "schema.json\",\"profile\":{\"productKey\":\"a1X2bEnP82z\"},\"services\":[{" + "\"outputData\":[],\"identifier\":\"set\",\"inputData\":[{\"identifier\":" + "\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}," + "\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"WIFI_Band\"," + "\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":" + "\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-" + "127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{" + "\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\"," + "\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{" + "\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"WIFI_Tx_Rate\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"WIFI_Tx_Rate_Name\"},{\"identifier\":\"WIFI_Rx_" + "Rate\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Rx_Rate_Name\"},{\"identifier\":" + "\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{" + "\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":" + "\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":" + "\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":" + "\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"HSVColor\",\"dataType\":" + "{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\"," + "\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%" + "\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":" + "\"HSV调色\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":" + "\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{" + "\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":" + "\"HSL调色\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":" + "\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":" + "\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":" + "\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}" + ",\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"Brightness\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":" + "\"明暗度\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{" + "\"unit\":\"K\",\"min\":\"2000\",\"unitName\":\"开尔文\",\"max\":\"7000\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":" + "\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":" + "\"text\"},\"name\":\"PropertyCharacter_Name\"},{\"identifier\":" + "\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"Propertypoint_Name\"}]," + "\"method\":\"thing.service.property.set\",\"name\":\"set\",\"required\":" + "true,\"callType\":\"async\",\"desc\":\"属性设置\"},{\"outputData\":[{" + "\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\"," + "\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":" + "\"WIFI_Band\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":" + "\"text\"},\"name\":\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{" + "\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_" + "BSSID\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"}," + "\"name\":\"热点BSSID\"},{\"identifier\":\"WIFI_Channel\",\"dataType\":{" + "\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\"," + "\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":" + "\"127\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信噪比\"},{" + "\"identifier\":\"WIFI_Tx_Rate\",\"dataType\":{\"specs\":{\"min\":\"0\"," + "\"max\":\"99999\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Tx_Rate_" + "Name\"},{\"identifier\":\"WIFI_Rx_Rate\",\"dataType\":{\"specs\":{\"min\":" + "\"0\",\"max\":\"99999\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_" + "Rx_Rate_Name\"},{\"identifier\":\"RGBColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Red\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":" + "\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"红色\"}," + "{\"identifier\":\"Green\",\"dataType\":{\"specs\":{\"min\":\"0\"," + "\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":{\"specs\":{" + "\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":" + "\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":\"RGB调色\"},{" + "\"identifier\":\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":" + "\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":" + "\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":" + "\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0." + "01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"明度\"}],\"type\":\"struct\"},\"name\":\"HSV调色\"},{\"identifier\":" + "\"HSLColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{" + "\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":" + "\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\"," + "\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"饱和度\"},{\"identifier\":\"Lightness\",\"dataType\":" + "{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"亮度\"}]," + "\"type\":\"struct\"},\"name\":\"HSL调色\"},{\"identifier\":\"WorkMode\"," + "\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":" + "\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"},\"name\":" + "\"工作模式\"},{\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{" + "\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\"},{" + "\"identifier\":\"Brightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"明暗度\"},{\"identifier\":\"ColorTemperature\"," + "\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":\"2000\",\"unitName\":" + "\"开尔文\",\"max\":\"7000\",\"step\":\"1\"},\"type\":\"int\"},\"name\":" + "\"冷暖色温\"},{\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":" + "{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"PropertyCharacter_Name\"}" + ",{\"identifier\":\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-" + "100\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"Propertypoint_Name\"}],\"identifier\":\"get\",\"inputData\":[" + "\"LightSwitch\",\"WIFI_Band\",\"WiFI_RSSI\",\"WIFI_AP_BSSID\",\"WIFI_" + "Channel\",\"WiFI_SNR\",\"WIFI_Tx_Rate\",\"WIFI_Rx_Rate\",\"RGBColor\"," + "\"HSVColor\",\"HSLColor\",\"WorkMode\",\"NightLightSwitch\",\"Brightness\"," + "\"ColorTemperature\",\"PropertyCharacter\",\"Propertypoint\"],\"method\":" + "\"thing.service.property.get\",\"name\":\"get\",\"required\":true," + "\"callType\":\"async\",\"desc\":\"属性获取\"}],\"properties\":[{" + "\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\"," + "\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\",\"accessMode\":" + "\"rw\",\"required\":true},{\"identifier\":\"WIFI_Band\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"频段\"," + "\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WiFI_RSSI\"," + "\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-" + "1\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信号强度\",\"accessMode\":" + "\"rw\",\"required\":true},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"," + "\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WIFI_Channel\"," + "\"dataType\":{\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信道\",\"accessMode\":\"rw\"," + "\"required\":true},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{" + "\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"信噪比\",\"accessMode\":\"rw\",\"required\":" + "true},{\"identifier\":\"WIFI_Tx_Rate\",\"dataType\":{\"specs\":{\"min\":" + "\"0\",\"max\":\"99999\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_" + "Tx_Rate_Name\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"WIFI_Rx_Rate\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Rx_Rate_Name\"," + "\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"RGBColor\"," + "\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{\"specs\":{" + "\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":" + "\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\",\"dataType\":{" + "\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":" + "{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":" + "\"RGB调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{" + "\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":" + "\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\"," + "\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"明度\"}]," + "\"type\":\"struct\"},\"name\":\"HSV调色\",\"accessMode\":\"rw\"," + "\"required\":false},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":" + "\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{" + "\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":" + "\"HSL调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"WorkMode\",\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":" + "\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"}," + "\"name\":\"工作模式\",\"accessMode\":\"rw\",\"required\":false},{" + "\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\"," + "\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\",\"accessMode\":" + "\"rw\",\"required\":false},{\"identifier\":\"Brightness\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"明暗度\"," + "\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"ColorTemperature\",\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":" + "\"2000\",\"unitName\":\"开尔文\",\"max\":\"7000\",\"step\":\"1\"},\"type\":" + "\"int\"},\"name\":\"冷暖色温\",\"accessMode\":\"rw\",\"required\":false},{" + "\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":" + "\"255\"},\"type\":\"text\"},\"name\":\"PropertyCharacter_Name\"," + "\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"Propertypoint\"," + "\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\",\"step\":\"0.01\"}" + ",\"type\":\"double\"},\"name\":\"Propertypoint_Name\",\"accessMode\":\"rw\"," + "\"required\":false}],\"events\":[{\"outputData\":[{\"identifier\":" + "\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}," + "\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"WIFI_Band\"," + "\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":" + "\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-" + "127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{" + "\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\"," + "\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{" + "\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"WIFI_Tx_Rate\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"WIFI_Tx_Rate_Name\"},{\"identifier\":\"WIFI_Rx_" + "Rate\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Rx_Rate_Name\"},{\"identifier\":" + "\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{" + "\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":" + "\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":" + "\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":" + "\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"HSVColor\",\"dataType\":" + "{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\"," + "\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%" + "\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":" + "\"HSV调色\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":" + "\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{" + "\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":" + "\"HSL调色\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":" + "\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":" + "\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":" + "\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}" + ",\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"Brightness\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":" + "\"明暗度\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{" + "\"unit\":\"K\",\"min\":\"2000\",\"unitName\":\"开尔文\",\"max\":\"7000\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":" + "\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":" + "\"text\"},\"name\":\"PropertyCharacter_Name\"},{\"identifier\":" + "\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"Propertypoint_Name\"}]," + "\"identifier\":\"post\",\"method\":\"thing.event.property.post\",\"name\":" + "\"post\",\"type\":\"info\",\"required\":true,\"desc\":\"属性上报\"},{" + "\"outputData\":[{\"identifier\":\"ErrorCode\",\"dataType\":{\"specs\":{" + "\"0\":\"恢复正常\"},\"type\":\"enum\"},\"name\":\"故障代码\"}]," + "\"identifier\":\"Error\",\"method\":\"thing.event.Error.post\",\"name\":" + "\"故障上报\",\"type\":\"error\",\"required\":true}]}"; \ No newline at end of file diff --git a/iotkit-embedded/src/dev_model/examples/data/solo_tsl.c b/iotkit-embedded/src/dev_model/examples/data/solo_tsl.c new file mode 100644 index 0000000..1b17be1 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/data/solo_tsl.c @@ -0,0 +1,254 @@ +/* + * please modify this string follow as product's TSL. + */ + +static const char TSL_STRING[] = + "{\"schema\":\"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/" + "schema.json\",\"profile\":{\"productKey\":\"a1X2bEnP82z\"},\"services\":[{" + "\"outputData\":[],\"identifier\":\"set\",\"inputData\":[{\"identifier\":" + "\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}," + "\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"WIFI_Band\"," + "\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":" + "\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-" + "127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{" + "\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\"," + "\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{" + "\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"WIFI_Tx_Rate\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"WIFI_Tx_Rate_Name\"},{\"identifier\":\"WIFI_Rx_" + "Rate\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Rx_Rate_Name\"},{\"identifier\":" + "\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{" + "\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":" + "\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":" + "\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":" + "\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"HSVColor\",\"dataType\":" + "{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\"," + "\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%" + "\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":" + "\"HSV调色\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":" + "\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{" + "\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":" + "\"HSL调色\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":" + "\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":" + "\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":" + "\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}" + ",\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"Brightness\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":" + "\"明暗度\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{" + "\"unit\":\"K\",\"min\":\"2000\",\"unitName\":\"开尔文\",\"max\":\"7000\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":" + "\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":" + "\"text\"},\"name\":\"PropertyCharacter_Name\"},{\"identifier\":" + "\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"Propertypoint_Name\"}]," + "\"method\":\"thing.service.property.set\",\"name\":\"set\",\"required\":" + "true,\"callType\":\"async\",\"desc\":\"属性设置\"},{\"outputData\":[{" + "\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\"," + "\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":" + "\"WIFI_Band\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":" + "\"text\"},\"name\":\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{" + "\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_" + "BSSID\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"}," + "\"name\":\"热点BSSID\"},{\"identifier\":\"WIFI_Channel\",\"dataType\":{" + "\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\"," + "\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":" + "\"127\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信噪比\"},{" + "\"identifier\":\"WIFI_Tx_Rate\",\"dataType\":{\"specs\":{\"min\":\"0\"," + "\"max\":\"99999\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Tx_Rate_" + "Name\"},{\"identifier\":\"WIFI_Rx_Rate\",\"dataType\":{\"specs\":{\"min\":" + "\"0\",\"max\":\"99999\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_" + "Rx_Rate_Name\"},{\"identifier\":\"RGBColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Red\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":" + "\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"红色\"}," + "{\"identifier\":\"Green\",\"dataType\":{\"specs\":{\"min\":\"0\"," + "\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":{\"specs\":{" + "\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":" + "\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":\"RGB调色\"},{" + "\"identifier\":\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":" + "\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":" + "\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{\"specs\":{\"unit\":" + "\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0." + "01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"明度\"}],\"type\":\"struct\"},\"name\":\"HSV调色\"},{\"identifier\":" + "\"HSLColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{" + "\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":" + "\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\"," + "\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"饱和度\"},{\"identifier\":\"Lightness\",\"dataType\":" + "{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"亮度\"}]," + "\"type\":\"struct\"},\"name\":\"HSL调色\"},{\"identifier\":\"WorkMode\"," + "\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":" + "\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"},\"name\":" + "\"工作模式\"},{\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{" + "\"0\":\"关闭\",\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\"},{" + "\"identifier\":\"Brightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"明暗度\"},{\"identifier\":\"ColorTemperature\"," + "\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":\"2000\",\"unitName\":" + "\"开尔文\",\"max\":\"7000\",\"step\":\"1\"},\"type\":\"int\"},\"name\":" + "\"冷暖色温\"},{\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":" + "{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"PropertyCharacter_Name\"}" + ",{\"identifier\":\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-" + "100\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"Propertypoint_Name\"}],\"identifier\":\"get\",\"inputData\":[" + "\"LightSwitch\",\"WIFI_Band\",\"WiFI_RSSI\",\"WIFI_AP_BSSID\",\"WIFI_" + "Channel\",\"WiFI_SNR\",\"WIFI_Tx_Rate\",\"WIFI_Rx_Rate\",\"RGBColor\"," + "\"HSVColor\",\"HSLColor\",\"WorkMode\",\"NightLightSwitch\",\"Brightness\"," + "\"ColorTemperature\",\"PropertyCharacter\",\"Propertypoint\"],\"method\":" + "\"thing.service.property.get\",\"name\":\"get\",\"required\":true," + "\"callType\":\"async\",\"desc\":\"属性获取\"}],\"properties\":[{" + "\"identifier\":\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\"," + "\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"主灯开关\",\"accessMode\":" + "\"rw\",\"required\":true},{\"identifier\":\"WIFI_Band\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"频段\"," + "\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WiFI_RSSI\"," + "\"dataType\":{\"specs\":{\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"-" + "1\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信号强度\",\"accessMode\":" + "\"rw\",\"required\":true},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"," + "\"accessMode\":\"rw\",\"required\":true},{\"identifier\":\"WIFI_Channel\"," + "\"dataType\":{\"specs\":{\"min\":\"1\",\"unitName\":\"无\",\"max\":\"255\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"信道\",\"accessMode\":\"rw\"," + "\"required\":true},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{" + "\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"信噪比\",\"accessMode\":\"rw\",\"required\":" + "true},{\"identifier\":\"WIFI_Tx_Rate\",\"dataType\":{\"specs\":{\"min\":" + "\"0\",\"max\":\"99999\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_" + "Tx_Rate_Name\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"WIFI_Rx_Rate\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Rx_Rate_Name\"," + "\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"RGBColor\"," + "\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{\"specs\":{" + "\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":" + "\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\",\"dataType\":{" + "\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":\"Blue\",\"dataType\":" + "{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":\"struct\"},\"name\":" + "\"RGB调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"HSVColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{" + "\"specs\":{\"unit\":\"°\",\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":" + "\"Saturation\",\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\"," + "\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"明度\"}]," + "\"type\":\"struct\"},\"name\":\"HSV调色\",\"accessMode\":\"rw\"," + "\"required\":false},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":" + "\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{" + "\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":" + "\"HSL调色\",\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"WorkMode\",\"dataType\":{\"specs\":{\"0\":\"手动\",\"1\":\"阅读\",\"2\":" + "\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":\"柔和\"},\"type\":\"enum\"}," + "\"name\":\"工作模式\",\"accessMode\":\"rw\",\"required\":false},{" + "\"identifier\":\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\"," + "\"1\":\"开启\"},\"type\":\"bool\"},\"name\":\"夜灯开关\",\"accessMode\":" + "\"rw\",\"required\":false},{\"identifier\":\"Brightness\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"明暗度\"," + "\"accessMode\":\"rw\",\"required\":false},{\"identifier\":" + "\"ColorTemperature\",\"dataType\":{\"specs\":{\"unit\":\"K\",\"min\":" + "\"2000\",\"unitName\":\"开尔文\",\"max\":\"7000\",\"step\":\"1\"},\"type\":" + "\"int\"},\"name\":\"冷暖色温\",\"accessMode\":\"rw\",\"required\":false},{" + "\"identifier\":\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":" + "\"255\"},\"type\":\"text\"},\"name\":\"PropertyCharacter_Name\"," + "\"accessMode\":\"rw\",\"required\":false},{\"identifier\":\"Propertypoint\"," + "\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\",\"step\":\"0.01\"}" + ",\"type\":\"double\"},\"name\":\"Propertypoint_Name\",\"accessMode\":\"rw\"," + "\"required\":false}],\"events\":[{\"outputData\":[{\"identifier\":" + "\"LightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}," + "\"type\":\"bool\"},\"name\":\"主灯开关\"},{\"identifier\":\"WIFI_Band\"," + "\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":" + "\"频段\"},{\"identifier\":\"WiFI_RSSI\",\"dataType\":{\"specs\":{\"min\":\"-" + "127\",\"unitName\":\"无\",\"max\":\"-1\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信号强度\"},{\"identifier\":\"WIFI_AP_BSSID\",\"dataType\":{" + "\"specs\":{\"length\":\"255\"},\"type\":\"text\"},\"name\":\"热点BSSID\"},{" + "\"identifier\":\"WIFI_Channel\",\"dataType\":{\"specs\":{\"min\":\"1\"," + "\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"},\"type\":\"int\"}," + "\"name\":\"信道\"},{\"identifier\":\"WiFI_SNR\",\"dataType\":{\"specs\":{" + "\"min\":\"-127\",\"unitName\":\"无\",\"max\":\"127\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"信噪比\"},{\"identifier\":\"WIFI_Tx_Rate\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":\"1\"}," + "\"type\":\"int\"},\"name\":\"WIFI_Tx_Rate_Name\"},{\"identifier\":\"WIFI_Rx_" + "Rate\",\"dataType\":{\"specs\":{\"min\":\"0\",\"max\":\"99999\",\"step\":" + "\"1\"},\"type\":\"int\"},\"name\":\"WIFI_Rx_Rate_Name\"},{\"identifier\":" + "\"RGBColor\",\"dataType\":{\"specs\":[{\"identifier\":\"Red\",\"dataType\":{" + "\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\",\"step\":\"1\"}" + ",\"type\":\"int\"},\"name\":\"红色\"},{\"identifier\":\"Green\"," + "\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":\"255\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"绿色\"},{\"identifier\":" + "\"Blue\",\"dataType\":{\"specs\":{\"min\":\"0\",\"unitName\":\"无\",\"max\":" + "\"255\",\"step\":\"1\"},\"type\":\"int\"},\"name\":\"蓝色\"}],\"type\":" + "\"struct\"},\"name\":\"RGB调色\"},{\"identifier\":\"HSVColor\",\"dataType\":" + "{\"specs\":[{\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\"," + "\"min\":\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":" + "\"饱和度\"},{\"identifier\":\"Value\",\"dataType\":{\"specs\":{\"unit\":\"%" + "\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"明度\"}],\"type\":\"struct\"},\"name\":" + "\"HSV调色\"},{\"identifier\":\"HSLColor\",\"dataType\":{\"specs\":[{" + "\"identifier\":\"Hue\",\"dataType\":{\"specs\":{\"unit\":\"°\",\"min\":" + "\"0\",\"unitName\":\"度\",\"max\":\"360\",\"step\":\"0.01\"},\"type\":" + "\"double\"},\"name\":\"色调\"},{\"identifier\":\"Saturation\",\"dataType\":{" + "\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":\"百分比\",\"max\":" + "\"100\",\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"饱和度\"},{" + "\"identifier\":\"Lightness\",\"dataType\":{\"specs\":{\"unit\":\"%\"," + "\"min\":\"0\",\"unitName\":\"百分比\",\"max\":\"100\",\"step\":\"0.01\"}," + "\"type\":\"double\"},\"name\":\"亮度\"}],\"type\":\"struct\"},\"name\":" + "\"HSL调色\"},{\"identifier\":\"WorkMode\",\"dataType\":{\"specs\":{\"0\":" + "\"手动\",\"1\":\"阅读\",\"2\":\"影院\",\"3\":\"夜灯\",\"4\":\"生活\",\"5\":" + "\"柔和\"},\"type\":\"enum\"},\"name\":\"工作模式\"},{\"identifier\":" + "\"NightLightSwitch\",\"dataType\":{\"specs\":{\"0\":\"关闭\",\"1\":\"开启\"}" + ",\"type\":\"bool\"},\"name\":\"夜灯开关\"},{\"identifier\":\"Brightness\"," + "\"dataType\":{\"specs\":{\"unit\":\"%\",\"min\":\"0\",\"unitName\":" + "\"百分比\",\"max\":\"100\",\"step\":\"1\"},\"type\":\"int\"},\"name\":" + "\"明暗度\"},{\"identifier\":\"ColorTemperature\",\"dataType\":{\"specs\":{" + "\"unit\":\"K\",\"min\":\"2000\",\"unitName\":\"开尔文\",\"max\":\"7000\"," + "\"step\":\"1\"},\"type\":\"int\"},\"name\":\"冷暖色温\"},{\"identifier\":" + "\"PropertyCharacter\",\"dataType\":{\"specs\":{\"length\":\"255\"},\"type\":" + "\"text\"},\"name\":\"PropertyCharacter_Name\"},{\"identifier\":" + "\"Propertypoint\",\"dataType\":{\"specs\":{\"min\":\"-100\",\"max\":\"100\"," + "\"step\":\"0.01\"},\"type\":\"double\"},\"name\":\"Propertypoint_Name\"}]," + "\"identifier\":\"post\",\"method\":\"thing.event.property.post\",\"name\":" + "\"post\",\"type\":\"info\",\"required\":true,\"desc\":\"属性上报\"},{" + "\"outputData\":[{\"identifier\":\"ErrorCode\",\"dataType\":{\"specs\":{" + "\"0\":\"恢复正常\"},\"type\":\"enum\"},\"name\":\"故障代码\"}]," + "\"identifier\":\"Error\",\"method\":\"thing.event.Error.post\",\"name\":" + "\"故障上报\",\"type\":\"error\",\"required\":true}]}"; \ No newline at end of file diff --git a/iotkit-embedded/src/dev_model/examples/gateway.c b/iotkit-embedded/src/dev_model/examples/gateway.c new file mode 100644 index 0000000..b722112 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/gateway.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include +#include +#include +#include +#include "cJSON.h" +#include "infra_compat.h" +#include "infra_defs.h" +#include "linkkit_gateway_export.h" +#ifdef LINKKIT_GATEWAY_TEST_CMD + #include "simulate_subdev/testcmd.h" +#endif + +void HAL_Free(void *ptr); +uint64_t HAL_UptimeMs(void); +void HAL_SleepMs(uint32_t ms); +int HAL_SetProductKey(char *product_key); +int HAL_SetDeviceName(char *device_name); +int HAL_SetProductSecret(char *product_secret); +int HAL_SetDeviceSecret(char *device_secret); + +/* for demo only */ +#define PRODUCT_KEY "a16UKrlKekO" +#define PRODUCT_SECRET "RDluqbn3LQazrdqM" +#define DEVICE_NAME "gateway_test01" +#define DEVICE_SECRET "AT2XFOPOIbJaKfXsKeaEhabJ8TLhMQYp" + +#define EXAMPLE_TRACE(...) \ + do { \ + printf("\033[1;31;40m%s.%d: ", __func__, __LINE__); \ + printf(__VA_ARGS__); \ + printf("\033[0m"); \ + } while (0) + +typedef struct { + int ZB_Band; + int ZB_Channel; + + char ZB_CO_MAC[32 + 1]; + char ZB_PAN_ID[32 + 1]; + char EXT_PAN_ID[32 + 1]; + char NETWORK_KEY[32 + 1]; + + int connected; + int register_completed; + int lk_dev; +} gateway_t; + +gateway_t gateway; +static int gateway_register_complete(void *ctx); +static int gateway_get_property(char *in, char *out, int out_len, void *ctx); +static int gateway_set_property(char *in, void *ctx); +static int gateway_call_service(char *identifier, char *in, char *out, + int out_len, void *ctx); + + +/* callback function */ +static linkkit_cbs_t linkkit_cbs = { + .register_complete = gateway_register_complete, + .get_property = gateway_get_property, + .set_property = gateway_set_property, + .call_service = gateway_call_service, +}; + +#ifdef LINKKIT_GATEWAY_TEST_CMD +static int disable_join = 1; /* not allow to join */ +static char permit_productKey[PRODUCT_KEY_MAXLEN]; +static uint64_t permit_timeout_ms; + +int linkkit_gateway_check_permit(int devtype, const char *productKey) +{ + uint64_t uptime_ms = HAL_UptimeMs(); + + EXAMPLE_TRACE("devtype = %d\n", devtype); + if (1 != devtype) { + return 1; + } + + EXAMPLE_TRACE("disable_join = %d\n", disable_join); + if (disable_join) { + return 0; + } + + EXAMPLE_TRACE("permit_productKey = %s\n", permit_productKey); + if (permit_productKey[0] && strcmp(permit_productKey, productKey)) { + return 0; + } + + EXAMPLE_TRACE("uptime_ms = %llu, permit_timeout_ms = %llu\n", uptime_ms, + permit_timeout_ms); + if (uptime_ms < permit_timeout_ms) { + return 1; + } + + disable_join = 1; + + return 0; +} + +int linkkit_gateway_testcmd_post_properties(const char *properties) +{ + if (linkkit_gateway_post_property_json_sync(gateway.lk_dev, + (char *)properties, 10000) < 0) { + return -1; + } + return 0; +} + +int linkkit_gateway_testcmd_post_event(const char *identifier, + const char *events) +{ + if (linkkit_gateway_trigger_event_json_sync( + gateway.lk_dev, (char *)identifier, (char *)events, 10000) < 0) { + return -1; + } + + return 0; +} + +#endif + +static int gateway_register_complete(void *ctx) +{ + gateway_t *gw = (gateway_t *)ctx; + + gw->register_completed = 1; + + return 0; +} + +/* + * the handler property get + * alink method: thing.service.property.get + */ +static int gateway_get_property(char *in, char *out, int out_len, void *ctx) +{ + gateway_t *gw = ctx; + cJSON *rJson, *pJson; + char *p; + int iSize, i; + + EXAMPLE_TRACE("in: %s\n", in); + + if (!gw) { + EXAMPLE_TRACE("gateway not found\n"); + return -1; + } + + /* parse input json */ + rJson = cJSON_Parse(in); + if (!rJson) { + return -1; + } + + iSize = cJSON_GetArraySize(rJson); + if (iSize <= 0) { + cJSON_Delete(rJson); + return -1; + } + + pJson = cJSON_CreateObject(); + if (!pJson) { + cJSON_Delete(rJson); + return -1; + } + + /* + * follow TSL to parse input json, and generate output json. + * please modify this logic in user's case follow as user's TSL. + */ + for (i = 0; i < iSize; i++) { + cJSON *pSub = cJSON_GetArrayItem(rJson, i); + + if (strcmp(pSub->valuestring, "ZB_Band") == 0) { + cJSON_AddNumberToObject(pJson, "ZB_Band", gw->ZB_Band); + } else if (strcmp(pSub->valuestring, "ZB_Channel") == 0) { + cJSON_AddNumberToObject(pJson, "ZB_Channel", gw->ZB_Channel); + } else if (strcmp(pSub->valuestring, "ZB_CO_MAC") == 0) { + cJSON_AddStringToObject(pJson, "ZB_CO_MAC", gw->ZB_CO_MAC); + } else if (strcmp(pSub->valuestring, "ZB_PAN_ID") == 0) { + cJSON_AddStringToObject(pJson, "ZB_PAN_ID", gw->ZB_PAN_ID); + } else if (strcmp(pSub->valuestring, "EXT_PAN_ID") == 0) { + cJSON_AddStringToObject(pJson, "EXT_PAN_ID", gw->EXT_PAN_ID); + } else if (strcmp(pSub->valuestring, "NETWORK_KEY") == 0) { + cJSON_AddStringToObject(pJson, "NETWORK_KEY", gw->NETWORK_KEY); + } + } + + p = cJSON_PrintUnformatted(pJson); + if (!p) { + cJSON_Delete(rJson); + cJSON_Delete(pJson); + return -1; + } + + if (strlen(p) >= out_len) { + cJSON_Delete(rJson); + cJSON_Delete(pJson); + HAL_Free(p); + return -1; + } + + strcpy(out, p); + + EXAMPLE_TRACE("out: %s\n", out); + + cJSON_Delete(rJson); + cJSON_Delete(pJson); + HAL_Free(p); + + return 0; +} + +/* + * the handler property set + * alink method: thing.service.property.set + */ +static int gateway_set_property(char *in, void *ctx) +{ + gateway_t *gw = ctx; + cJSON *rJson, *ZB_Band, *ZB_Channel, *ZB_PAN_ID, *EXT_PAN_ID, *ZB_CO_MAC, + *NETWORK_KEY; + + EXAMPLE_TRACE("in: %s\n", in); + + rJson = cJSON_Parse(in); + if (!rJson) { + return -1; + } + + /* parse input json, set the gateway value */ + ZB_Band = cJSON_GetObjectItem(rJson, "ZB_Band"); + if (ZB_Band) { + gw->ZB_Band = ZB_Band->valueint; + } + + ZB_Channel = cJSON_GetObjectItem(rJson, "ZB_Channel"); + if (ZB_Channel) { + gw->ZB_Channel = ZB_Channel->valueint; + } + + ZB_PAN_ID = cJSON_GetObjectItem(rJson, "ZB_PAN_ID"); + if (ZB_PAN_ID) + strncpy(gw->ZB_PAN_ID, ZB_PAN_ID->valuestring, + sizeof(gw->ZB_PAN_ID) - 1); + + EXT_PAN_ID = cJSON_GetObjectItem(rJson, "EXT_PAN_ID"); + if (EXT_PAN_ID) + strncpy(gw->EXT_PAN_ID, EXT_PAN_ID->valuestring, + sizeof(gw->EXT_PAN_ID) - 1); + + ZB_CO_MAC = cJSON_GetObjectItem(rJson, "ZB_CO_MAC"); + if (ZB_CO_MAC) + strncpy(gw->ZB_CO_MAC, ZB_CO_MAC->valuestring, + sizeof(gw->ZB_CO_MAC) - 1); + + NETWORK_KEY = cJSON_GetObjectItem(rJson, "NETWORK_KEY"); + if (NETWORK_KEY) + strncpy(gw->NETWORK_KEY, NETWORK_KEY->valuestring, + sizeof(gw->NETWORK_KEY) - 1); + + linkkit_gateway_post_property_json_sync(gw->lk_dev, in, 5000); + cJSON_Delete(rJson); + + return 0; +} + + +/* + * the handler of service which is defined by identifier, not property + * alink method: thing.service.{tsl.service.identifier} + */ +static int gateway_call_service(char *identifier, char *in, char *out, + int out_len, void *ctx) +{ + /* + * please follow user's TSL to mofidy this id - SetTimerTask and TimeReset. + */ + if (strcmp(identifier, "SetTimerTask") == 0) { + snprintf(out, out_len, "{\"SetTimer\": \"hello, gateway!\"}"); + } else if (strcmp(identifier, "TimeReset") == 0) { + EXAMPLE_TRACE("TimeReset params: %s\n", in); + } + + return 0; +} + + +/* + * post all properties + */ +static int post_all_properties(gateway_t *gw) +{ + cJSON *pJson = cJSON_CreateObject(); + char *p = NULL; + if (!pJson) { + return -1; + } + + cJSON_AddNumberToObject(pJson, "ZB_Band", gw->ZB_Band); + cJSON_AddNumberToObject(pJson, "ZB_Channel", gw->ZB_Channel); + cJSON_AddStringToObject(pJson, "ZB_CO_MAC", gw->ZB_CO_MAC); + cJSON_AddStringToObject(pJson, "ZB_PAN_ID", gw->ZB_PAN_ID); + cJSON_AddStringToObject(pJson, "EXT_PAN_ID", gw->EXT_PAN_ID); + cJSON_AddStringToObject(pJson, "NETWORK_KEY", gw->NETWORK_KEY); + + p = cJSON_PrintUnformatted(pJson); + if (!p) { + cJSON_Delete(pJson); + return -1; + } + + EXAMPLE_TRACE("property: %s\n", p); + + linkkit_gateway_post_property_json_sync(gw->lk_dev, p, 5000); + + cJSON_Delete(pJson); + HAL_Free(p); + + return 0; +} + +/* event handler for gateway */ +static int event_handler(linkkit_event_t *ev, void *ctx) +{ + gateway_t *gw = ctx; + + switch (ev->event_type) { + /* cloud connected */ + case LINKKIT_EVENT_CLOUD_CONNECTED: { + EXAMPLE_TRACE("cloud connected\n"); + /* modify user's logic in there */ + /* example case just post all property */ + post_all_properties(gw); /* sync to cloud */ + gw->connected = 1; + } + break; + + /* cloud disconnected */ + case LINKKIT_EVENT_CLOUD_DISCONNECTED: { + gw->connected = 0; + EXAMPLE_TRACE("cloud disconnected\n"); + } + break; + + /* subdev delete */ + case LINKKIT_EVENT_SUBDEV_DELETED: { + char *productKey = ev->event_data.subdev_deleted.productKey; + char *deviceName = ev->event_data.subdev_deleted.deviceName; + EXAMPLE_TRACE("delete subdev %s<%s>\n", productKey, deviceName); + +#ifdef LINKKIT_GATEWAY_TEST_CMD + if (testcmd_delete_device(productKey, deviceName)) { + EXAMPLE_TRACE("Delete subdevice %s<%s> failed!\n", productKey, + deviceName); + } +#endif + } + break; + + /* between timeoutSec, subdev of productKey can be register */ + case LINKKIT_EVENT_SUBDEV_PERMITED: { + char *productKey = ev->event_data.subdev_permited.productKey; + int timeoutSec = ev->event_data.subdev_permited.timeoutSec; + EXAMPLE_TRACE("permit subdev %s in %d seconds\n", productKey, + timeoutSec); +#ifdef LINKKIT_GATEWAY_TEST_CMD + disable_join = 0; + if (NULL == productKey) { + memset(permit_productKey, 0, sizeof(permit_productKey)); + } else { + strcpy(permit_productKey, productKey); + } + permit_timeout_ms = HAL_UptimeMs() + timeoutSec * 1000; +#endif + /* please enter user's logic in there */ + } + break; + } + + return 0; +} + +void set_iotx_info() +{ + HAL_SetProductKey(PRODUCT_KEY); + HAL_SetProductSecret(PRODUCT_SECRET); + HAL_SetDeviceName(DEVICE_NAME); + HAL_SetDeviceSecret(DEVICE_SECRET); +} + +int main(int argc, char **argv) +{ + linkkit_params_t *initParams = NULL; + int maxMsgSize, maxMsgQueueSize, prop_post_reply, event_post_reply; + + IOT_SetLogLevel(IOT_LOG_DEBUG); + +#if !defined(WIFI_PROVISION_ENABLED) || !defined(BUILD_AOS) + set_iotx_info(); +#endif + memset(&gateway, 0, sizeof(gateway_t)); + + /* fill fake zigbee network info */ + /* + * this example is a zigbee subdev. + * please modify this logic follow as user's case. + */ + gateway.ZB_Band = 25; + gateway.ZB_Channel = 16; + + strcpy(gateway.ZB_PAN_ID, "8215"); + strcpy(gateway.EXT_PAN_ID, "000D6F000ED34E34"); + strcpy(gateway.ZB_CO_MAC, "000D6F000ED34E34"); + strcpy(gateway.NETWORK_KEY, "21B9F385F114B1C4AE07D5753B95355D"); + + /* + * please set init parameter + */ + initParams = linkkit_gateway_get_default_params(); + if (!initParams) { + return -1; + } + /* LINKKIT_OPT_MAX_MSG_SIZE: max size of message */ + maxMsgSize = 4096; + linkkit_gateway_setopt(initParams, LINKKIT_OPT_MAX_MSG_SIZE, &maxMsgSize, + sizeof(int)); + /* LINKKIT_OPT_MAX_MSG_QUEUE_SIZE: max size of message queue */ + maxMsgQueueSize = 8; + linkkit_gateway_setopt(initParams, LINKKIT_OPT_MAX_MSG_QUEUE_SIZE, + &maxMsgQueueSize, sizeof(int)); + + prop_post_reply = 0; + linkkit_gateway_setopt(initParams, LINKKIT_OPT_PROPERTY_POST_REPLY, + &prop_post_reply, sizeof(int)); + + event_post_reply = 0; + linkkit_gateway_setopt(initParams, LINKKIT_OPT_EVENT_POST_REPLY, + &event_post_reply, sizeof(int)); + + int stacksize = 1024 * 4; + linkkit_gateway_setopt(initParams, LINKKIT_OPT_THREAD_STACK_SIZE, + &stacksize, sizeof(int)); + + /* set event handler */ + linkkit_gateway_set_event_callback(initParams, event_handler, &gateway); + + /* set init parameter into gateway */ + if (linkkit_gateway_init(initParams) < 0) { + EXAMPLE_TRACE("linkkit_gateway_init failed\n"); + return -1; + } + + /* start */ + gateway.lk_dev = linkkit_gateway_start(&linkkit_cbs, &gateway); + if (gateway.lk_dev < 0) { + EXAMPLE_TRACE("linkkit_gateway_start failed\n"); + return -1; + } + + while (gateway.register_completed == 0) { + HAL_SleepMs(1000); + } + + + while (1) { + /* + * gateway trigger event + * please follow user's case, modify this logic + */ + linkkit_gateway_trigger_event_json_sync(gateway.lk_dev, "Error", + "{\"ErrorCode\": 0}", 10000); + HAL_SleepMs(1000); + } + + /* gateway stop */ + linkkit_gateway_stop(gateway.lk_dev); + /* gateway exit */ + linkkit_gateway_exit(); + + IOT_DumpMemoryStats(IOT_LOG_DEBUG); + + EXAMPLE_TRACE("out of sample!\n"); + return 0; +} diff --git a/iotkit-embedded/src/dev_model/examples/linkkit_example_gateway.c b/iotkit-embedded/src/dev_model/examples/linkkit_example_gateway.c new file mode 100644 index 0000000..12eaea8 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/linkkit_example_gateway.c @@ -0,0 +1,517 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include "infra_config.h" +#ifdef DEPRECATED_LINKKIT +#include "gateway.c" +#else +#include +#include +#include +#include +#include +#include +#include "cJSON.h" +#include "infra_types.h" +#include "infra_defs.h" +#include "infra_compat.h" +#include "infra_log.h" +#include "infra_compat.h" +#include "infra_log.h" +#include "dev_model_api.h" +#include "dm_wrapper.h" + +#ifdef LINKKIT_GATEWAY_TEST_CMD + #include "simulate_subdev/testcmd.h" +#endif + +#if defined(OTA_ENABLED) && defined(BUILD_AOS) + #include "ota_service.h" +#endif + +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}; + +#define USER_EXAMPLE_YIELD_TIMEOUT_MS (200) + +void HAL_Printf(const char *fmt, ...); +#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_SUBDEV_ADD_NUM 3 +#define EXAMPLE_SUBDEV_MAX_NUM 20 +const iotx_linkkit_dev_meta_info_t subdevArr[EXAMPLE_SUBDEV_MAX_NUM] = { + { + "a13Npv1vjZ4", + "PKbZL7baK8pBso94", + "example_sub1", + "eglNFNJiRuR0yncB9RP05sSTY4FrUIoe" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_02", + "jFsErM3uA7UfbS6J0hm0QaEXsQbmO6Pa" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_03", + "MjWMvCLBcuZyqUswryBbgypN8uOgJGVD" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_04", + "DXbcbpxepIyYm3BiS0ICdBou4uWPfP6L" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_05", + "VKuVZfcz3umcoR3WhOp4cu1p2dyTQGq1" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_06", + "QTobiz1BdGW5XNgLGIgNSylH0btVvvGS" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_07", + "IX7ol50rRS2uP8V74jt0DKfmYn8iC6h1" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_08", + "sbFxx62evXVoVgJ5gL2oCLcz1pX9d6K2" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_09", + "S0CpOl54GZxEO7Gz5DWQa5YxgUMfT4xA" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_10", + "MowJJjiNIkTdUcX5fCNUDu39Yz02KADL" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_11", + "BrJNdAihVznMWTpdRfe8HIiI95ubSYdN" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_12", + "Yd3ZHK8D6cAKKRQb9rUevCfwPf7atoQ4" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_13", + "d3HKvu2eBR5ytcgDaBEt0gpvJZlu9W0g" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_14", + "qAJYUpQ1tGmAINQBzMiZwwbyjY6YXDGc" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_15", + "GxgVknnAmUmwjjdHJf9dbEBDoqyDaUfp" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_16", + "9d17Sv05j1XeTYOs80UBpBU1OYTTJ58X" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_17", + "FTUm4HAfhZ5wH2u0pPn7PWcCLGDrgEfn" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_18", + "mF7a2ptc3PRi7jWLE92t0GElhGdPnAe3" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_19", + "Vrh8HuNvu3jtTEwSzulAjTqgOseAsVgz" + }, + { + "a1YRfb9bepk", + "PKbZL7baK8pBso94", + "test_20", + "8Wxrxnjch6SW0s2HR5JkIBtgjt3BOUo7" + } +}; + +typedef struct { + int auto_add_subdev; + int master_devid; + int cloud_connected; + int master_initialized; + int subdev_index; + int permit_join; + void *g_user_dispatch_thread; + int g_user_dispatch_thread_running; +} user_example_ctx_t; + +static user_example_ctx_t g_user_example_ctx; + +void *example_malloc(size_t size) +{ + return HAL_Malloc(size); +} + +void example_free(void *ptr) +{ + HAL_Free(ptr); +} + +static user_example_ctx_t *user_example_get_ctx(void) +{ + return &g_user_example_ctx; +} + +static int user_connected_event_handler(void) +{ + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + + EXAMPLE_TRACE("Cloud Connected"); + + user_example_ctx->cloud_connected = 1; + + return 0; +} + +static int user_disconnected_event_handler(void) +{ + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + + EXAMPLE_TRACE("Cloud Disconnected"); + + user_example_ctx->cloud_connected = 0; + + return 0; +} + +static int user_property_set_event_handler(const int devid, const char *request, const int request_len) +{ + int res = 0; + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + EXAMPLE_TRACE("Property Set Received, Devid: %d, Request: %s", devid, request); + + res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY, + (unsigned char *)request, request_len); + EXAMPLE_TRACE("Post Property Message ID: %d", res); + + return 0; +} + +static int user_report_reply_event_handler(const int devid, const int msgid, const int code, const char *reply, + const int reply_len) +{ + const char *reply_value = (reply == NULL) ? ("NULL") : (reply); + const int reply_value_len = (reply_len == 0) ? (strlen("NULL")) : (reply_len); + + EXAMPLE_TRACE("Message Post Reply Received, Devid: %d, Message ID: %d, Code: %d, Reply: %.*s", devid, msgid, code, + reply_value_len, + reply_value); + return 0; +} + +static int user_timestamp_reply_event_handler(const char *timestamp) +{ + EXAMPLE_TRACE("Current Timestamp: %s", timestamp); + + return 0; +} + +static int user_initialized(const int devid) +{ + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + EXAMPLE_TRACE("Device Initialized, Devid: %d", devid); + + if (user_example_ctx->master_devid == devid) { + user_example_ctx->master_initialized = 1; + user_example_ctx->subdev_index++; + } + + return 0; +} + +static uint64_t user_update_sec(void) +{ + static uint64_t time_start_ms = 0; + + if (time_start_ms == 0) { + time_start_ms = HAL_UptimeMs(); + } + + return (HAL_UptimeMs() - time_start_ms) / 1000; +} + +void user_post_property(void) +{ + int res = 0; + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + char *property_payload = "{\"Counter\":1}"; + + res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_POST_PROPERTY, + (unsigned char *)property_payload, strlen(property_payload)); + EXAMPLE_TRACE("Post Property Message ID: %d", res); +} + +void user_deviceinfo_update(void) +{ + int res = 0; + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + char *device_info_update = "[{\"attrKey\":\"abc\",\"attrValue\":\"hello,world\"}]"; + + res = IOT_Linkkit_Report(user_example_ctx->master_devid, ITM_MSG_DEVICEINFO_UPDATE, + (unsigned char *)device_info_update, strlen(device_info_update)); + EXAMPLE_TRACE("Device Info Update Message ID: %d", res); +} + +void user_deviceinfo_delete(void) +{ + int res = 0; + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + char *device_info_delete = "[{\"attrKey\":\"abc\"}]"; + + res = IOT_Linkkit_Report(user_example_ctx->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 user_master_dev_available(void) +{ + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + + if (user_example_ctx->cloud_connected && user_example_ctx->master_initialized) { + return 1; + } + + return 0; +} + +static int example_add_subdev(iotx_linkkit_dev_meta_info_t *meta_info) +{ + int res = 0, devid = -1; + devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_SLAVE, meta_info); + if (devid == FAIL_RETURN) { + EXAMPLE_TRACE("subdev open Failed\n"); + return FAIL_RETURN; + } + EXAMPLE_TRACE("subdev open susseed, devid = %d\n", devid); + + res = IOT_Linkkit_Connect(devid); + if (res == FAIL_RETURN) { + EXAMPLE_TRACE("subdev connect Failed\n"); + return res; + } + EXAMPLE_TRACE("subdev connect success: devid = %d\n", devid); + + res = IOT_Linkkit_Report(devid, ITM_MSG_LOGIN, NULL, 0); + if (res == FAIL_RETURN) { + EXAMPLE_TRACE("subdev login Failed\n"); + return res; + } + EXAMPLE_TRACE("subdev login success: devid = %d\n", devid); + return res; +} + +int user_permit_join_event_handler(const char *product_key, const int time) +{ + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + + EXAMPLE_TRACE("Product Key: %s, Time: %d", product_key, time); + + user_example_ctx->permit_join = 1; + + return 0; +} + +void *user_dispatch_yield(void *args) +{ + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + + while (user_example_ctx->g_user_dispatch_thread_running) { + IOT_Linkkit_Yield(USER_EXAMPLE_YIELD_TIMEOUT_MS); + } + + return NULL; +} + +static int max_running_seconds = 0; +int main(int argc, char **argv) +{ + int res = 0; + uint64_t time_prev_sec = 0, time_now_sec = 0, time_begin_sec = 0; + user_example_ctx_t *user_example_ctx = user_example_get_ctx(); + iotx_linkkit_dev_meta_info_t master_meta_info; + int domain_type = 0; + int dynamic_register = 0; + int post_event_reply = 0; + + memset(user_example_ctx, 0, sizeof(user_example_ctx_t)); + +#if defined(__UBUNTU_SDK_DEMO__) + if (argc > 1) { + int tmp = atoi(argv[1]); + + if (tmp >= 60) { + max_running_seconds = tmp; + EXAMPLE_TRACE("set [max_running_seconds] = %d seconds\n", max_running_seconds); + } + } + + if (argc > 2) { + if (strlen("auto") == strlen(argv[2]) && + memcmp("auto", argv[2], strlen(argv[2])) == 0) { + user_example_ctx->auto_add_subdev = 1; + } + } +#endif + + HAL_GetProductKey(PRODUCT_KEY); + HAL_GetProductSecret(PRODUCT_SECRET); + HAL_GetDeviceName(DEVICE_NAME); + HAL_GetDeviceSecret(DEVICE_SECRET); + + user_example_ctx->subdev_index = -1; + + IOT_SetLogLevel(IOT_LOG_DEBUG); + + /* Register Callback */ + IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler); + IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler); + IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_event_handler); + IOT_RegisterCallback(ITE_REPORT_REPLY, user_report_reply_event_handler); + IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_event_handler); + IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized); + IOT_RegisterCallback(ITE_PERMIT_JOIN, user_permit_join_event_handler); + + 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)); + + /* Create Master Device Resources */ + user_example_ctx->master_devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, &master_meta_info); + if (user_example_ctx->master_devid < 0) { + EXAMPLE_TRACE("IOT_Linkkit_Open Failed\n"); + return -1; + } + + /* Choose Login Server */ + domain_type = IOTX_CLOUD_REGION_SHANGHAI; + 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); + + /* Choose Whether You Need Post Property/Event Reply */ + post_event_reply = 0; + IOT_Ioctl(IOTX_IOCTL_RECV_EVENT_REPLY, (void *)&post_event_reply); + + /* Start Connect Aliyun Server */ + do { + res = IOT_Linkkit_Connect(user_example_ctx->master_devid); + if (res < 0) { + EXAMPLE_TRACE("IOT_Linkkit_Connect failed, retry after 5s...\n"); + HAL_SleepMs(5000); + } + } while (res < 0); + + + user_example_ctx->g_user_dispatch_thread_running = 1; + res = HAL_ThreadCreate(&user_example_ctx->g_user_dispatch_thread, user_dispatch_yield, NULL, NULL, NULL); + if (res < 0) { + EXAMPLE_TRACE("HAL_ThreadCreate Failed\n"); + IOT_Linkkit_Close(user_example_ctx->master_devid); + return -1; + } + + time_begin_sec = user_update_sec(); + while (1) { + HAL_SleepMs(200); + + time_now_sec = user_update_sec(); + if (time_prev_sec == time_now_sec) { + continue; + } + if (max_running_seconds && (time_now_sec - time_begin_sec > max_running_seconds)) { + EXAMPLE_TRACE("Example Run for Over %d Seconds, Break Loop!\n", max_running_seconds); + break; + } + + /* Add subdev */ + if (user_example_ctx->master_initialized && user_example_ctx->subdev_index >= 0 && + (user_example_ctx->auto_add_subdev == 1 || user_example_ctx->permit_join != 0)) { + if (user_example_ctx->subdev_index < EXAMPLE_SUBDEV_ADD_NUM) { + /* Add next subdev */ + if (example_add_subdev((iotx_linkkit_dev_meta_info_t *)&subdevArr[user_example_ctx->subdev_index]) == SUCCESS_RETURN) { + EXAMPLE_TRACE("subdev %s add succeed", subdevArr[user_example_ctx->subdev_index].device_name); + } else { + EXAMPLE_TRACE("subdev %s add failed", subdevArr[user_example_ctx->subdev_index].device_name); + } + user_example_ctx->subdev_index++; + user_example_ctx->permit_join = 0; + } + } + + /* Post Proprety Example */ + if (time_now_sec % 11 == 0 && user_master_dev_available()) { + /* user_post_property(); */ + } + + /* Device Info Update Example */ + if (time_now_sec % 23 == 0 && user_master_dev_available()) { + /* user_deviceinfo_update(); */ + } + + /* Device Info Delete Example */ + if (time_now_sec % 29 == 0 && user_master_dev_available()) { + /* user_deviceinfo_delete(); */ + } + + time_prev_sec = time_now_sec; + } + + user_example_ctx->g_user_dispatch_thread_running = 0; + IOT_Linkkit_Close(user_example_ctx->master_devid); + HAL_ThreadDelete(user_example_ctx->g_user_dispatch_thread); + + IOT_DumpMemoryStats(IOT_LOG_DEBUG); + IOT_SetLogLevel(IOT_LOG_NONE); + return 0; +} + +#endif diff --git a/iotkit-embedded/src/dev_model/examples/linkkit_example_solo.c b/iotkit-embedded/src/dev_model/examples/linkkit_example_solo.c new file mode 100644 index 0000000..fc3908d --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/linkkit_example_solo.c @@ -0,0 +1,362 @@ +/* + * 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 + +#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; + + +/** 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 disconnected event callback */ +static int user_disconnected_event_handler(void) +{ + EXAMPLE_TRACE("Cloud Disconnected"); + g_user_example_ctx.cloud_connected = 0; + + 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; +} + +/** recv event post response message from cloud **/ +static int user_property_set_event_handler(const int devid, const char *request, const int request_len) +{ + int res = 0; + EXAMPLE_TRACE("Property Set Received, Request: %s", request); + + res = IOT_Linkkit_Report(EXAMPLE_MASTER_DEVID, ITM_MSG_POST_PROPERTY, + (unsigned char *)request, request_len); + EXAMPLE_TRACE("Post Property Message ID: %d", res); + + return 0; +} + + +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 add_result = 0; + cJSON *root = NULL, *item_number_a = NULL, *item_number_b = NULL; + const char *response_fmt = "{\"Result\": %d}"; + + EXAMPLE_TRACE("Service Request Received, Service ID: %.*s, Payload: %s", serviceid_len, serviceid, request); + + /* Parse Root */ + root = cJSON_Parse(request); + if (root == NULL || !cJSON_IsObject(root)) { + EXAMPLE_TRACE("JSON Parse Error"); + return -1; + } + + if (strlen("Operation_Service") == serviceid_len && memcmp("Operation_Service", serviceid, serviceid_len) == 0) { + /* Parse NumberA */ + item_number_a = cJSON_GetObjectItem(root, "NumberA"); + if (item_number_a == NULL || !cJSON_IsNumber(item_number_a)) { + cJSON_Delete(root); + return -1; + } + EXAMPLE_TRACE("NumberA = %d", item_number_a->valueint); + + /* Parse NumberB */ + item_number_b = cJSON_GetObjectItem(root, "NumberB"); + if (item_number_b == NULL || !cJSON_IsNumber(item_number_b)) { + cJSON_Delete(root); + return -1; + } + EXAMPLE_TRACE("NumberB = %d", item_number_b->valueint); + + add_result = item_number_a->valueint + item_number_b->valueint; + + /* Send Service Response To Cloud */ + *response_len = strlen(response_fmt) + 10 + 1; + *response = (char *)HAL_Malloc(*response_len); + if (*response == NULL) { + EXAMPLE_TRACE("Memory Not Enough"); + return -1; + } + memset(*response, 0, *response_len); + HAL_Snprintf(*response, *response_len, response_fmt, add_result); + *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 0; +} + +/** fota event handler **/ +static int user_fota_event_handler(int type, const char *version) +{ + char buffer[128] = {0}; + int buffer_length = 128; + + /* 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; +} + +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); +} + +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); +} + +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); +} + +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); +} + + +int main(int argc, char **argv) +{ + int res = 0; + int cnt = 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)); + + IOT_SetLogLevel(IOT_LOG_DEBUG); + + /* Register Callback */ + IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler); + IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_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_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_INITIALIZE_COMPLETED, user_initialized); + IOT_RegisterCallback(ITE_FOTA, user_fota_event_handler); + IOT_RegisterCallback(ITE_COTA, user_cota_event_handler); + + domain_type = IOTX_CLOUD_REGION_SHANGHAI; + 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 */ + do { + res = IOT_Linkkit_Connect(g_user_example_ctx.master_devid); + if (res < 0) { + EXAMPLE_TRACE("IOT_Linkkit_Connect failed, retry after 5s...\n"); + HAL_SleepMs(5000); + } + } while (res < 0); + + while (1) { + IOT_Linkkit_Yield(EXAMPLE_YIELD_TIMEOUT_MS); + + /* Post Proprety Example */ + if ((cnt % 2) == 0) { + user_post_property(); + } + + /* Post Event Example */ + if ((cnt % 10) == 0) { + user_post_event(); + } + + if (++cnt > 3600) { + break; + } + + HAL_SleepMs(1000); + } + + IOT_Linkkit_Close(g_user_example_ctx.master_devid); + + IOT_DumpMemoryStats(IOT_LOG_DEBUG); + IOT_SetLogLevel(IOT_LOG_NONE); + + return 0; +} + +#endif + diff --git a/iotkit-embedded/src/dev_model/examples/model_for_examples.json b/iotkit-embedded/src/dev_model/examples/model_for_examples.json new file mode 100644 index 0000000..40ab215 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/model_for_examples.json @@ -0,0 +1,201 @@ +{ + "schema":"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json", + "profile":{ + "productKey":"a1pkcDf0Xv0" + }, + "services":[ + { + "outputData":[ + + ], + "identifier":"set", + "inputData":[ + { + "identifier":"PowerSwitch", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"开启" + }, + "type":"bool" + }, + "name":"电源开关" + } + ], + "method":"thing.service.property.set", + "name":"set", + "required":true, + "callType":"async", + "desc":"属性设置" + }, + { + "outputData":[ + { + "identifier":"PowerSwitch", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"开启" + }, + "type":"bool" + }, + "name":"电源开关" + }, + { + "identifier":"Counter", + "dataType":{ + "specs":{ + "min":"0", + "max":"99999", + "step":"1" + }, + "type":"int" + }, + "name":"计数器演示" + } + ], + "identifier":"get", + "inputData":[ + "PowerSwitch", + "Counter" + ], + "method":"thing.service.property.get", + "name":"get", + "required":true, + "callType":"async", + "desc":"属性获取" + }, + { + "outputData":[ + { + "identifier":"Result", + "dataType":{ + "specs":{ + "min":"1", + "max":"10000000", + "step":"1" + }, + "type":"int" + }, + "name":"计算结果" + } + ], + "identifier":"Operation_Service", + "inputData":[ + { + "identifier":"NumberA", + "dataType":{ + "specs":{ + "min":"0", + "max":"1000000", + "step":"1" + }, + "type":"int" + }, + "name":"数值A" + }, + { + "identifier":"NumberB", + "dataType":{ + "specs":{ + "min":"1", + "max":"1000000", + "step":"1" + }, + "type":"int" + }, + "name":"数值B" + } + ], + "method":"thing.service.Operation_Service", + "name":"数值计算服务演示", + "required":false, + "callType":"sync" + } + ], + "properties":[ + { + "identifier":"PowerSwitch", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"开启" + }, + "type":"bool" + }, + "name":"电源开关", + "accessMode":"rw", + "required":false + }, + { + "identifier":"Counter", + "dataType":{ + "specs":{ + "min":"0", + "max":"99999", + "step":"1" + }, + "type":"int" + }, + "name":"计数器演示", + "accessMode":"r", + "required":true + } + ], + "events":[ + { + "outputData":[ + { + "identifier":"PowerSwitch", + "dataType":{ + "specs":{ + "0":"关闭", + "1":"开启" + }, + "type":"bool" + }, + "name":"电源开关" + }, + { + "identifier":"Counter", + "dataType":{ + "specs":{ + "min":"0", + "max":"99999", + "step":"1" + }, + "type":"int" + }, + "name":"计数器演示" + } + ], + "identifier":"post", + "method":"thing.event.property.post", + "name":"post", + "type":"info", + "required":true, + "desc":"属性上报" + }, + { + "outputData":[ + { + "identifier":"ErrorCode", + "dataType":{ + "specs":{ + "0":"故障类型0", + "1":"故障类型1", + "2":"故障类型2" + }, + "type":"enum" + }, + "name":"故障编号" + } + ], + "identifier":"HardwareError", + "method":"thing.event.HardwareError.post", + "name":"故障事件演示", + "type":"error", + "required":false + } + ] +} \ No newline at end of file diff --git a/iotkit-embedded/src/dev_model/examples/solo.c b/iotkit-embedded/src/dev_model/examples/solo.c new file mode 100644 index 0000000..0d6f905 --- /dev/null +++ b/iotkit-embedded/src/dev_model/examples/solo.c @@ -0,0 +1,803 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include +#include +#include +#include + +#include "infra_compat.h" +#include "infra_defs.h" +#include "linkkit_export.h" +/* + * please modify this string follow as product's TSL. + */ +#include "data/solo_tsl.c" + +#define EVENT_ERROR_IDENTIFIER "Error" +#define EVENT_ERROR_OUTPUT_INFO_IDENTIFIER "ErrorCode" + +/* for demo only */ +#define PRODUCT_KEY "a1X2bEnP82z" +#define PRODUCT_SECRET "7jluWm1zql7bt8qK" +#define DEVICE_NAME "test_06" +#define DEVICE_SECRET "wQ1xOzFH3kLdjCTLfi8Xbw4otRz0lHoq" + +void HAL_Printf(const char *fmt, ...); + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while (0) + +typedef struct _sample_context { + const void *thing; + int cloud_connected; + int local_connected; + int thing_enabled; +} sample_context_t; + +void HAL_Free(void *ptr); +uint64_t HAL_UptimeMs(void); +int HAL_SetProductKey(char *product_key); +int HAL_SetDeviceName(char *device_name); +int HAL_SetProductSecret(char *product_secret); +int HAL_SetDeviceSecret(char *device_secret); + +/* + * the callback of linkkit_post_property. + * response_id is compare with the result of linkkit_post_property. + * + */ +void post_property_cb(const void *thing_id, int response_id, int code, + const char *response_message, void *ctx) +{ + EXAMPLE_TRACE("thing@%p: response arrived:\nid:%d\tcode:%d\tmessage:%s\n", + thing_id, response_id, code, + response_message == NULL ? "NULL" : response_message); + + /* do user's post property callback process logical here. */ + + /* ............................... */ + + /* user's post property callback process logical complete */ +} + + +/* connect handle + * cloud and local + */ +#ifdef LOCAL_CONN_ENABLE + static int on_connect(void *ctx, int cloud) +#else + static int on_connect(void *ctx) +#endif +{ + sample_context_t *sample_ctx = ctx; +#ifdef LOCAL_CONN_ENABLE + if (cloud) { + sample_ctx->cloud_connected = 1; + } else { + sample_ctx->local_connected = 1; + } + EXAMPLE_TRACE("%s is connected\n", cloud ? "cloud" : "local"); +#else + sample_ctx->cloud_connected = 1; + EXAMPLE_TRACE("%s is connected\n", "cloud"); +#endif + /* do user's connect process logical here. */ + + /* ............................... */ + + /* user's connect process logical complete */ + + return 0; +} + + +/* disconnect handle + * cloud and local + */ +#ifdef LOCAL_CONN_ENABLE + static int on_disconnect(void *ctx, int cloud) +#else + static int on_disconnect(void *ctx) +#endif +{ + sample_context_t *sample_ctx = ctx; + +#ifdef LOCAL_CONN_ENABLE + if (cloud) { + sample_ctx->cloud_connected = 0; + } else { + sample_ctx->local_connected = 0; + } + EXAMPLE_TRACE("%s is disconnect\n", cloud ? "cloud" : "local"); +#else + sample_ctx->cloud_connected = 0; + EXAMPLE_TRACE("%s is disconnect\n", "cloud"); +#endif + + /* do user's disconnect process logical here. */ + + /* ............................... */ + + /* user's disconnect process logical complete */ + return 0; +} + +/* TODO: */ +/* + * receive raw data handler + */ +static int raw_data_arrived(const void *thing_id, const void *data, int len, + void *ctx) +{ + char raw_data[128] = { 0 }; + + EXAMPLE_TRACE("raw data arrived,len:%d\n", len); + + /* do user's raw data process logical here. */ + + /* ............................... */ + + /* user's raw data process logical complete */ + + /* send result to cloud + * please send your data via raw_data + * example rule: just reply a string to check + */ + snprintf(raw_data, sizeof(raw_data), "test down raw reply data %lld", + (long long)HAL_UptimeMs()); + /* answer raw data handle result */ + linkkit_invoke_raw_service(thing_id, 0, raw_data, strlen(raw_data)); + + return 0; +} + + +/* thing create succuss */ +static int thing_create(const void *thing_id, void *ctx) +{ + sample_context_t *sample_ctx = ctx; + + EXAMPLE_TRACE("new thing@%p created.\n", thing_id); + sample_ctx->thing = thing_id; + + /* do user's thing create process logical here. */ + + /* ............................... */ + + /* user's thing create process logical complete */ + + return 0; +} + + +/* thing enable + * thing is enabled, than it can be communicated + */ +static int thing_enable(const void *thing_id, void *ctx) +{ + sample_context_t *sample_ctx = ctx; + + sample_ctx->thing_enabled = 1; + + /* do user's thing enable process logical here. */ + + /* ............................... */ + + /* user's thing enable process logical complete */ + + return 0; +} + + +/* thing disable + * thing is disable, than it can not be communicated + */ +static int thing_disable(const void *thing_id, void *ctx) +{ + sample_context_t *sample_ctx = ctx; + + sample_ctx->thing_enabled = 0; + + /* do user's thing disable process logical here. */ + + /* ............................... */ + + /* user's thing disable process logical complete */ + + return 0; +} + +/* + * this is the "custom" service handler + * alink method: thing.service.Custom + * please follow TSL modify the idendifier + */ +#ifdef RRPC_ENABLED +static int handle_service_custom(sample_context_t *_sample_ctx, + const void *thing, + const char *service_identifier, int request_id, + int rrpc) +#else +static int handle_service_custom(sample_context_t *_sample_ctx, + const void *thing, + const char *service_identifier, int request_id) +#endif /* RRPC_ENABLED */ +{ + char identifier[128] = { 0 }; + /* + * please follow TSL modify the value type + */ + int transparency_value; + int contrastratio_value; + + /* + * get iutput value. + * compare the service identifier + * please follow user's TSL modify the "transparency". + */ + snprintf(identifier, sizeof(identifier), "%s.%s", service_identifier, + "transparency"); + linkkit_get_value(linkkit_method_get_service_input_value, thing, identifier, + &transparency_value, NULL); + + EXAMPLE_TRACE("identifier: %s value is %d.\n", identifier, + transparency_value); + + /* + * set output value according to user's process result. + * example rule: Contrastratio will changed by transparency. + */ + + /* do user's service process logical here. */ + + /* ............................... */ + + /* user's service process logical complete */ + + + /* + * please follow user's TSL modify the "transparency". + */ + snprintf(identifier, sizeof(identifier), "%s.%s", service_identifier, + "Contrastratio"); + contrastratio_value = transparency_value + 1; + linkkit_set_value(linkkit_method_set_service_output_value, thing, + identifier, &contrastratio_value, NULL); +#ifdef RRPC_ENABLED + linkkit_answer_service(thing, service_identifier, request_id, 200, rrpc); +#else + linkkit_answer_service(thing, service_identifier, request_id, 200); +#endif /* RRPC_ENABLED */ + + return 0; +} + + +/* + * the handler of service which is defined by identifier, not property + * alink method: thing.service.{tsl.service.identifier} + */ +#ifdef RRPC_ENABLED +static int thing_call_service(const void *thing_id, const char *service, + int request_id, int rrpc, void *ctx) +#else +static int thing_call_service(const void *thing_id, const char *service, + int request_id, void *ctx) +#endif /* RRPC_ENABLED */ +{ + sample_context_t *sample_ctx = ctx; + + EXAMPLE_TRACE("service(%s) requested, id: thing@%p, request id:%d\n", + service, thing_id, request_id); + + /* please follow TSL modify the idendifier --- Custom */ + if (strcmp(service, "Custom") == 0) { +#ifdef RRPC_ENABLED + handle_service_custom(sample_ctx, thing_id, service, request_id, rrpc); +#else + handle_service_custom(sample_ctx, thing_id, service, request_id); +#endif /* RRPC_ENABLED */ + } + + return 0; +} + + +/* + * the handler of property changed + * alink method: thing.service.property.set + */ +static int thing_prop_changed(const void *thing_id, const char *property, + void *ctx) +{ + char *value_str = NULL; + char property_buf[64] = { 0 }; + int response_id = -1; + + /* do user's property changed process logical here. */ + + /* ............................... */ + + /* user's property changed process logical complete */ + + + /* + * example: + * property identifier: + * IndoorTemperature + * TemperatureModelStatus + * CurrentTemperature + * + * please follow TSL modify this property identifier + */ + + /* if the proprety id is %s.%s, please follow this code */ + /* get new property value */ + if (strstr(property, "HSVColor") != 0) { + double hue, saturation, value; + + /* generate property identifier HSVColor.Hue */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Hue"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &hue, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + /* generate property identifier HSVColor.Saturation */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, + "Saturation"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &saturation, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + /* generate property identifier HSVColor.Value */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, + "Value"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &value, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + EXAMPLE_TRACE("property(%s), Hue:%f, Saturation:%f, Value:%f\n", + property, hue, saturation, value); + } else if (strstr(property, "HSLColor") != 0) { + double hue, saturation, lightness; + + /* generate property identifier HSLColor.Hue */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Hue"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &hue, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + /* generate property identifier HSLColor.Saturation */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, + "Saturation"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &saturation, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + /* generate property identifier HSLColor.Lightness */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, + "Lightness"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &lightness, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + EXAMPLE_TRACE("property(%s), Hue:%f, Saturation:%f, Lightness:%f\n", + property, hue, saturation, lightness); + } else if (strstr(property, "RGBColor") != 0) { + int red, green, blue; + + /* generate property identifier RGBColor.Red */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Red"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &red, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + /* generate property identifier RGBColor.Green */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, + "Green"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &green, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + /* generate property identifier RGBColor.Blue */ + snprintf(property_buf, sizeof(property_buf), "%s.%s", property, "Blue"); + /* get value by linkkit_get_value */ + linkkit_get_value(linkkit_method_get_property_value, thing_id, + property_buf, &blue, &value_str); + if (value_str) { + HAL_Free(value_str); + value_str = NULL; + } + + EXAMPLE_TRACE("property(%s), Red:%d, Green:%d, Blue:%d\n", property, + red, green, blue); + } + + /* post property + * result is response_id; if response_id = -1, it is fail, else it is + * success. response_id by be compare in post_property_cb. + */ + response_id = linkkit_post_property(thing_id, property, post_property_cb); + + EXAMPLE_TRACE("post property(%s) response id: %d\n", property, response_id); + + return 0; +} + + +/* there is some data transparent transmission by linkkit */ +static int linkit_data_arrived(const void *thing_id, const void *params, + int len, void *ctx) +{ + EXAMPLE_TRACE("thing@%p: masterdev_linkkit_data(%d byte): %s\n", thing_id, + len, (const char *)params); + + /* do user's data arrived process logical here. */ + + /* ............................... */ + + /* user's data arrived process logical complete */ + return 0; +} + +static int is_active(sample_context_t *sample_ctx) +{ +#ifdef LOCAL_CONN_ENABLE + return (sample_ctx->cloud_connected /* && sample_ctx->thing_enabled*/) || + (sample_ctx->local_connected /* && sample_ctx->thing_enabled*/); +#else + return sample_ctx->cloud_connected /* && sample_ctx->thing_enabled*/; +#endif +} + +#ifdef POST_WIFI_STATUS + +typedef struct { + char *band; + int channel; + int rssi; + int snr; + char mac[6]; + int tx_rate; + int rx_rate; +} user_wireless_info_t; + +static user_wireless_info_t example_wireless_info = { + .band = 0, + .channel = 1, + .rssi = -30, + .snr = 30, + .mac = {0x18, 0xFE, 0x34, 0x12, 0x34, 0x56}, + .tx_rate = 1, + .rx_rate = 1, +}; + +static int get_wireless_info(user_wireless_info_t *wireless_info) +{ + if (wireless_info) { + memcpy(wireless_info, &example_wireless_info, sizeof(user_wireless_info_t)); + } + + return 0; +} + +static int post_property_wifi_status_once(sample_context_t *sample_ctx) +{ + int ret = -1; + int i = 0; + static int is_post = 0; + char val_buf[32]; + uint8_t bssid[ETH_ALEN]; + user_wireless_info_t wireless_info; + + char *band = NULL; + int channel = 0; + int rssi = 0; + int snr = 0; + int tx_rate = 0; + int rx_rate = 0; + + if (is_active(sample_ctx) && 0 == is_post) { + get_wireless_info(&wireless_info); +#ifdef WIFI_PROVISION_ENABLED + HAL_Wifi_Get_Ap_Info(NULL, NULL, bssid); +#endif + + band = wireless_info.band == 0 ? "2.4G" : "5G"; + channel = wireless_info.channel; + rssi = wireless_info.rssi; + snr = wireless_info.snr; + tx_rate = wireless_info.tx_rate; + rx_rate = wireless_info.rx_rate; + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WIFI_Band", band, NULL); + linkkit_post_property(sample_ctx->thing, "WIFI_Band", post_property_cb); + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WIFI_Channel", &channel, NULL); + linkkit_post_property(sample_ctx->thing, "WIFI_Channel", + post_property_cb); + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WiFI_RSSI", &rssi, NULL); + linkkit_post_property(sample_ctx->thing, "WiFI_RSSI", post_property_cb); + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WiFI_SNR", &snr, NULL); + linkkit_post_property(sample_ctx->thing, "WiFI_SNR", post_property_cb); + + memset(val_buf, 0, sizeof(val_buf)); + for (i = 0; i < ETH_ALEN; i++) { + snprintf(val_buf + strlen(val_buf), + sizeof(val_buf) - strlen(val_buf), "%c:", bssid[i]); + } + if (strlen(val_buf) > 0 && val_buf[strlen(val_buf) - 1] == ':') { + val_buf[strlen(val_buf) - 1] = '\0'; + } + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WIFI_AP_BSSID", val_buf, NULL); + linkkit_post_property(sample_ctx->thing, "WIFI_AP_BSSID", + post_property_cb); + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WIFI_Tx_Rate", &tx_rate, NULL); + linkkit_post_property(sample_ctx->thing, "WIFI_Tx_Rate", + post_property_cb); + + linkkit_set_value(linkkit_method_set_property_value, sample_ctx->thing, + "WIFI_Rx_Rate", &rx_rate, NULL); + linkkit_post_property(sample_ctx->thing, "WIFI_Rx_Rate", + post_property_cb); + + is_post = 1; + ret = 0; + } + return ret; +} +#endif + + +static unsigned long long uptime_sec(void) +{ + static unsigned long long start_time = 0; + + if (start_time == 0) { + start_time = HAL_UptimeMs(); + } + + return (HAL_UptimeMs() - start_time) / 1000; +} + + +int post_all_prop(sample_context_t *sample) +{ + /* demo for post all property */ + return linkkit_post_property(sample->thing, NULL, post_property_cb); +} + + +int trigger_event(sample_context_t *sample) +{ + char event_output_identifier[64]; + int errorCode = 0; + snprintf(event_output_identifier, sizeof(event_output_identifier), "%s.%s", + EVENT_ERROR_IDENTIFIER, EVENT_ERROR_OUTPUT_INFO_IDENTIFIER); + + + linkkit_set_value(linkkit_method_set_event_output_value, sample->thing, + event_output_identifier, &errorCode, NULL); + + return linkkit_trigger_event(sample->thing, EVENT_ERROR_IDENTIFIER, + post_property_cb); +} + +#ifdef EXTENDED_INFO_ENABLED +int trigger_deviceinfo(sample_context_t *sample) +{ + /* please modify the parameter */ + return linkkit_trigger_extended_info_operate( + sample->thing, "[{device_info : 21}]", + linkkit_extended_info_operate_update); +} +#endif + +void ntp_time_reply(const char *offset_time) +{ + EXAMPLE_TRACE("ntp time: %s\n", offset_time); +} + + +int linkkit_example() +{ + sample_context_t sample_ctx = { 0 }; + int exit = 0; + int cnt = 0; + unsigned long long now = 0; + unsigned long long prev_sec = 0; + int get_tsl_from_cloud = 0; /* the param of whether it is get tsl from cloud */ + + linkkit_ops_t linkkit_ops = { + .on_connect = on_connect, /* connect handler */ + .on_disconnect = on_disconnect, /* disconnect handler */ + .raw_data_arrived = raw_data_arrived, /* receive raw data handler */ + .thing_create = thing_create, /* thing created handler */ + .thing_enable = thing_enable, /* thing enabled handler */ + .thing_disable = thing_disable, /* thing disabled handler */ + .thing_call_service = thing_call_service, /* self-defined service handler */ + .thing_prop_changed = thing_prop_changed, /* property set handler */ + .linkit_data_arrived = linkit_data_arrived, /* transparent transmission data handler */ + }; + + EXAMPLE_TRACE("linkkit start"); + + /* + * linkkit start + * max_buffered_msg = 16, set the handle msg max numbers. + * if it is enough memory, this number can be set bigger. + * if get_tsl_from_cloud = 0, it will use the default tsl [TSL_STRING]; if + * get_tsl_from_cloud =1, it will get tsl from cloud. + */ + if (-1 == linkkit_start(16, get_tsl_from_cloud, linkkit_loglevel_debug, + &linkkit_ops, linkkit_cloud_domain_shanghai, + &sample_ctx)) { + EXAMPLE_TRACE("linkkit start fail"); + return -1; + } + + if (!get_tsl_from_cloud) { + /* + * if get_tsl_from_cloud = 0, set default tsl [TSL_STRING] + * please modify TSL_STRING by the TSL's defined. + */ + linkkit_set_tsl(TSL_STRING, strlen(TSL_STRING)); + } + + EXAMPLE_TRACE("linkkit enter loop"); + while (!linkkit_is_try_leave()) { + /* + * if linkkit is support Multi-thread, the linkkit_dispatch and + * linkkit_yield with callback by linkkit, else it need user to call + * these function to received data. + */ +#if (CONFIG_SDK_THREAD_COST == 0) + linkkit_yield(100); + if (++cnt % 10 == 0) { + EXAMPLE_TRACE("."); + cnt = 0; + } + linkkit_dispatch(); +#else + HAL_SleepMs(100); +#endif /* CONFIG_SDK_THREAD_COST */ + now = uptime_sec(); + if (prev_sec == now) { + continue; + } + + /* + * do user's process logical here. + * example rule: + * about 10 seconds, assume trigger post wifi property event about + * every 10s. about 30 seconds, assume trigger post property event about + * every 30s. + * + * please follow user's rule to modify these code. + */ + + /* Manually Trigger Config OTA */ + /* if (now % 10 == 0) { + linkkit_invoke_cota_get_config("product","file","",NULL); + } */ + +#ifdef POST_WIFI_STATUS + if (now % 10 == 0) { + linkkit_ntp_time_request(ntp_time_reply); + post_property_wifi_status_once(&sample_ctx); + } +#endif + if (now % 30 == 0 && is_active(&sample_ctx)) { + linkkit_ntp_time_request(ntp_time_reply); + post_all_prop(&sample_ctx); + } + + if (now % 45 == 0 && is_active(&sample_ctx)) { + linkkit_ntp_time_request(ntp_time_reply); + trigger_event(&sample_ctx); + } + +#ifdef EXTENDED_INFO_ENABLED + if (now % 50 == 0 && is_active(&sample_ctx)) { + linkkit_ntp_time_request(ntp_time_reply); + trigger_deviceinfo(&sample_ctx); + } +#endif + + if (exit) { + break; + } + + /* after all, this is an sample, give a chance to return... */ + /* modify this value for this sample executaion time period */ + +#if 0 + if (now > 60 * execution_time) { + exit = 1; + } +#endif + + prev_sec = now; + } + + /* linkkit end */ + linkkit_end(); + return 0; +} + +void set_iotx_info() +{ + HAL_SetProductKey(PRODUCT_KEY); + HAL_SetProductSecret(PRODUCT_SECRET); + HAL_SetDeviceName(DEVICE_NAME); + HAL_SetDeviceSecret(DEVICE_SECRET); +} + +int main(int argc, char *argv[]) +{ +#if !defined(WIFI_PROVISION_ENABLED) || !defined(BUILD_AOS) + set_iotx_info(); +#endif + + EXAMPLE_TRACE("start!\n"); + /* + * linkkit demo + * please check document: https://help.aliyun.com/document_detail/73708.html + * API introduce: https://help.aliyun.com/document_detail/68687.html + */ + linkkit_example(); + + IOT_DumpMemoryStats(IOT_LOG_DEBUG); + + EXAMPLE_TRACE("out of sample!\n"); + + return 0; +} diff --git a/iotkit-embedded/src/dev_model/impl_linkkit.c b/iotkit-embedded/src/dev_model/impl_linkkit.c new file mode 100644 index 0000000..fec9787 --- /dev/null +++ b/iotkit-embedded/src/dev_model/impl_linkkit.c @@ -0,0 +1,1632 @@ +/* + * 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 + +#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; + 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; + + HAL_SetProductKey(meta_info->product_key); + HAL_SetProductSecret(meta_info->product_secret); + HAL_SetDeviceName(meta_info->device_name); + HAL_SetDeviceSecret(meta_info->device_secret); + + /* 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 + +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; + } + } + 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; + } + + 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 +} + +#ifdef DEVICE_MODEL_GATEWAY +int iot_linkkit_subdev_query_id(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]) +{ + int res = -1; + iotx_linkkit_ctx_t *ctx = _iotx_linkkit_get_ctx(); + + if (ctx->is_opened == 0) { + return res; + } + + iotx_dm_subdev_query(product_key, device_name, &res); + return res; +} +#endif /* #ifdef DEVICE_MODEL_GATEWAY */ + +#endif diff --git a/iotkit-embedded/src/dev_model/iot.mk b/iotkit-embedded/src/dev_model/iot.mk new file mode 100644 index 0000000..ab77f05 --- /dev/null +++ b/iotkit-embedded/src/dev_model/iot.mk @@ -0,0 +1,27 @@ +LIBA_TARGET := libiot_alink.a + +HDR_REFS += src/infra +HDR_REFS += src/mqtt +HDR_REFS += src/dev_sign + +DEPENDS += wrappers +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +LIB_SRCS_PATTERN := *.c server/*.c client/*.c deprecated/*.c + +LIB_SRCS_EXCLUDE := examples/linkkit_example_solo.c examples/cJSON.c +SRCS_linkkit-example-solo := examples/linkkit_example_solo.c examples/cJSON.c + +LIB_SRCS_EXCLUDE += examples/linkkit_example_gateway.c examples/cJSON.c +SRCS_linkkit-example-gateway := examples/linkkit_example_gateway.c examples/cJSON.c + +$(call Append_Conditional, LIB_SRCS_PATTERN, alcs/*.c, ALCS_ENABLED) + +ifneq (,$(filter -DDEPRECATED_LINKKIT,$(CFLAGS))) +$(call Append_Conditional, TARGET, linkkit-example-solo, DEVICE_MODEL_ENABLED, BUILD_AOS NO_EXECUTABLES DEVICE_MODEL_GATEWAY) +$(call Append_Conditional, TARGET, linkkit-example-gateway, DEVICE_MODEL_ENABLED DEVICE_MODEL_GATEWAY, BUILD_AOS NO_EXECUTABLES) +else +$(call Append_Conditional, TARGET, linkkit-example-solo, DEVICE_MODEL_ENABLED, BUILD_AOS NO_EXECUTABLES) +$(call Append_Conditional, TARGET, linkkit-example-gateway, DEVICE_MODEL_GATEWAY, BUILD_AOS NO_EXECUTABLES) +endif + diff --git a/iotkit-embedded/src/dev_model/iotx_cm.c b/iotkit-embedded/src/dev_model/iotx_cm.c new file mode 100644 index 0000000..9ebfe13 --- /dev/null +++ b/iotkit-embedded/src/dev_model/iotx_cm.c @@ -0,0 +1,310 @@ +#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--; + } + + if (inited_conn_num == 0) { +#ifdef DEVICE_MODEL_GATEWAY + while (!yield_task_leave) { + HAL_SleepMs(10); + } + if (yield_thread != NULL) { + 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/iotkit-embedded/src/dev_model/iotx_cm.h b/iotkit-embedded/src/dev_model/iotx_cm.h new file mode 100644 index 0000000..877b103 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/iotx_cm_coap.c b/iotkit-embedded/src/dev_model/iotx_cm_coap.c new file mode 100644 index 0000000..10a2466 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/iotx_cm_coap.h b/iotkit-embedded/src/dev_model/iotx_cm_coap.h new file mode 100644 index 0000000..9d664b3 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/iotx_cm_internal.h b/iotkit-embedded/src/dev_model/iotx_cm_internal.h new file mode 100644 index 0000000..ca9fccd --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/iotx_cm_mqtt.c b/iotkit-embedded/src/dev_model/iotx_cm_mqtt.c new file mode 100644 index 0000000..2626b8f --- /dev/null +++ b/iotkit-embedded/src/dev_model/iotx_cm_mqtt.c @@ -0,0 +1,411 @@ +#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; + } + memset(_mqtt_conncection, 0, sizeof(iotx_cm_connection_t)); + + 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; + } + memset(mqtt_param, 0, sizeof(iotx_mqtt_param_t)); + + _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; + } +} + +extern sdk_impl_ctx_t g_sdk_impl_ctx; +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)); + + if (g_sdk_impl_ctx.mqtt_customzie_info) { + ((iotx_mqtt_param_t *)_mqtt_conncection->open_params)->customize_info = g_sdk_impl_ctx.mqtt_customzie_info; + } + + 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/iotkit-embedded/src/dev_model/iotx_cm_mqtt.h b/iotkit-embedded/src/dev_model/iotx_cm_mqtt.h new file mode 100644 index 0000000..90b4289 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/iotx_dm.h b/iotkit-embedded/src/dev_model/iotx_dm.h new file mode 100644 index 0000000..c5ade51 --- /dev/null +++ b/iotkit-embedded/src/dev_model/iotx_dm.h @@ -0,0 +1,289 @@ +/* + * 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_query(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], + _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], + _OU_ int *devid); +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/iotkit-embedded/src/dev_model/iotx_dm_config.h b/iotkit-embedded/src/dev_model/iotx_dm_config.h new file mode 100644 index 0000000..7920fa5 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/iotx_dm_internal.h b/iotkit-embedded/src/dev_model/iotx_dm_internal.h new file mode 100644 index 0000000..b527fc9 --- /dev/null +++ b/iotkit-embedded/src/dev_model/iotx_dm_internal.h @@ -0,0 +1,124 @@ +/* + * 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 + +#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/iotkit-embedded/src/dev_model/iotx_log_report.h b/iotkit-embedded/src/dev_model/iotx_log_report.h new file mode 100644 index 0000000..dde32ee --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_model/server/dm_server.c b/iotkit-embedded/src/dev_model/server/dm_server.c new file mode 100644 index 0000000..5735d9f --- /dev/null +++ b/iotkit-embedded/src/dev_model/server/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/iotkit-embedded/src/dev_model/server/dm_server.h b/iotkit-embedded/src/dev_model/server/dm_server.h new file mode 100644 index 0000000..2ada978 --- /dev/null +++ b/iotkit-embedded/src/dev_model/server/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/iotkit-embedded/src/dev_model/server/dm_server_adapter.c b/iotkit-embedded/src/dev_model/server/dm_server_adapter.c new file mode 100644 index 0000000..dc82770 --- /dev/null +++ b/iotkit-embedded/src/dev_model/server/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/iotkit-embedded/src/dev_model/server/dm_server_adapter.h b/iotkit-embedded/src/dev_model/server/dm_server_adapter.h new file mode 100644 index 0000000..bfb49a7 --- /dev/null +++ b/iotkit-embedded/src/dev_model/server/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/iotkit-embedded/src/dev_reset/dev_reset.c b/iotkit-embedded/src/dev_reset/dev_reset.c new file mode 100644 index 0000000..59c89b8 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_reset/dev_reset_api.h b/iotkit-embedded/src/dev_reset/dev_reset_api.h new file mode 100644 index 0000000..fed5379 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_reset/dev_reset_internal.h b/iotkit-embedded/src/dev_reset/dev_reset_internal.h new file mode 100644 index 0000000..8899e5d --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_reset/dev_reset_wrapper.h b/iotkit-embedded/src/dev_reset/dev_reset_wrapper.h new file mode 100644 index 0000000..f1d09a5 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_reset/examples/dev_reset_example.c b/iotkit-embedded/src/dev_reset/examples/dev_reset_example.c new file mode 100644 index 0000000..b954019 --- /dev/null +++ b/iotkit-embedded/src/dev_reset/examples/dev_reset_example.c @@ -0,0 +1,82 @@ +#include +#include +#include "mqtt_api.h" +#include "dev_reset_api.h" + +void HAL_Printf(const char *fmt, ...); +int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]); +int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]); + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while(0) + +static int reset_mqtt_packet_id = 0; +static int reset_reply_received = 0; + +void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) +{ + EXAMPLE_TRACE("msg->event_type : %d", msg->event_type); +} + +void example_devrst_evt_handle(iotx_devrst_evt_type_t evt, void *msg) +{ + switch (evt) + { + case IOTX_DEVRST_EVT_RECEIVED: { + iotx_devrst_evt_recv_msg_t *recv_msg = (iotx_devrst_evt_recv_msg_t *)msg; + if (recv_msg->msgid != reset_mqtt_packet_id) { + return; + } + EXAMPLE_TRACE("Receive Reset Responst"); + EXAMPLE_TRACE("Msg ID: %d", recv_msg->msgid); + EXAMPLE_TRACE("Payload: %.*s", recv_msg->payload_len, recv_msg->payload); + reset_reply_received = 1; + } + break; + + default: + break; + } +} + +int main(int argc, char *argv[]) +{ + int res = 0; + void *pclient = NULL; + iotx_dev_meta_info_t meta_info; + iotx_mqtt_param_t mqtt_params; + + memset(&mqtt_params, 0, sizeof(iotx_mqtt_param_t)); + memset(&meta_info, 0, sizeof(iotx_dev_meta_info_t)); + + HAL_GetProductKey(meta_info.product_key); + HAL_GetDeviceName(meta_info.device_name); + + mqtt_params.handle_event.h_fp = example_event_handle; + + pclient = IOT_MQTT_Construct(&mqtt_params); + if (NULL == pclient) { + EXAMPLE_TRACE("MQTT construct failed"); + return -1; + } + + res = IOT_DevReset_Report(&meta_info, example_devrst_evt_handle, NULL); + if (res < 0) { + return -1; + } + reset_mqtt_packet_id = res; + + while (!reset_reply_received) { + + IOT_MQTT_Yield(pclient, 200); + } + + EXAMPLE_TRACE("Example Execute Success, Now Exit..."); + + return 0; +} + diff --git a/iotkit-embedded/src/dev_reset/iot.mk b/iotkit-embedded/src/dev_reset/iot.mk new file mode 100644 index 0000000..c1a3219 --- /dev/null +++ b/iotkit-embedded/src/dev_reset/iot.mk @@ -0,0 +1,11 @@ +LIBA_TARGET := libiot_reset.a + +HDR_REFS := src/infra src/mqtt + +DEPENDS += wrappers +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +LIB_SRCS_EXCLUDE += examples/dev_reset_example.c +SRCS_dev-reset-example := examples/dev_reset_example.c + +$(call Append_Conditional, TARGET, dev-reset-example, DEV_RESET, BUILD_AOS NO_EXECUTABLES) diff --git a/iotkit-embedded/src/dev_sign/dev_sign_api.h b/iotkit-embedded/src/dev_sign/dev_sign_api.h new file mode 100644 index 0000000..9b56c17 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_sign/dev_sign_config.h b/iotkit-embedded/src/dev_sign/dev_sign_config.h new file mode 100644 index 0000000..1da42ad --- /dev/null +++ b/iotkit-embedded/src/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 (128) +#define DEV_SIGN_CLIENT_ID_MAXLEN (200) +#define DEV_SIGN_USERNAME_MAXLEN (64) +#define DEV_SIGN_PASSWORD_MAXLEN (65) + +#endif + diff --git a/iotkit-embedded/src/dev_sign/dev_sign_internal.h b/iotkit-embedded/src/dev_sign/dev_sign_internal.h new file mode 100644 index 0000000..6487527 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dev_sign/dev_sign_mqtt.c b/iotkit-embedded/src/dev_sign/dev_sign_mqtt.c new file mode 100644 index 0000000..09fac78 --- /dev/null +++ b/iotkit-embedded/src/dev_sign/dev_sign_mqtt.c @@ -0,0 +1,237 @@ +#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" +#define MODE_ITLS_DNS_ID2 "8" + +#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 + }, + { + "_v", "sdk-c-"IOTX_SDK_VERSION + }, + { + "securemode", SECURE_MODE + }, + { + "signmethod", "hmacsha256" + }, + { + "lan", "C" + }, +#if defined(DEVICE_MODEL_ENABLED) && !defined(DEVICE_MODEL_CLASSIC) + { + "v", IOTX_ALINK_VERSION + }, +#else + { + "gw", "0" + }, + { + "ext", "0" + }, +#endif +}; + +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, const char *custom_kv, uint8_t enable_itls) +{ + 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); + + if (enable_itls > 0) { + clientid_kv[2][1] = MODE_ITLS_DNS_ID2; + } + else { + clientid_kv[2][1] = SECURE_MODE; + } + + 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); + } + + if (custom_kv != NULL) { + if ((strlen(clientid_string) + strlen(custom_kv) + 1) >= DEV_SIGN_CLIENT_ID_MAXLEN) { + return FAIL_RETURN; + } + memcpy(clientid_string + strlen(clientid_string), custom_kv, strlen(custom_kv)); + 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; +} + +static char* rt_strlwr(char *str) +{ + if(str == NULL) + return NULL; + + char *p = str; + while (*p != '\0') + { + if(*p >= 'A' && *p <= 'Z') + *p = (*p) + 0x20; + p++; + } + return str; +} + +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, NULL, 0) != 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])); + } + rt_strlwr(signout->hostname); + rt_kprintf("host name:%s\r\n", signout->hostname); + + /* 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/iotkit-embedded/src/dev_sign/dev_sign_wrapper.h b/iotkit-embedded/src/dev_sign/dev_sign_wrapper.h new file mode 100644 index 0000000..c3520e6 --- /dev/null +++ b/iotkit-embedded/src/dev_sign/dev_sign_wrapper.h @@ -0,0 +1,4 @@ + + +#include "infra_types.h" +#include "infra_defs.h" diff --git a/iotkit-embedded/src/dev_sign/examples/dev_sign_example.c b/iotkit-embedded/src/dev_sign/examples/dev_sign_example.c new file mode 100644 index 0000000..fba4932 --- /dev/null +++ b/iotkit-embedded/src/dev_sign/examples/dev_sign_example.c @@ -0,0 +1,63 @@ +#include "dev_sign_api.h" + +#define EXAMPLE_PRODUCT_KEY "a1X2bEnP82z" +#define EXAMPLE_PRODUCT_SECRET "7jluWm1zql7bt8qK" +#define EXAMPLE_DEVICE_NAME "example1" +#define EXAMPLE_DEVICE_SECRET "ga7XA6KdlEeiPXQPpRbAjOZXwG8ydgSe" + +/* Implenment this HAL or using "printf" of your own system if you want to print something in example*/ +void HAL_Printf(const char *fmt, ...); + +int main(int argc, char *argv[]) +{ + iotx_mqtt_region_types_t region = IOTX_CLOUD_REGION_SHANGHAI; + iotx_dev_meta_info_t meta; + iotx_sign_mqtt_t sign_mqtt; + + memset(&meta, 0, sizeof(iotx_dev_meta_info_t)); + memcpy(meta.product_key, EXAMPLE_PRODUCT_KEY, strlen(EXAMPLE_PRODUCT_KEY)); + memcpy(meta.product_secret, EXAMPLE_PRODUCT_SECRET, strlen(EXAMPLE_PRODUCT_SECRET)); + memcpy(meta.device_name, EXAMPLE_DEVICE_NAME, strlen(EXAMPLE_DEVICE_NAME)); + memcpy(meta.device_secret, EXAMPLE_DEVICE_SECRET, strlen(EXAMPLE_DEVICE_SECRET)); + + if (IOT_Sign_MQTT(region, &meta, &sign_mqtt) < 0) { + return -1; + } + +#if 1 /* Uncomment this if you want to show more information */ + HAL_Printf("sign_mqtt.hostname: %s\n", sign_mqtt.hostname); + HAL_Printf("sign_mqtt.port : %d\n", sign_mqtt.port); + HAL_Printf("sign_mqtt.username: %s\n", sign_mqtt.username); + HAL_Printf("sign_mqtt.password: %s\n", sign_mqtt.password); + HAL_Printf("sign_mqtt.clientid: %s\n", sign_mqtt.clientid); +#endif + + /* + * Then you can pass this output parameter to MQTT connect APIs to establish connection + * + * e.g. + * + * memset(&mqtt_params, 0x0, sizeof(mqtt_params)); + * + * mqtt_params.port = sign_mqtt.port; + * mqtt_params.host = sign_mqtt.hostname; + * mqtt_params.client_id = sign_mqtt.clientid; + * mqtt_params.username = sign_mqtt.username; + * mqtt_params.password = sign_mqtt.password; + * + * mqtt_params.request_timeout_ms = 2000; + * mqtt_params.clean_session = 0; + * mqtt_params.keepalive_interval_ms = 60000; + * mqtt_params.read_buf_size = 1024; + * mqtt_params.write_buf_size = 1024; + * + * mqtt_params.handle_event.h_fp = example_event_handle; + * mqtt_params.handle_event.pcontext = NULL; + * + * pclient = IOT_MQTT_Construct(&mqtt_params); + * + */ + + return 0; +} + diff --git a/iotkit-embedded/src/dev_sign/iot.mk b/iotkit-embedded/src/dev_sign/iot.mk new file mode 100644 index 0000000..09398a5 --- /dev/null +++ b/iotkit-embedded/src/dev_sign/iot.mk @@ -0,0 +1,14 @@ +LIBA_TARGET := libiot_sign.a + +HDR_REFS := src/infra + +DEPENDS += wrappers +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +DEPENDS += external_libs/mbedtls + +LIB_SRCS_EXCLUDE := examples/dev_sign_example.c +SRCS_dev-sign-example += examples/dev_sign_example.c + +$(call Append_Conditional, TARGET, dev-sign-example, DEV_SIGN, BUILD_AOS NO_EXECUTABLES) + diff --git a/iotkit-embedded/src/dm/CMakeLists.txt b/iotkit-embedded/src/dm/CMakeLists.txt deleted file mode 100644 index 6d1fe06..0000000 --- a/iotkit-embedded/src/dm/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -file(GLOB C_SOURCES "src/*.c") -add_library(dm STATIC ${C_SOURCES}) - -target_link_libraries(dm iot_sdk) diff --git a/iotkit-embedded/src/dm/include/cJSON.h b/iotkit-embedded/src/dm/include/cJSON.h deleted file mode 100644 index 524e817..0000000 --- a/iotkit-embedded/src/dm/include/cJSON.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - 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 6 -#define CJSON_VERSION_PATCH 0 - -#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; -#ifdef CJSON_STRING_ZEROCOPY - size_t valuestring_length; -#endif - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char* string; -#ifdef CJSON_STRING_ZEROCOPY - size_t string_length; -#endif - /* The item's number, if type==cJSON_Number */ - double valuedouble; -} cJSON; - -typedef struct cJSON_Hooks { - void* (*malloc_fn)(size_t sz); - void (*free_fn)(void* ptr); -} cJSON_Hooks; - -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); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - -/* 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); -/* 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 so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON*) cJSON_ParseWithOpts(const char* value, const char** return_parse_end, - cJSON_bool require_null_terminated); - -/* 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); - - -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/iotkit-embedded/src/dm/include/cmp_abstract_impl.h b/iotkit-embedded/src/dm/include/cmp_abstract_impl.h deleted file mode 100644 index a4be119..0000000 --- a/iotkit-embedded/src/dm/include/cmp_abstract_impl.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef CMP_ABSTRACT_IMPL_H -#define CMP_ABSTRACT_IMPL_H - -#include "interface/cmp_abstract.h" - -#include "iot_import.h" -#include "iot_export_errno.h" -#include "iot_export_cmp.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "dm_import.h" - -#define CMP_ABSTRACT_IMPL_CLASS get_cmp_impl_class() - -typedef struct { - const void* _; - int cmp_inited; -} cmp_abstract_impl_t; - -extern const void* get_cmp_impl_class(); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CMP_ABSTRACT_IMPL_H */ diff --git a/iotkit-embedded/src/dm/include/cmp_message_info.h b/iotkit-embedded/src/dm/include/cmp_message_info.h deleted file mode 100644 index f6023c0..0000000 --- a/iotkit-embedded/src/dm/include/cmp_message_info.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef CMP_MESSAGE_INFO_H -#define CMP_MESSAGE_INFO_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "interface/message_info_abstract.h" -#include "interface/log_abstract.h" -#include "dm_import.h" - -#define CMP_MESSAGE_INFO_CLASS get_cmp_message_info_class() -#define CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX 1200 - -#define CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST 0 -#define CMP_MESSAGE_INFO_MESSAGE_TYPE_RESPONSE 1 -#define CMP_MESSAGE_INFO_MESSAGE_TYPE_RAW 2 - -typedef struct _req_rsp_param { - char* key; - char* value; -} req_rsp_param_t; - -typedef struct { - const void* _; - char* uri; - char* payload_buf; - char* params_data_buf; -#ifdef MEMORY_NO_COPY - int params_data_buf_prefix_len; -#endif - char* raw_data_buf; - int raw_data_length; - char* product_key; - char* device_name; - int id; - int code; - char* version; - void* param_list; - char* method; - int message_type; /* 0: request; 1: response; 2: raw. */ - int ret; -} cmp_message_info_t; - -extern const void* get_cmp_message_info_class(); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CMP_MESSAGE_INFO_H */ diff --git a/iotkit-embedded/src/dm/include/dm_import.h b/iotkit-embedded/src/dm/include/dm_import.h deleted file mode 100644 index b5f1aca..0000000 --- a/iotkit-embedded/src/dm/include/dm_import.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef DM_IMPORT_H -#define DM_IMPORT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include -#include - -#define DM_MODULE_NAME "dm" - -#ifdef ESP8266 -#include "esp_common.h" - -#define dm_printf os_printf -#define dm_sprintf os_sprintf -#define dm_snprintf os_snprintf -#define __DM_READ_ONLY__ ICACHE_RODATA_ATTR STORE_ATTR -#else -#define dm_printf printf -#define dm_sprintf sprintf -#define dm_snprintf snprintf -#define __DM_READ_ONLY__ -#endif - -void* dm_lite_malloc(size_t size); -void* dm_lite_calloc(size_t nmemb, size_t size); -void dm_lite_free_func(void* ptr); -void dm_lite_free(void* ptr); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* DM_IMPORT_H */ diff --git a/iotkit-embedded/src/dm/include/dm_thing.h b/iotkit-embedded/src/dm/include/dm_thing.h deleted file mode 100644 index 06c49a9..0000000 --- a/iotkit-embedded/src/dm/include/dm_thing.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef DM_THING_H -#define DM_THING_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "interface/thing_abstract.h" -#include "interface/log_abstract.h" -#include "dsl.h" - -#define DEFAULT_DSL_DELIMITER '.' -#define MAX_IDENTIFIER_LENGTH (50+1) /* user input max id lengh is 50 characters. */ - -#define DM_THING_CLASS get_dm_thing_class() - -void property_iterator(void* _self, handle_item_t handle_fp, ...); -void event_iterator(void* _self, handle_item_t handle_fp, ...); -void service_iterator(void* _self, handle_item_t handle_fp, ...); - -typedef struct { - const void* _; - char* _name; /* dm thing object name. */ - char* _dsl_string; /* dsl string from yun or customer input. */ - size_t _dsl_string_length; - void* _json_object; /* json object after dsl string parsed. */ - dsl_template_t dsl_template; - int _arr_index; -} dm_thing_t; - -extern const void* get_dm_thing_class(); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* DM_THING_H */ diff --git a/iotkit-embedded/src/dm/include/dm_thing_manager.h b/iotkit-embedded/src/dm/include/dm_thing_manager.h deleted file mode 100644 index 39af7e2..0000000 --- a/iotkit-embedded/src/dm/include/dm_thing_manager.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef DM_THING_MANAGER_H -#define DM_THING_MANAGER_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "interface/thing_abstract.h" -#include "interface/thing_manager_abstract.h" -#include "interface/log_abstract.h" -#include "interface/list_abstract.h" -#include "dm_import.h" -#include "iot_export.h" -#include "iot_export_cmp.h" -#include "iot_import.h" - -#define DM_THING_MANAGER_CLASS get_dm_thing_manager_class() -#define DM_LOCAL_THING_NAME_PATTERN "lthing_%d" -#define DM_REQUEST_VERSION_STRING "1.0" - -#define METHOD_NAME_SUB_REGISTER "thing/sub/register" -#define METHOD_NAME_SUB_REGISTER_REPLY "thing/sub/register_reply" -#define METHOD_NAME_SUB_UNREGISTER "thing/sub/unregister" -#define METHOD_NAME_SUB_UNREGISTER_REPLY "thing/sub/unregister_reply" -#define METHOD_NAME_LOGIN "thing/login" -#define METHOD_NAME_LOGIN_REPLY "thing/login_reply" -#define METHOD_NAME_LOGOUT "thing/logout" -#define METHOD_NAME_LOGOUT_REPLY "thing/logout_reply" -#define METHOD_NAME_TOPO_ADD "thing/topo/add" -#define METHOD_NAME_TOPO_ADD_REPLY "thing/topo/add_reply" -#define METHOD_NAME_TOPO_DEL "thing/topo/delete" -#define METHOD_NAME_TOPO_DEL_REPLY "thing/topo/delete_reply" -#define METHOD_NAME_THING_ENABLE "thing/enable" -#define METHOD_NAME_THING_ENABLE_REPLY "thing/enable_reply" -#define METHOD_NAME_THING_DELETE "thing/delete" -#define METHOD_NAME_THING_DELETE_REPLY "thing/delete_reply" -#define METHOD_NAME_THING_DISABLE "thing/disable" -#define METHOD_NAME_THING_DISABLE_REPLY "thing/disable_reply" -#define METHOD_NAME_THING_DSL_POST "thing/keyelement/post" -#define METHOD_NAME_THING_DSL_POST_REPLY "thing/keyelement/post_reply" -#define METHOD_NAME_THING_DSL_GET "thing/dsltemplate/get" -#define METHOD_NAME_THING_DSL_GET_REPLY "thing/dsltemplate/get_reply" -#define METHOD_NAME_PROPERTY_POST "thing/event/property/post" -#define METHOD_NAME_PROPERTY_POST_REPLY "thing/event/property/post_reply" -#define METHOD_NAME_PROPERTY_SET "thing/service/property/set" -#define METHOD_NAME_PROPERTY_SET_REPLY "thing/service/property/set_reply" -#define METHOD_NAME_PROPERTY_GET "thing/service/property/get" -#define METHOD_NAME_PROPERTY_GET_REPLY "thing/service/property/get_reply" -#define METHOD_NAME_DOWN_RAW "thing/model/down_raw" -#define METHOD_NAME_DOWN_RAW_PEPLY "thing/model/down_raw_reply" -#define METHOD_NAME_UP_RAW "thing/model/up_raw" -#define METHOD_NAME_UP_RAW_REPLY "thing/model/up_raw_reply" -#ifdef DEVICEINFO_ENABLED -#define METHOD_NAME_DEVICEINFO_UPDATE "thing/deviceinfo/update" -#define METHOD_NAME_DEVICEINFO_UPDATE_REPLY "thing/deviceinfo/update_reply" -#define METHOD_NAME_DEVICEINFO_DELETE "thing/deviceinfo/delete" -#define METHOD_NAME_DEVICEINFO_DELETE_REPLY "thing/deviceinfo/delete_reply" -#endif /* DEVICEINFO_ENABLED*/ -#ifdef RRPC_ENABLED -#define METHOD_NAME_RRPC_REQUEST_PLUS "rrpc/request/+" -#define METHOD_NAME_RRPC_REQUEST "rrpc/request" -#endif /* RRPC_ENABLED */ - -#define METHOD_MAX_LENGH 128 -#define URI_MAX_LENGH 256 -#define PROPERTY_KEY_VALUE_BUFF_MAX_LENGTH 1024 - -typedef struct { - const void* _; - char* _name; /* dm thing manager object name. */ - void* _local_thing_list; /* local thing list. */ - void* _local_thing_name_list; /* local thing list. */ - void* _sub_thing_list; /* sub thing list. currently not use. */ - void* _callback_list; /* callback function list */ - void* _service_property_get_identifier_list; /* identifier list when method=thing.service.property.get */ - void* _ota; - void* _thing_id; - void* _identifier; - void* _property_identifier_post; /* used when event = thing.event.property.post */ - void* _property_identifier_set; /* used when event = thing.service.property.set */ - void* _property_identifier_value_set; /* used when event = thing.service.property.set */ - void* _service_identifier_requested; /* service identifier when requested. */ - void* _get_value; - void* _set_value; - char* _set_value_str; - char* _get_value_str; - void* _message_info; - void* _cmp; - int _local_thing_id; - int _ret; - int _code; - char* _dm_version; - int _id; - int _response_id; - int _request_id; - void* _raw_data; - int _raw_data_length; - char* _method; - int _cloud_connected; - int _get_tsl_from_cloud; - int _destructing; -#ifdef RRPC_ENABLED - int _rrpc; - int _rrpc_message_id; -#endif /* RRPC_ENABLED */ - dm_callback_type_t _callback_type; - dm_cloud_domain_type_t _cloud_domain; - iotx_cmp_event_handle_func_fpt _cmp_event_handle_func_fp; - iotx_cmp_register_func_fpt _cmp_register_func_fp; - char _device_name[DEVICE_NAME_MAXLEN]; - char _product_key[PRODUCT_KEY_MAXLEN]; - char _device_secret[DEVICE_SECRET_MAXLEN]; - char _device_id[DEVICE_ID_MAXLEN]; -} dm_thing_manager_t; - -extern const void* get_dm_thing_manager_class(); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* DM_THING_MANAGER_H */ diff --git a/iotkit-embedded/src/dm/include/dsl.h b/iotkit-embedded/src/dm/include/dsl.h deleted file mode 100644 index 37c49c1..0000000 --- a/iotkit-embedded/src/dm/include/dsl.h +++ /dev/null @@ -1,269 +0,0 @@ -#ifndef DSL_H -#define DSL_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "dm_import.h" - -typedef enum { - property_access_mode_rw = 0, /* rw */ - property_access_mode_r, /* r */ - property_access_mode_w, /* w */ -} property_access_mode_t; - -typedef enum { - data_type_type_text = 0, /* text */ - data_type_type_enum, /* enum */ - data_type_type_bool, /* bool */ - data_type_type_float, /* float */ - data_type_type_double, /* double */ - data_type_type_int, /* int */ - data_type_type_date, /* date */ - data_type_type_struct, /* struct */ - data_type_type_array, /* array */ -} data_type_type_t; - -typedef enum { - event_type_info = 0, - event_type_alert, - event_type_error, -} event_type_t; - -typedef enum { - service_type_others = 0, /* other services */ - service_type_property_get, /* "method": "thing.service.property.get" */ - service_type_property_set, /* "method": "thing.service.property.set" */ -} service_type_t; - -#ifdef LITE_THING_MODEL -typedef union _data_type_x { - struct _data_type_int { - int min; /* min */ - int max; /* max */ - int value; /* truly value. */ - char* value_str; /* string type value */ - int precise; /* precise */ - } data_type_int_t; - - struct _data_type_float { - float min; /* min */ - float max; /* max */ - float value; /* truly value. */ - char* value_str; /* string type value */ - int precise; /* precise */ - } data_type_float_t; - - struct _data_type_double { - float min; /* min */ - float max; /* max */ - double value; /* truly value. */ - char* value_str; /* string type value */ - int precise; /* precise */ - } data_type_double_t; - - struct _data_type_enum { - int enum_item_number; /* number of enum items. */ - int value; /* truly value. */ - char* value_str; /* string type value */ - char** enum_item_key; - char** enum_item_value; - } data_type_enum_t; - - struct _data_type_text { - char* length_str; - int length; /* text length. */ - char* value; /* truly value. */ - } data_type_text_t; - - struct _data_type_date { - unsigned long long value; /* truly value. */ - char* value_str; /* string type value */ - } data_type_date_t; - - struct _data_type_bool { - int bool_item_number; /* number of enum items. */ - int value; /* 0: false; 1: true. */ - char* value_str; /* string type value */ - char** bool_item_key; - char** bool_item_value; - } data_type_bool_t; - - struct _data_type_array { - int size; - data_type_type_t item_type; - void* array; - char** value_str; - } data_type_array_t; - -} data_type_x_t; -#else -typedef union _data_type_x { - struct _data_type_int { - int min; /* min */ - char* min_str; - int max; /* max */ - char* max_str; - int value; /* truly value. */ - char* value_str; /* string type value */ - int precise; /* precise */ - char* precise_str; - char* unit; /* unit */ - char* unit_name; /* unitName */ - } data_type_int_t; - - struct _data_type_float { - float min; /* min */ - char* min_str; - float max; /* max */ - char* max_str; - float value; /* truly value. */ - char* value_str; /* string type value */ - int precise; /* precise */ - char* precise_str; - char* unit; /* unit */ - char* unit_name; /* unitName */ - } data_type_float_t; - - struct _data_type_double { - double min; /* min */ - char* min_str; - double max; /* max */ - char* max_str; - double value; /* truly value. */ - char* value_str; /* string type value */ - int precise; /* precise */ - char* precise_str; - char* unit; /* unit */ - char* unit_name; /* unitName */ - } data_type_double_t; - - struct _data_type_enum { - int enum_item_number; /* number of enum items. */ - int value; /* truly value. */ - char* value_str; /* string type value */ - char** enum_item_key; - char** enum_item_value; - } data_type_enum_t; - - struct _data_type_text { - char* length_str; - int length; /* text length. */ - char* value; /* truly value. */ - char* unit; /* unit */ - char* unit_name; /* unitName */ - } data_type_text_t; - - struct _data_type_date { - unsigned long long value; /* truly value. */ - char* value_str; /* string type value */ - } data_type_date_t; - - struct _data_type_bool { - int bool_item_number; /* number of enum items. */ - int value; /* 0: false; 1: true. */ - char* value_str; /* string type value */ - char** bool_item_key; - char** bool_item_value; - } data_type_bool_t; - - struct _data_type_array { - int size; - data_type_type_t item_type; - void* array; - char** value_str; - } data_type_array_t; - -} data_type_x_t; -#endif - -typedef struct _dataType { - data_type_type_t type; /* type */ - char* type_str; /* type, string format */ - size_t data_type_specs_number; /* useful when type = struct, otherwise 1 as default. */ - void* specs; /* specs, lite_property_t* when type = struct for property and event, otherwise cJSON*. */ - data_type_x_t value; /* actually store property values. used when type != struct */ -} data_type_t; - -typedef struct _lite_property { - /* warning: do not move orders of first three items. */ - char* identifier; /* identifier */ - char* name; /* name */ - data_type_t data_type; /* dataType */ - -} lite_property_t; - -typedef struct _property { - /* warning: do not move orders of first three items. be same as lite_property_t. */ - char* identifier; /* identifier */ - char* name; /* name */ - data_type_t data_type; /* dataType */ - - property_access_mode_t access_mode; /* accessMode */ - int required; /* required, 0: false, 1: true */ - char* desc; /* desc */ -} property_t; - -typedef union _input_data { - property_t property_to_set; /* "method": "thing.service.property.set" */ - - lite_property_t lite_property; /* "method": "thing.service.others" */ - - char* property_to_get_name; /* "method": "thing.service.property.get" */ -} input_data_t; - -typedef struct _event { - char* identifier; /* identifier */ - char* name; /* name */ - event_type_t event_type; /* type */ - char* event_type_str; /* type, string format */ - int required; /* 1 true or 0 false */ - char* desc; /* desc */ - size_t event_output_data_num; /* outputData number, default value 1 */ - lite_property_t* event_output_data; /* outputData */ - char* method; /* method */ -} event_t; - -typedef struct _service { - char* identifier; /* identifier */ - char* name; /* name */ - int required; /* 1 true or 0 false */ - char* desc; /* desc */ - char* call_type; /* callType */ - - service_type_t service_type; - - size_t service_input_data_num; /* inputData number */ - input_data_t* service_input_data; /* inputData */ - - size_t service_output_data_num; /* outputData number */ - lite_property_t* service_output_data; /* outputData */ - char* method; /* method */ -} service_t; - -typedef struct _profile { - char* product_key; /* productKey */ - char* device_name; /* deviceName */ -} profile_t; - -typedef struct _dsl_template { - char* schema; /* schema */ - char* link; /* link */ - profile_t profile; /* profile */ - - size_t property_number; - property_t* properties; /* properties */ - - size_t event_number; - event_t* events; /* events */ - - size_t service_number; - service_t* services; /* services */ -} dsl_template_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* DSL_H */ diff --git a/iotkit-embedded/src/dm/include/interface/cmp_abstract.h b/iotkit-embedded/src/dm/include/interface/cmp_abstract.h deleted file mode 100644 index 6adfbb5..0000000 --- a/iotkit-embedded/src/dm/include/interface/cmp_abstract.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef CMP_ABSTRACT_H -#define CMP_ABSTRACT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#include "iot_import.h" -#include "iot_export_cmp.h" -#include "iot_export_dm.h" - -#include "message_info_abstract.h" - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - int (*init)(void* _self, const char* product_key, const char* device_name, const char* device_secret, - const char* device_id, iotx_cmp_event_handle_func_fpt event_cb, void* pcontext, dm_cloud_domain_type_t domain_type); - int (*deinit)(void* _self, const void* option); - int (*regist)(void* _self, char* uri, iotx_cmp_register_func_fpt register_cb, void* pcontext, void* option); - int (*unregist)(void* _self, char* uri, void* option); - int (*send)(void* _self, message_info_t** msg, void* option); -#ifndef CMP_SUPPORT_MULTI_THREAD - int (*yield)(void* _self, int timeout_ms); -#endif -} cmp_abstract_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CMP_ABSTRACT_H */ diff --git a/iotkit-embedded/src/dm/include/interface/list_abstract.h b/iotkit-embedded/src/dm/include/interface/list_abstract.h deleted file mode 100644 index 4d17baa..0000000 --- a/iotkit-embedded/src/dm/include/interface/list_abstract.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef LIST_ABSTRACT_H -#define LIST_ABSTRACT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -typedef void (*print_fp_t)(void* data); -typedef void (*handle_fp_t)(void* node, va_list* params); - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - void (*insert)(void* _self, void* data); - void (*remove)(void* _self, void* data); - void (*clear)(void* _self); - int (*empty)(const void* _self); - int (*get_size)(const void* _self); - void (*iterator)(const void* _self, handle_fp_t handle_fp, va_list* params); - void (*print)(const void* _self, print_fp_t print_fp); -} list_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LIST_ABSTRACT_H */ diff --git a/iotkit-embedded/src/dm/include/interface/log_abstract.h b/iotkit-embedded/src/dm/include/interface/log_abstract.h deleted file mode 100644 index 61e6fac..0000000 --- a/iotkit-embedded/src/dm/include/interface/log_abstract.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef LOG_ABSTRACT_H -#define LOG_ABSTRACT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include -#include - -typedef enum { - log_level_emerg = 0, /* emergency level */ - log_level_crit, /* critical level */ - log_level_err, /* error level */ - log_level_warning, /* warning level */ - log_level_info, /* information level */ - log_level_debug, /* debug level */ -} log_level_t; - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - void (*open)(void* _self, void* _log_name); - void (*close)(const void* _self); - void (*set_log_level)(void* _self, log_level_t _log_level); - log_level_t (*get_log_level)(const void* _self); - void* (*get_log_name)(const void* _self); - void (*print_log)(const void* _self, const char* _func, const int _line, const int _log_level, const char* fmt, va_list* params); - void (*log)(const void* _self, const char* _func, const int _line, log_level_t _log_level, const char* fmt, ...); -} log_t; - -#define dm_log_emerg(...) (*(log_t**)_g_default_logger)->log(_g_default_logger, __FUNCTION__, __LINE__, log_level_emerg, __VA_ARGS__) -#define dm_log_crit(...) (*(log_t**)_g_default_logger)->log(_g_default_logger, __FUNCTION__, __LINE__, log_level_crit, __VA_ARGS__) -#define dm_log_err(...) (*(log_t**)_g_default_logger)->log(_g_default_logger, __FUNCTION__, __LINE__, log_level_err, __VA_ARGS__) -#define dm_log_warning(...) (*(log_t**)_g_default_logger)->log(_g_default_logger, __FUNCTION__, __LINE__, log_level_warning, __VA_ARGS__) -#define dm_log_info(...) (*(log_t**)_g_default_logger)->log(_g_default_logger, __FUNCTION__, __LINE__, log_level_info, __VA_ARGS__) -#define dm_log_debug(...) (*(log_t**)_g_default_logger)->log(_g_default_logger, __FUNCTION__, __LINE__, log_level_debug, __VA_ARGS__) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LOG_ABSTRACT_H */ diff --git a/iotkit-embedded/src/dm/include/interface/message_info_abstract.h b/iotkit-embedded/src/dm/include/interface/message_info_abstract.h deleted file mode 100644 index c51620f..0000000 --- a/iotkit-embedded/src/dm/include/interface/message_info_abstract.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef MESSAGE_INFO_ABSTRACT_H -#define MESSAGE_INFO_ABSTRACT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - int (*set_uri)(void* _self, char* uri); /* malloc mem and copy uri. */ - void (*set_payload)(void* _self, char* playload_buf, unsigned int payload_len); /* malloc mem and copy payload. */ - void (*clear)(void* _self); - void* (*get_uri)(void* _self); - void* (*get_payload)(void* _self); - void (*set_id)(void* _self, int id); - int (*get_id)(void* _self); - void (*set_version)(void* _self, const char* version); - char* (*get_version)(void* _self); - void (*add_params_data_item)(void* _self, const char* key, const char* value); - void (*set_method)(void* _self, const char* method); - char* (*get_method)(void* _self); - int (*serialize_to_payload_request)(void* _self); - int (*serialize_to_payload_response)(void* _self); - void (*set_message_type)(void* _self, int request); - int (*get_message_type)(void* _self); -#ifdef MEMORY_NO_COPY - char* (*get_params_data)(void* _self, int start); -#else - char* (*get_params_data)(void* _self); -#endif - void (*set_params_data)(void* _self, char* params_data_buf); /* malloc mem and copy payload. */ - int (*set_raw_data_and_length)(void* _self, void* raw_data, int raw_data_length); /* malloc mem and copy payload. */ - void* (*get_raw_data)(void* _self); - int (*get_raw_data_length)(void* _self); - char* (*get_product_key)(void* _self); - void (*set_product_key)(void* _self, char* product_key); /* malloc mem and copy payload. */ - char* (*get_device_name)(void* _self); - void (*set_device_name)(void* _self, char* device_name); /* malloc mem and copy payload. */ - void (*set_code)(void* _self, int code); - int (*get_code)(void* _self); -} message_info_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* MESSAGE_INFO_ABSTRACT_H */ diff --git a/iotkit-embedded/src/dm/include/interface/thing_abstract.h b/iotkit-embedded/src/dm/include/interface/thing_abstract.h deleted file mode 100644 index da0fa4a..0000000 --- a/iotkit-embedded/src/dm/include/interface/thing_abstract.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef THING_ABSTRACT_H -#define THING_ABSTRACT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -typedef void (*handle_item_t)(void* property, int index, va_list* params); - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - int (*set_dsl_string)(void* _self, const char* dsl, int dsl_str_len); /* set dsl to thing model. */ - void* (*get_dsl_string)(void* _self); /* get dsl from thing model. */ - int (*get_property_number)(const void* _self); - int (*get_service_number)(const void* _self); - int (*get_event_number)(const void* _self); - void* (*get_property_by_identifier)(const void* _self, const char* const identifier); - int (*get_property_identifier_by_index)(const void* _self, int index, char* identifier); - void* (*get_service_by_identifier)(const void* _self, const char* const identifier); - int (*get_service_identifier_by_index)(const void* _self, int index, char* identifier); - void* (*get_event_by_identifier)(const void* _self, const char* const identifier); - int (*get_event_identifier_by_index)(const void* _self, int index, char* identifier); - int (*get_schema)(const void* _self, char* schema); - int (*get_link)(const void* _self, char* link); - int (*get_product_key)(const void* _self, char* product_key); - char* (*return_product_key)(const void* _self); - int (*get_device_name)(const void* _self, char* device_name); - char* (*return_device_name)(const void* _self); - int (*set_property_value_by_identifier)(void* _self, const char* const identifier, const void* value, const char* value_str); - int (*set_property_value)(void* _self, void* property, const void* value, const char* value_str); - int (*get_property_value_by_identifier)(const void* _self, const char* const identifier, void* value, char** value_str); - int (*get_property_value)(const void* _self, const void* const property, void* value, char** value_str); - void (*property_iterator)(void* _self, handle_item_t handle_fp, va_list* params); - void (*event_iterator)(void* _self, handle_item_t handle_fp, va_list* params); - void (*service_iterator)(void* _self, handle_item_t handle_fp, va_list* params); -#ifdef ENABLE_THING_DEBUG - void (*print_property_lite_info)(const void* _self); - void (*print_property_detail_info)(const void* _self); - void (*print_event_lite_info)(const void* _self); - void (*print_event_detail_info)(const void* _self); - void (*print_service_lite_info)(const void* _self); - void (*print_service_detail_info)(const void* _self); -#endif - /* identifier must be *.* format pointer to identifier of outputData. */ - int (*set_event_value_by_identifier)(void* _self, const char* const identifier, const void* value, const char* value_str); - int (*get_event_value_by_identifier)(void* _self, const char* const identifier, void* value, char** value_str); - int (*set_service_input_output_data_value_by_identifier)(void* _self, const char* const identifier, const void* value, const char* value_str); - int (*get_service_input_output_data_value_by_identifier)(void* _self, const char* const identifier, void* value, char** value_str); - int (*get_lite_property_value)(const void* _self, const void* const property, void* value, char** value_str); -} thing_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif // THING_ABSTRACT_H diff --git a/iotkit-embedded/src/dm/include/interface/thing_manager_abstract.h b/iotkit-embedded/src/dm/include/interface/thing_manager_abstract.h deleted file mode 100644 index 4a87b84..0000000 --- a/iotkit-embedded/src/dm/include/interface/thing_manager_abstract.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef THING_MANAGER_ABSTRACT_H -#define THING_MANAGER_ABSTRACT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#include "iot_export_dm.h" - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - void* (*generate_new_local_thing)(void* _self, const char* tsl, int tsl_len); - int (*add_callback_function)(void* _self, handle_dm_callback_fp_t callback_func); - int (*set_thing_property_value)(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - int (*get_thing_property_value)(void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*set_thing_event_output_value)(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - int (*get_thing_event_output_value)(void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*get_thing_service_input_value)(void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*get_thing_service_output_value)(void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*set_thing_service_output_value)(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - int (*trigger_event)(void* _self, const void* thing_id, const void* event_identifier, const char* property_identifier); -#ifdef DEVICEINFO_ENABLED - int (*trigger_deviceinfo_update)(void* _self, const void* thing_id, const char* params); - int (*trigger_deviceinfo_delete)(void* _self, const void* thing_id, const char* params); -#endif /* DEVICEINFO_ENABLED*/ -#ifdef RRPC_ENABLED - int (*answer_service)(void* _self, const void* thing_id, const void* identifier, int response_id, int code, int rrpc); -#else - int (*answer_service)(void* _self, const void* thing_id, const void* identifier, int response_id, int code); -#endif /* RRPC_ENABLED */ - int (*invoke_raw_service)(void* _self, const void* thing_id, void* raw_data, int raw_data_length); - int (*answer_raw_service)(void* _self, const void* thing_id, void* raw_data, int raw_data_length); -#ifndef CMP_SUPPORT_MULTI_THREAD - int (*yield)(void* _self, int timeout); -#endif - int (*install_product_key_device_name)(void *_self, const void* thing_id, char *product_key, char *device_name); -} thing_manager_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* THING_MANAGER_ABSTRACT_H */ diff --git a/iotkit-embedded/src/dm/include/logger.h b/iotkit-embedded/src/dm/include/logger.h deleted file mode 100644 index 9f3ace7..0000000 --- a/iotkit-embedded/src/dm/include/logger.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LOGGER_H -#define LOGGER_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "interface/log_abstract.h" - -#define LOGGER_CLASS get_logger_class() - -typedef struct { - const void* _; - log_level_t _log_level; - char* _log_name; - char* _log_buffer; -} logger_t; - -extern const void* get_logger_class(); - -extern void* _g_default_logger; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* LOGGER_H */ diff --git a/iotkit-embedded/src/dm/include/single_list.h b/iotkit-embedded/src/dm/include/single_list.h deleted file mode 100644 index 775869a..0000000 --- a/iotkit-embedded/src/dm/include/single_list.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SINGLE_LIST_H -#define SINGLE_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include "interface/log_abstract.h" - -#define SINGLE_LIST_CLASS get_single_list_class() - -void list_iterator(const void* _list, handle_fp_t handle_fn, ...); - -typedef struct _node { - void* data; - struct _node* next; -} node_t; - -typedef struct { - const void* _; - node_t* _head; - int _size; - char* _name; -} single_list_t; - -extern const void* get_single_list_class(); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* SINGLE_LIST_H */ diff --git a/iotkit-embedded/src/dm/iot.mk b/iotkit-embedded/src/dm/iot.mk deleted file mode 100644 index ca782ab..0000000 --- a/iotkit-embedded/src/dm/iot.mk +++ /dev/null @@ -1,2 +0,0 @@ -LIBA_TARGET := libiot_dm.a -HDR_REFS := src diff --git a/iotkit-embedded/src/dm/src/cmp_abstract_impl.c b/iotkit-embedded/src/dm/src/cmp_abstract_impl.c deleted file mode 100644 index 79e4d2e..0000000 --- a/iotkit-embedded/src/dm/src/cmp_abstract_impl.c +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include -#include - -#include "interface/cmp_abstract.h" -#include "interface/log_abstract.h" -#include "cmp_abstract_impl.h" -#include "logger.h" -#include "cmp_message_info.h" - -#include "dm_import.h" - -#define CMP_IMPL_EXTENTED_ROOM_FOR_STRING_MALLOC 1 -static int cmp_impl_deinit(void* _self, const void* option); - -static const char string_cmp_abstrct_impl_class_name[] __DM_READ_ONLY__ = "cmp_impl_cls"; -static const char string_down_raw[] __DM_READ_ONLY__ = "down_raw"; -static const char string_down_raw_reply[] __DM_READ_ONLY__ = "down_raw_reply"; -static const char string_up_raw[] __DM_READ_ONLY__ = "up_raw"; -static const char string_up_raw_reply[] __DM_READ_ONLY__ = "up_raw_reply"; -static const char string__reply[] __DM_READ_ONLY__ = "_reply"; - -static void* cmp_impl_ctor(void* _self, va_list* params) -{ - cmp_abstract_impl_t* self = _self; - - self->cmp_inited = 0; - - return self; -} - -static void* cmp_impl_dtor(void* _self) -{ - cmp_abstract_impl_t* self = _self; - - if (self->cmp_inited) cmp_impl_deinit(self, NULL); - - return self; -} - -static int cmp_impl_init(void* _self, const char* _product_key, const char* _device_name, const char* _device_secret, - const char* _device_id, iotx_cmp_event_handle_func_fpt event_cb, void* pcontext, dm_cloud_domain_type_t domain_type) -{ - cmp_abstract_impl_t* self = _self; - iotx_cmp_init_param_t init_param; - - int ret = SUCCESS_RETURN; - - if (!_product_key || !_device_name || !_device_secret || !_device_id || !event_cb || !pcontext) return -1; - - if (self->cmp_inited) return ret; - - init_param.event_func = event_cb; - init_param.user_data = pcontext; - - init_param.domain_type = (iotx_cmp_cloud_domain_types_t)domain_type; - init_param.secret_type = IOTX_CMP_DEVICE_SECRET_DEVICE; - - ret = IOT_CMP_Init(&init_param, NULL); - - dm_log_debug("ret = IOT_CMP_Init() = %d\n", ret); - - if (FAIL_RETURN == ret) { - dm_printf("init fail\n"); - } else { - self->cmp_inited = 1; - } - - return ret; -} - -static int cmp_impl_deinit(void* _self, const void* option) -{ - cmp_abstract_impl_t* self = _self; - - (void)option; /* prevent build warning. */ - - self->cmp_inited = 0; - - return IOT_CMP_Deinit(NULL);; -} - -static int cmp_impl_regist(void* _self, char* uri, iotx_cmp_register_func_fpt register_cb, void* pcontext, void* option) -{ - iotx_cmp_register_param_t register_param; - int ret; - - if(!uri || !register_cb || !pcontext) { - dm_log_err("invalid param!"); - return FAIL_RETURN; - } - - /* Subscribe the specific topic */ - register_param.URI_type = IOTX_CMP_URI_UNDEFINE; - register_param.URI = uri; - - if (strstr(uri, string_down_raw) || strstr(uri, string_down_raw_reply) || strstr(uri, string_up_raw) || strstr(uri, string_up_raw_reply)) { - register_param.message_type = IOTX_CMP_MESSAGE_RAW; - } else if (strstr(uri, string__reply)) { - register_param.message_type = IOTX_CMP_MESSAGE_RESPONSE; - } else { - register_param.message_type = IOTX_CMP_MESSAGE_REQUEST; - } - - register_param.register_func = register_cb; - register_param.user_data = pcontext; - ret = IOT_CMP_Register(®ister_param, NULL); - - dm_log_debug("ret = IOT_CMP_Register() = %d\n", ret); - - if (FAIL_RETURN == ret) { - dm_printf("register fail\n"); - } - - return ret; -} - -static int cmp_impl_unregist(void* _self, char* uri, void* option) -{ - cmp_abstract_impl_t* self = _self; - iotx_cmp_unregister_param_t unregister_param; - int ret = -1; - - (void)option; /* prevent build warning. */ - - if (!uri || !self->cmp_inited) return -1; - - unregister_param.URI_type = IOTX_CMP_URI_UNDEFINE; - unregister_param.URI = uri; - - ret = IOT_CMP_Unregister(&unregister_param, NULL); - - dm_log_debug("ret = IOT_CMP_Unregister() = %d\n", ret); - - if (FAIL_RETURN == ret) { - dm_printf("unregister fail\n"); - } - - return ret; -} - -#ifdef MEMORY_NO_COPY -void recycle_memory(void* _user_data) -{ - void* p = _user_data; - dm_lite_free(p); -} -#endif - -static int cmp_impl_send(void* _self, message_info_t** msg, void* option) -{ - message_info_t** message_info = msg; - iotx_cmp_message_info_t iotx_cmp_message_info = {0}; - iotx_cmp_send_peer_t send_peer; - char* device_name; - char* product_key; - int ret; - int message_type; - (void)option; /* prevent build warning. */ - - if (!msg) return -1; - - iotx_cmp_message_info.id = (*message_info)->get_id(message_info); - iotx_cmp_message_info.code = (*message_info)->get_code(message_info); - message_type = (*message_info)->get_message_type(message_info); - iotx_cmp_message_info.message_type = message_type == CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST ? IOTX_CMP_MESSAGE_REQUEST : (message_type == CMP_MESSAGE_INFO_MESSAGE_TYPE_RESPONSE ? IOTX_CMP_MESSAGE_RESPONSE : IOTX_CMP_MESSAGE_RAW); - iotx_cmp_message_info.URI = (*message_info)->get_uri(message_info); - iotx_cmp_message_info.URI_type = IOTX_CMP_URI_UNDEFINE; - iotx_cmp_message_info.method = (*message_info)->get_method(message_info); -#ifdef MEMORY_NO_COPY - iotx_cmp_message_info.parameter = iotx_cmp_message_info.message_type == IOTX_CMP_MESSAGE_RAW ? (*message_info)->get_raw_data(message_info) : (*message_info)->get_params_data(message_info, 0); -#else - iotx_cmp_message_info.parameter = iotx_cmp_message_info.message_type == IOTX_CMP_MESSAGE_RAW ? (*message_info)->get_raw_data(message_info) : (*message_info)->get_params_data(message_info); -#endif - iotx_cmp_message_info.parameter_length = iotx_cmp_message_info.message_type == IOTX_CMP_MESSAGE_RAW ? (*message_info)->get_raw_data_length(message_info) : strlen(iotx_cmp_message_info.parameter); -#ifdef MEMORY_NO_COPY - iotx_cmp_message_info.recycle_memory_fp = recycle_memory; - iotx_cmp_message_info.user_data = iotx_cmp_message_info.message_type == IOTX_CMP_MESSAGE_RAW ? (*message_info)->get_raw_data(message_info) : (*message_info)->get_params_data(message_info, 1);; -#endif - product_key = (*message_info)->get_product_key(message_info); - device_name = (*message_info)->get_device_name(message_info); - - memset(&send_peer, 0, sizeof(iotx_cmp_send_peer_t)); - - strncpy(send_peer.device_name, device_name, sizeof(send_peer.device_name)); - strncpy(send_peer.product_key, product_key, sizeof(send_peer.product_key)); - - ret = IOT_CMP_Send(&send_peer, &iotx_cmp_message_info, NULL); - - dm_log_debug("ret = IOT_CMP_Send() = %d\n", ret); - - (*message_info)->clear(message_info); - - return ret; -} - -#ifndef CMP_SUPPORT_MULTI_THREAD -static int cmp_impl_yield(void* _self, int timeout_ms) -{ - return IOT_CMP_Yield(timeout_ms, NULL); -} -#endif - -static const cmp_abstract_t _cmp_impl_class = { - sizeof(cmp_abstract_impl_t), - string_cmp_abstrct_impl_class_name, - cmp_impl_ctor, - cmp_impl_dtor, - cmp_impl_init, - cmp_impl_deinit, - cmp_impl_regist, - cmp_impl_unregist, - cmp_impl_send, -#ifndef CMP_SUPPORT_MULTI_THREAD - cmp_impl_yield, -#endif -}; - -const void* get_cmp_impl_class() -{ - return &_cmp_impl_class; -} diff --git a/iotkit-embedded/src/dm/src/cmp_message_info.c b/iotkit-embedded/src/dm/src/cmp_message_info.c deleted file mode 100644 index d7d3c71..0000000 --- a/iotkit-embedded/src/dm/src/cmp_message_info.c +++ /dev/null @@ -1,570 +0,0 @@ -#include -#include -#include -#include -#include - -#include "cmp_message_info.h" -#include "logger.h" -#include "dm_import.h" -#include "iot_export_dm.h" -#include "interface/list_abstract.h" -#include "single_list.h" -#include "class_interface.h" - -#define CMP_MESSAGE_INFO_EXTENTED_ROOM_FOR_STRING_MALLOC 1 - -static const char string_cmp_message_info_class_name[] __DM_READ_ONLY__ = "cmp_msg_info_cls"; -static const char string_cmp_message_info_param_list_object_name[] __DM_READ_ONLY__ = "cmp message info param list"; - -static void cmp_message_info_clear(void* _self); -static void cmp_message_info_set_params_data(void* _self, char* params_buf); - -static void list_insert(void* _list, void* _data) -{ - list_t** list = (list_t**)_list; - - (*list)->insert(list, _data); -} - -static void* cmp_message_info_ctor(void* _self, va_list* params) -{ - cmp_message_info_t* self = _self; - - self->uri = NULL; - self->payload_buf = NULL; - self->params_data_buf = NULL; - self->params_data_buf = NULL; - self->raw_data_length = 0; - self->product_key = NULL; - self->device_name = NULL; - self->id = 0; - self->code = 0; - self->version = NULL; - self->param_list = new_object(SINGLE_LIST_CLASS, string_cmp_message_info_param_list_object_name); - self->method = NULL; - self->message_type = CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST; - self->ret = -1; - (void)params; - - return self; -} - -static int deep_strcpy(char** _dst, const void* _src) -{ - char** dst = _dst; - const char* src = _src; - int size = strlen(src) + CMP_MESSAGE_INFO_EXTENTED_ROOM_FOR_STRING_MALLOC; - - *dst = dm_lite_calloc(1, size); - - assert(*dst); - if (*dst == NULL) return -1; - - strcpy(*dst, src); - - return 0; -} - -static void* cmp_message_info_dtor(void* _self) -{ - cmp_message_info_t* self = _self; - - cmp_message_info_clear(self); - delete_object(self->param_list); - - return self; -} - -static int cmp_message_info_set_uri(void* _self, char* uri) -{ - cmp_message_info_t* self = _self; - - if (self->uri) { - dm_lite_free(self->uri); - self->uri = NULL; - } - assert(uri); - if (uri) { - return deep_strcpy(&self->uri, uri); - } - - return -1; -} - -static void cmp_message_info_set_payload(void* _self, char* payload_buf, unsigned int payload_len) -{ - cmp_message_info_t* self = _self; - - if (self->payload_buf) { - dm_lite_free(self->payload_buf); - self->payload_buf = NULL; - } - assert(payload_buf); - if (payload_buf) deep_strcpy(&self->payload_buf, payload_buf); -} - -static void clear_req_rsp_params(void* _req_rsp_param, va_list* params) -{ - req_rsp_param_t* req_rsp_param = _req_rsp_param; - cmp_message_info_t* cmp_message_info; - - cmp_message_info = va_arg(*params, void*); - - assert(cmp_message_info); - - if (req_rsp_param) { - if (req_rsp_param->key) dm_lite_free(req_rsp_param->key); - if (req_rsp_param->value) dm_lite_free(req_rsp_param->value); - - dm_lite_free(req_rsp_param); - - req_rsp_param = NULL; - } -} - -static void cmp_message_info_clear(void* _self) -{ - cmp_message_info_t* self = _self; - - if (self->uri) { - dm_lite_free(self->uri); - self->uri = NULL; - } - - if (self->payload_buf) { - dm_lite_free(self->payload_buf); - self->payload_buf = NULL; - } - - if (self->product_key) { - dm_lite_free(self->product_key); - self->product_key = NULL; - } - - if (self->device_name) { - dm_lite_free(self->device_name); - self->device_name = NULL; - } -#ifdef MEMORY_NO_COPY - self->params_data_buf = NULL; - self->raw_data_buf = NULL; - self->raw_data_length = 0; -#else - if (self->params_data_buf) { - dm_lite_free(self->params_data_buf); - self->params_data_buf = NULL; - } - - if (self->raw_data_buf) { - dm_lite_free(self->raw_data_buf); - self->raw_data_buf = NULL; - self->raw_data_length = 0; - } -#endif - if (self->version) { - dm_lite_free(self->version); - self->version = NULL; - } - - self->id = 0; - - if (self->param_list) { - list_t** list = self->param_list; - list_iterator(list, clear_req_rsp_params, self); - (*list)->clear(list); - } - - if (self->method) { - dm_lite_free(self->method); - self->method = NULL; - } -} - -static void* cmp_message_info_get_uri(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->uri; -} - -static void* cmp_message_info_get_payload(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->payload_buf; -} - -static void cmp_message_info_set_id(void* _self, int id) -{ - cmp_message_info_t* self = _self; - self->id = id; -} - -static int cmp_message_info_get_id(void* _self) -{ - cmp_message_info_t* self = _self; - return self->id; -} - -static void cmp_message_info_set_version(void* _self, const char* version) -{ - cmp_message_info_t* self = _self; - - assert(version); - - if (self->version) { - dm_lite_free(self->version); - self->version = NULL; - } - assert(version); - if (version) deep_strcpy(&self->version, version); -} - -static char* cmp_message_info_get_version(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->version; -} - -static void cmp_message_info_add_params_data_item(void* _self, const char* key, const char* value) -{ - cmp_message_info_t* self = _self; - list_t** list = self->param_list; - req_rsp_param_t* req_rsp_param; - - req_rsp_param = (req_rsp_param_t*)dm_lite_calloc(1, sizeof(req_rsp_param_t)); - - assert(req_rsp_param); - - if (req_rsp_param == NULL) return; - - if (key && value) { - deep_strcpy(&req_rsp_param->key, key); - deep_strcpy(&req_rsp_param->value, value); - } - - list_insert(list, req_rsp_param); -} - -static void cmp_message_info_set_method(void* _self, const char* method) -{ - cmp_message_info_t* self = _self; - - assert(method); - - if (self->method) { - dm_lite_free(self->method); - self->method = NULL; - } - assert(method); - if (method) deep_strcpy(&self->method, method); -} - -static char* cmp_message_info_get_method(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->method; -} - -static void serialize_params_data(void* _req_rsp_param, va_list* _params) -{ - req_rsp_param_t* req_rsp_param = _req_rsp_param; - cmp_message_info_t* cmp_message_info; - char* params; - int len = 6; /* "key":"value"\0 */ - - cmp_message_info = va_arg(*_params, void*); - params = va_arg(*_params, char*); - - if(0 != cmp_message_info->ret) return; - assert(req_rsp_param && cmp_message_info && req_rsp_param->key && req_rsp_param->value && params); - - if (strcmp(params, "{}") == 0) { - *(params + 1) = 0; - } - else { - *(params + strlen(params) - 1) = ','; /* change from '}' to ',' */ - } - - if (req_rsp_param && cmp_message_info && req_rsp_param->key && req_rsp_param->value) { - len += strlen(req_rsp_param->key); - len += strlen(req_rsp_param->value); - - /* check if there is enough room for new key-value. */ - if (len > (CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX - strlen(params))) { - cmp_message_info->ret = -1; - - dm_printf("\n[err] param buffer is short,len(%d) available(%lu)\n", len,(CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX - strlen(params))); - return; - } - - dm_sprintf(params + strlen(params), "\"%s\":%s}", req_rsp_param->key, req_rsp_param->value); - } -} - -static int cmp_message_info_serialize_to_payload_request(void* _self) -{ - cmp_message_info_t* self = _self; - const list_t** list = self->param_list; - char params[CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX] = {'{', '}', 0}; -#if 0 - char request[CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX + 32] = {0}; -#endif - int ret = -1; - - assert(self->version && self->method && list && (*list)); - if (self->version && self->method && list && (*list)) { - self->ret = 0; - list_iterator(list, serialize_params_data, self, params); -#if 0 - dm_snprintf(request, CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX + 32, "{\"id\":%d,\"version\":\"%s\",\"params\":%s,\"method\":\"%s\"}", - self->id, self->version, params, self->method); - cmp_message_info_set_payload(self, request, strlen(request)); -#endif - if(0 == self->ret) { - cmp_message_info_set_params_data(self, params); - - /* for debug only. */ - dm_printf("\nrequest params:\n%s\n\n", params); - - ret = 0; - } - self->ret = 0; - } - - return ret; -} - -static int cmp_message_info_serialize_to_payload_response(void* _self) -{ - cmp_message_info_t* self = _self; - const list_t** list = self->param_list; - char data[CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX] = {'{', '}', 0}; -#if 0 - char response[CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX + 32] = {0}; -#endif - int ret = -1; - - assert(list && (*list)); - if (list && (*list)) { - self->ret = 0; - list_iterator(list, serialize_params_data, self, data); -#if 0 - dm_snprintf(response, CMP_MESSAGE_INFO_PARAMS_LENGTH_MAX + 32, "{\"id\":%d,\"code\":%d,\"data\":%s}", - self->id, self->code, data); - cmp_message_info_set_payload(self, response, strlen(response)); -#endif - if(0 == self->ret) { - cmp_message_info_set_params_data(self, data); - - /* for debug only. */ - dm_printf("\nresponse data:\n%s\n\n", data); - - ret = 0; - } - self->ret = 0; - } - - return ret; -} - -static void cmp_message_info_set_message_type(void* _self, int message_type) -{ - cmp_message_info_t* self = _self; - - self->message_type = message_type; -} - -static int cmp_message_info_get_message_type(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->message_type; -} -#ifdef MEMORY_NO_COPY -static char* cmp_message_info_get_params_data(void* _self, int start) -{ - cmp_message_info_t* self = _self; - - if (start) { - return self->params_data_buf; - } else { - return self->params_data_buf + self->params_data_buf_prefix_len; - } -} -#else -static char* cmp_message_info_get_params_data(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->params_data_buf; -} -#endif - - -/* malloc mem and copy payload. */ -static void cmp_message_info_set_params_data(void* _self, char* params_data_buf) -{ - cmp_message_info_t* self = _self; -#ifdef MEMORY_NO_COPY - int param_data_buf_length = 0; - char temp_buf[128] = {0}; - int prefix_len = 0; -#endif - assert(params_data_buf); - - if (self->params_data_buf) { - dm_lite_free(self->params_data_buf); - self->params_data_buf = NULL; - } -#ifdef MEMORY_NO_COPY - if (params_data_buf) { - if (self->message_type == CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST) { - snprintf(temp_buf, sizeof(temp_buf), "{\"id\":%d,\"version\":\"%s\",\"method\":\"%s\",\"params\":", - self->id, self->version, self->method); - } else if (self->message_type == CMP_MESSAGE_INFO_MESSAGE_TYPE_RESPONSE) { - snprintf(temp_buf, sizeof(temp_buf), "{\"id\":%d,\"code\":%d,\"data\":", - self->id, self->code); - } else { - return; - } - param_data_buf_length = strlen(params_data_buf); - prefix_len = strlen(temp_buf); - self->params_data_buf = dm_lite_calloc(1, param_data_buf_length + prefix_len + 1 + 1); - strcpy(self->params_data_buf + prefix_len, params_data_buf); - memset(self->params_data_buf, 0, prefix_len); - self->params_data_buf_prefix_len = prefix_len; - } -#else - if (params_data_buf) deep_strcpy(&self->params_data_buf, params_data_buf); -#endif -} - -/* malloc mem and copy payload. */ -static int cmp_message_info_set_raw_data_and_length(void* _self, void* raw_data, int raw_data_length) -{ - cmp_message_info_t* self = _self; - - if (self->raw_data_buf) { - dm_lite_free(self->params_data_buf); - self->raw_data_buf = NULL; - } - - self->raw_data_buf = dm_lite_calloc(1, raw_data_length); - assert(self->raw_data_buf); - if (self->raw_data_buf == NULL) return -1; - self->raw_data_length = raw_data_length; - - memcpy(self->raw_data_buf, raw_data, raw_data_length); - - return 0; -} - - -static void* cmp_message_info_get_raw_data(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->raw_data_buf; -} - -static int cmp_message_info_get_raw_data_length(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->raw_data_length; -} - -static char* cmp_message_info_get_product_key(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->product_key; -} - -/* malloc mem and copy payload. */ -static void cmp_message_info_set_product_key(void* _self, char* product_key) -{ - cmp_message_info_t* self = _self; - - if (self->product_key) { - dm_lite_free(self->product_key); - self->product_key = NULL; - } - assert(product_key); - if (product_key) deep_strcpy(&self->product_key, product_key); -} - -static char* cmp_message_info_get_device_name(void* _self) -{ - cmp_message_info_t* self = _self; - - return self->device_name; -} - -/* malloc mem and copy payload. */ -static void cmp_message_info_set_device_name(void* _self, char* device_name) -{ - cmp_message_info_t* self = _self; - - if (self->device_name) { - dm_lite_free(self->device_name); - self->device_name = NULL; - } - assert(device_name); - if (device_name) deep_strcpy(&self->device_name, device_name); -} - -static void cmp_message_info_set_code(void* _self, int code) -{ - cmp_message_info_t* self = _self; - self->code = code; -} - -static int cmp_message_info_get_code(void* _self) -{ - cmp_message_info_t* self = _self; - return self->code; -} - -static const message_info_t _cmp_message_info_class = { - sizeof(cmp_message_info_t), - string_cmp_message_info_class_name, - cmp_message_info_ctor, - cmp_message_info_dtor, - cmp_message_info_set_uri, - cmp_message_info_set_payload, - cmp_message_info_clear, - cmp_message_info_get_uri, - cmp_message_info_get_payload, - cmp_message_info_set_id, - cmp_message_info_get_id, - cmp_message_info_set_version, - cmp_message_info_get_version, - cmp_message_info_add_params_data_item, - cmp_message_info_set_method, - cmp_message_info_get_method, - cmp_message_info_serialize_to_payload_request, - cmp_message_info_serialize_to_payload_response, - cmp_message_info_set_message_type, - cmp_message_info_get_message_type, - cmp_message_info_get_params_data, - cmp_message_info_set_params_data, - cmp_message_info_set_raw_data_and_length, - cmp_message_info_get_raw_data, - cmp_message_info_get_raw_data_length, - cmp_message_info_get_product_key, - cmp_message_info_set_product_key, - cmp_message_info_get_device_name, - cmp_message_info_set_device_name, - cmp_message_info_set_code, - cmp_message_info_get_code, -}; - -const void* get_cmp_message_info_class() -{ - return &_cmp_message_info_class; -} diff --git a/iotkit-embedded/src/dm/src/dm_impl.c b/iotkit-embedded/src/dm/src/dm_impl.c deleted file mode 100644 index c2ef59e..0000000 --- a/iotkit-embedded/src/dm/src/dm_impl.c +++ /dev/null @@ -1,314 +0,0 @@ -#include -#include -#include -#include -#include - -#include "interface/thing_abstract.h" -#include "interface/log_abstract.h" -#include "interface/list_abstract.h" -#include "interface/thing_manager_abstract.h" -#include "dm_thing_manager.h" -#include "logger.h" -#include "dm_thing.h" -#include "single_list.h" -#include "iot_export_dm.h" -#include "iot_import.h" -#include "lite-utils.h" -#include "class_interface.h" - -#include "dm_import.h" - -static const char string_dm_impl_class_name[] __DM_READ_ONLY__ = "dm_impl_cls"; -static const char string_dm_impl_log_object_name[] __DM_READ_ONLY__ = "dm_logger"; -static const char string_dm_impl_thing_manager_object_name[] __DM_READ_ONLY__ = "dm thing manager"; - -static void* dm_impl_ctor(void* _self, va_list* params) -{ - dm_impl_t* self = _self; - log_t** logger; - void* linkkit_callback_fp; - - self->_name = va_arg(*params, char*); - self->_get_tsl_from_cloud = va_arg(*params, int); - self->_log_level = va_arg(*params, int); - linkkit_callback_fp = va_arg(*params, void*); - self->_domain_type = va_arg(*params, int); - - if (self->_log_level > IOT_LOG_DEBUG) { - self->_log_level = IOT_LOG_DEBUG; - } - - self->_logger = new_object(LOGGER_CLASS, string_dm_impl_log_object_name, 0); - logger = self->_logger; - (*logger)->open(logger, "dm"); - (*logger)->set_log_level(logger, self->_log_level); - - /* use sh as default domain. */ - if (self->_domain_type >= dm_cloud_domain_max) { - self->_domain_type = dm_cloud_domain_sh; - } - - self->_thing_manager = new_object(DM_THING_MANAGER_CLASS, string_dm_impl_thing_manager_object_name, self->_get_tsl_from_cloud, linkkit_callback_fp, self->_domain_type); - - return self; -} - -static void* dm_impl_dtor(void* _self) -{ - dm_impl_t* self = _self; - - delete_object(self->_thing_manager); - delete_object(self->_logger); - - self->_logger = NULL; - - return self; -} - -static void* dm_impl_generate_new_thing(void* _self, const char* tsl, int tsl_len) -{ - dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - thing_t** thing = NULL; - - assert(thing_manager && tsl && tsl_len > 0); - - thing = (thing_t**)(*thing_manager)->generate_new_local_thing(thing_manager, tsl, tsl_len); - - return thing; -} - -static int dm_impl_set_property_value(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str) -{ - dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->set_thing_property_value && thing_id && identifier && (value || value_str)); - - return (*thing_manager)->set_thing_property_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_set_event_output_value(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str) -{ - dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->set_thing_event_output_value && thing_id && identifier && (value || value_str)); - if (strstr(identifier, "post")) { - return -1; - } - return (*thing_manager)->set_thing_event_output_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_set_service_output_value(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str) -{ - dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->set_thing_service_output_value && thing_id && identifier && (value || value_str)); - if (strcmp(identifier, "set") == 0|| strcmp(identifier, "get") == 0) { - return -1; - } - return (*thing_manager)->set_thing_service_output_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_get_property_value(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->get_thing_property_value && thing_id && identifier && (value || value_str)); - - return (*thing_manager)->get_thing_property_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_get_service_input_value(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->get_thing_service_input_value && thing_id && identifier && (value || value_str)); - if (strcmp(identifier, "set") == 0 || strcmp(identifier, "get") == 0) { - return -1; - } - return (*thing_manager)->get_thing_service_input_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_get_service_output_value(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->get_thing_service_output_value && thing_id && identifier && (value || value_str)); - if (strcmp(identifier, "set") == 0 || strcmp(identifier, "get") == 0) { - return -1; - } - return (*thing_manager)->get_thing_service_output_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_get_event_output_value(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str) -{ - const dm_impl_t* self = _self; - const thing_manager_t** thing_manager = (const thing_manager_t**)self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->get_thing_event_output_value && thing_id && identifier && (value || value_str)); - if (strstr(identifier, "post")) { - return -1; - } - return (*thing_manager)->get_thing_event_output_value(thing_manager, thing_id, identifier, value, value_str); -} - -static int dm_impl_install_callback_function(void* _self, handle_dm_callback_fp_t linkkit_callback_fp) -{ - dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - if (!linkkit_callback_fp) return -1; - - return (*thing_manager)->add_callback_function(thing_manager, linkkit_callback_fp); -} - -static int dm_impl_trigger_event(const void* _self, const void* thing_id, const void* event_identifier, const char* property_identifier) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->trigger_event && thing_id && event_identifier); - - return (*thing_manager)->trigger_event(thing_manager, thing_id, event_identifier, property_identifier); -} -#ifdef DEVICEINFO_ENABLED -static int dm_impl_trigger_deviceinfo_update(const void* _self, const void* thing_id, const char* params) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->trigger_deviceinfo_update && thing_id && params); - - return (*thing_manager)->trigger_deviceinfo_update(thing_manager, thing_id, params); -} - -static int dm_impl_trigger_deviceinfo_delete(const void* _self, const void* thing_id, const char* params) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->trigger_deviceinfo_delete && thing_id && params); - - return (*thing_manager)->trigger_deviceinfo_delete(thing_manager, thing_id, params); -} -#endif /* DEVICEINFO_ENABLED*/ -#ifdef RRPC_ENABLED -static int dm_impl_answer_service(const void* _self, const void* thing_id, const void* identifier, int response_id, int code, int rrpc) -#else -static int dm_impl_answer_service(const void* _self, const void* thing_id, const void* identifier, int response_id, int code) -#endif /* RRPC_ENABLED */ -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->answer_service && thing_id && identifier); -#ifdef RRPC_ENABLED - return (*thing_manager)->answer_service(thing_manager, thing_id, identifier, response_id, code, rrpc); -#else - return (*thing_manager)->answer_service(thing_manager, thing_id, identifier, response_id, code); -#endif /* RRPC_ENABLED */ -} - -static int dm_impl_invoke_raw_service(const void* _self, const void* thing_id, void* raw_data, int raw_data_length) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->invoke_raw_service && thing_id); - - return (*thing_manager)->invoke_raw_service(thing_manager, thing_id, raw_data, raw_data_length); -} - -static int dm_impl_answer_raw_service(const void* _self, const void* thing_id, void* raw_data, int raw_data_length) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->invoke_raw_service && thing_id); - - return (*thing_manager)->answer_raw_service(thing_manager, thing_id, raw_data, raw_data_length); -} -#ifndef CMP_SUPPORT_MULTI_THREAD -static int dm_impl_yield(const void* _self, int timeout_ms) -{ - const dm_impl_t* self = _self; - thing_manager_t** thing_manager = self->_thing_manager; - - assert(thing_manager && *thing_manager && (*thing_manager)->yield); - - return (*thing_manager)->yield(thing_manager, timeout_ms); -} -#endif -void* dm_lite_calloc(size_t nmemb, size_t size) -{ -#ifdef CMP_SUPPORT_MEMORY_MAGIC - return LITE_calloc(nmemb, size, MEM_MAGIC, DM_MODULE_NAME); -#else - return LITE_calloc(nmemb, size); -#endif -} - -void* dm_lite_malloc(size_t size) -{ -#ifdef CMP_SUPPORT_MEMORY_MAGIC - return LITE_malloc(size, MEM_MAGIC, DM_MODULE_NAME); -#else - return LITE_malloc(size); -#endif -} - -void dm_lite_free_func(void* ptr) -{ - return LITE_free_internal(ptr); -} - -void dm_lite_free(void* ptr) -{ - assert(ptr); - - if(!ptr) { - dm_printf("dm_lite_free abort\n"); - return; - } - - LITE_free_internal(ptr); -} - -static dm_t _dm_impl_class = { - sizeof(dm_impl_t), - string_dm_impl_class_name, - dm_impl_ctor, - dm_impl_dtor, - dm_impl_generate_new_thing, - dm_impl_set_property_value, - dm_impl_set_event_output_value, - dm_impl_set_service_output_value, - dm_impl_get_property_value, - dm_impl_get_service_input_value, - dm_impl_get_service_output_value, - dm_impl_get_event_output_value, - dm_impl_install_callback_function, - dm_impl_trigger_event, -#ifdef DEVICEINFO_ENABLED - dm_impl_trigger_deviceinfo_update, - dm_impl_trigger_deviceinfo_delete, -#endif /* DEVICEINFO_ENABLED*/ - dm_impl_answer_service, - dm_impl_invoke_raw_service, - dm_impl_answer_raw_service, -#ifndef CMP_SUPPORT_MULTI_THREAD - dm_impl_yield, -#endif -}; - -const void* get_dm_impl_class() -{ - return &_dm_impl_class; -} diff --git a/iotkit-embedded/src/dm/src/dm_thing.c b/iotkit-embedded/src/dm/src/dm_thing.c deleted file mode 100644 index 8203cff..0000000 --- a/iotkit-embedded/src/dm/src/dm_thing.c +++ /dev/null @@ -1,3750 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "interface/thing_abstract.h" -#include "interface/list_abstract.h" -#include "dm_thing.h" -#include "dm_import.h" -#include "logger.h" -#include "single_list.h" - -#include "lite-utils.h" - -#include "cJSON.h" - -#define DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC 1 - -static const char string_dm_thing_class_name[] __DM_READ_ONLY__ = "dm_thing_cls"; -static const char string_property[] __DM_READ_ONLY__ = "property"; -static const char string_service[] __DM_READ_ONLY__ = "service"; -static const char string_event[] __DM_READ_ONLY__ = "event"; -static const char string_properties[] __DM_READ_ONLY__ = "properties"; -static const char string_services[] __DM_READ_ONLY__ = "services"; -static const char string_events[] __DM_READ_ONLY__ = "events"; -static const char string_text[] __DM_READ_ONLY__ = "text"; -static const char string_enum[] __DM_READ_ONLY__ = "enum"; -static const char string_bool[] __DM_READ_ONLY__ = "bool"; -static const char string_float[] __DM_READ_ONLY__ = "float"; -static const char string_double[] __DM_READ_ONLY__ = "double"; -static const char string_int[] __DM_READ_ONLY__ = "int"; -static const char string_date[] __DM_READ_ONLY__ = "date"; -static const char string_struct[] __DM_READ_ONLY__ = "struct"; -static const char string_array[] __DM_READ_ONLY__ = "array"; -static const char string_min[] __DM_READ_ONLY__ = "min"; -static const char string_max[] __DM_READ_ONLY__ = "max"; -static const char string_length[] __DM_READ_ONLY__ = "length"; -static const char string_type[] __DM_READ_ONLY__ = "type"; -static const char string_identifier[] __DM_READ_ONLY__ = "identifier"; -static const char string_method[] __DM_READ_ONLY__ = "method"; -static const char string_callType[] __DM_READ_ONLY__ = "callType"; -static const char string_name[] __DM_READ_ONLY__ = "name"; -static const char string_specs[] __DM_READ_ONLY__ = "specs"; -static const char string_accessMode[] __DM_READ_ONLY__ = "accessMode"; -static const char string_required[] __DM_READ_ONLY__ = "required"; -static const char string_dataType[] __DM_READ_ONLY__ = "dataType"; -static const char string_desc[] __DM_READ_ONLY__ = "desc"; -static const char string_outputData[] __DM_READ_ONLY__ = "outputData"; -static const char string_inputData[] __DM_READ_ONLY__ = "inputData"; -static const char string_info[] __DM_READ_ONLY__ = "info"; -static const char string_alert[] __DM_READ_ONLY__ = "alert"; -static const char string_error[] __DM_READ_ONLY__ = "error"; -static const char string_size[] __DM_READ_ONLY__ = "size"; -static const char string_item[] __DM_READ_ONLY__ = "item"; -static const char string_thing_event_property_post[] __DM_READ_ONLY__ = "thing.event.property.post"; -static const char string_thing_service_property_set[] __DM_READ_ONLY__ = "thing.service.property.set"; -static const char string_thing_service_property_get[] __DM_READ_ONLY__ = "thing.service.property.get"; -static const char string_profile_productKey[] __DM_READ_ONLY__ = "profile.productKey"; -static const char string_profile_deviceName[] __DM_READ_ONLY__ = "profile.deviceName"; -static const char string_input[] __DM_READ_ONLY__ = "input"; -static const char string_output[] __DM_READ_ONLY__ = "output"; -static const char string_false[] __DM_READ_ONLY__ = "false"; -static const char string_true[] __DM_READ_ONLY__ = "true"; - -#ifdef USING_UTILS_JSON -#define KEY_BUFF_SIZE 32 -static int install_cjson_item_string(void** dst, const char* key, const char* src, int src_len); -static void install_cjson_obj_property(property_t* dst, const char* src, int src_len); -static void install_cjson_obj_lite_property(void* dst, const char* src, int src_len); -#ifdef LITE_THING_MODEL -static void install_cjson_item_string_without_malloc(void* dst, const char *key, const char* src, int src_len); -#endif -#else -static int install_cjson_item_string(void** dst, const cJSON* const cjson_obj, const char* const item_name); -static void install_cjson_obj_property(property_t* dst, const cJSON* cjson_obj); -static void install_cjson_obj_lite_property(void* dst, const cJSON* const cjson_obj); -#ifdef LITE_THING_MODEL -static void install_cjson_item_string_without_malloc(void* dst, const cJSON* const cjson_obj, const char* const item_name); -#endif -#endif -#ifdef ENABLE_THING_DEBUG -static void property_print_data_type_info(void* dst); -static void item_print_info(void* _item, int index, va_list* params); -#endif /* ENABLE_THING_DEBUG */ - -static void dm_lltoa(long long n, char* str, int radix) -{ - int i, j; - long long remain; - unsigned long long n_abs; - char tmp_char; - - i = 0; - - if (n < 0) { - str[i] = '-'; - str++; - n_abs = -1 * n; - } else { - n_abs = n; - } - - do { - remain = n_abs % radix; - if(remain > 9) - str[i] = remain - 10 + 'A'; - else - str[i] = remain + '0'; - i++; - } while(n_abs /= radix); - - str[i] = '\0'; - - for(i-- , j = 0 ; j <= i ; j++ , i--) - { - tmp_char = str[j]; - str[j] = str[i]; - str[i] = tmp_char; - } - return; -} - -static void free_item_memory(void* _item, int index, va_list* params); -static void free_lite_property(void* _lite_property); -static void free_property(void* _property, ...); - -static void* dm_thing_ctor(void* _self, va_list* params) -{ - dm_thing_t* self = _self; - - self->_name = va_arg(*params, char*); - self->_dsl_string_length = 0; - self->_dsl_string = NULL; - self->_arr_index = -1; - self->_json_object = NULL; - memset(&self->dsl_template, 0, sizeof(dsl_template_t)); - - return self; -} - -static void* dm_thing_dtor(void* _self) -{ - dm_thing_t* self = _self; - - property_iterator((thing_t*)self, free_item_memory, string_property, self->dsl_template.property_number); - event_iterator((thing_t*)self, free_item_memory, string_event, self->dsl_template.event_number); - service_iterator((thing_t*)self, free_item_memory, string_service, self->dsl_template.service_number); - - if (self->dsl_template.schema) { - dm_lite_free(self->dsl_template.schema); - } - if (self->dsl_template.link) { - dm_lite_free(self->dsl_template.link); - } - if (self->dsl_template.profile.device_name) { - dm_lite_free(self->dsl_template.profile.device_name); - } - if (self->dsl_template.profile.product_key) { - dm_lite_free(self->dsl_template.profile.product_key); - } - - return self; -} - -static void sprintf_float_double_precise(void* dst, double value, int precise) -{ - char temp_buff[48] = {0}; - char *point = NULL; - assert(dst); - - dm_snprintf(temp_buff, sizeof(temp_buff), "%.16lf", value); - point = strchr(temp_buff, '.'); - - assert(point); - - if (!point) return; - - *(point + (precise == 0 ? 0 : precise + 1)) = 0; - - strcpy(dst, temp_buff); -} - -static int get_type_size(data_type_type_t type) -{ - int size = 0; - switch(type) { - case data_type_type_int: - size = sizeof(int); - break; - case data_type_type_double: - size = sizeof(double); - break; - case data_type_type_float: - size = sizeof(float); - break; - case data_type_type_text: - size = sizeof(char*); - break; - default: - dm_printf("%s: unsupport data type: %d\n", __func__, type); - break; - } - return size; -} - -static data_type_type_t detect_data_type_type(const char* const type_str) -{ - data_type_type_t type; - if (strcmp(type_str, string_text) == 0) { - type = data_type_type_text; - } else if (strcmp(type_str, string_enum) == 0) { - type = data_type_type_enum; - } else if (strcmp(type_str, string_bool) == 0) { - type = data_type_type_bool; - } else if (strcmp(type_str, string_float) == 0) { - type = data_type_type_float; - } else if (strcmp(type_str, string_double) == 0) { - type = data_type_type_double; - } else if (strcmp(type_str, string_int) == 0) { - type = data_type_type_int; - } else if (strcmp(type_str, string_date) == 0) { - type = data_type_type_date; - } else if (strcmp(type_str, string_struct) == 0) { - type = data_type_type_struct; - } else if (strcmp(type_str, string_array) == 0) { - type = data_type_type_array; - } else { - dm_printf("%s: unknown data type: %s\n", __func__, type_str); - assert(0); - } - return type; -} - -#ifdef USING_UTILS_JSON -static void install_cjson_item_data_type_value(void *dst, data_type_type_t type, const char *src, int src_len) -{ - data_type_x_t *data_type_x = (data_type_x_t *)dst; - int index = 0; - char temp_buf[24] = {0}; - char temp_identifiy[32] = {0}; - char **current_key; -#ifndef LITE_THING_MODEL - char *p_tmp = NULL; - char **current_val; -#endif - long long long_val; - - if (type == data_type_type_int) { - /* min */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_min, src, src_len); - data_type_x->data_type_int_t.min = atoi(temp_buf); -#else - install_cjson_item_string((void **)&data_type_x->data_type_int_t.min_str, string_min, src, src_len); - data_type_x->data_type_int_t.min = atoi(data_type_x->data_type_int_t.min_str); -#endif - /* max */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_max, src, src_len); - data_type_x->data_type_int_t.max = atoi(temp_buf); -#else - install_cjson_item_string((void **)&data_type_x->data_type_int_t.max_str, string_max, src, src_len); - data_type_x->data_type_int_t.max = atoi(data_type_x->data_type_int_t.max_str); -#endif - -#if 0 - /* precise */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, "precise", src, src_len); - if (strlen(temp_buf)) { - data_type_x->data_type_int_t.precise = atoi(temp_buf); - } -#else - install_cjson_item_string((void **)&data_type_x->data_type_int_t.precise_str, "precise", src, src_len); - if (data_type_x->data_type_int_t.precise_str) { - data_type_x->data_type_int_t.precise = atoi(data_type_x->data_type_int_t.precise_str); - } -#endif -#else - data_type_x->data_type_int_t.precise = 0; -#endif - -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void **)&data_type_x->data_type_int_t.unit, "unit", src, src_len); - /* unitName */ - install_cjson_item_string((void **)&data_type_x->data_type_int_t.unit_name, "unitName", src, src_len); -#endif - - data_type_x->data_type_int_t.value = (data_type_x->data_type_int_t.min + data_type_x->data_type_int_t.max) / 2; /* default value? */ - - long_val = data_type_x->data_type_int_t.max; - dm_lltoa(long_val, temp_buf, 10); - data_type_x->data_type_int_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + 2 + data_type_x->data_type_int_t.precise + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - - assert(data_type_x->data_type_int_t.value_str); - dm_sprintf(data_type_x->data_type_int_t.value_str, "%d", data_type_x->data_type_int_t.value); - } else if (type == data_type_type_float) { - /* min */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_min, src, src_len); - data_type_x->data_type_float_t.min = atof(temp_buf); -#else - install_cjson_item_string((void **)&data_type_x->data_type_float_t.min_str, string_min, src, src_len); - data_type_x->data_type_float_t.min = atof(data_type_x->data_type_float_t.min_str); -#endif - /* max */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_max, src, src_len); - data_type_x->data_type_float_t.max = atof(temp_buf); -#else - install_cjson_item_string((void **)&data_type_x->data_type_float_t.max_str, string_max, src, src_len); - data_type_x->data_type_float_t.max = atof(data_type_x->data_type_float_t.max_str); -#endif -#if 0 - /* precise */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, "precise", src, src_len); - if (strlen(temp_buf)) { - data_type_x->data_type_float_t.precise = atoi(temp_buf); - } -#else - install_cjson_item_string((void **)&data_type_x->data_type_float_t.precise_str, "precise", src, src_len); - if (data_type_x->data_type_float_t.precise_str) { - data_type_x->data_type_float_t.precise = atoi(data_type_x->data_type_float_t.precise_str); - } -#endif -#else - data_type_x->data_type_float_t.precise = 7; -#endif - - -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void **)&data_type_x->data_type_float_t.unit, "unit", src, src_len); - /* unitName */ - install_cjson_item_string((void **)&data_type_x->data_type_float_t.unit_name, "unitName", src, src_len); -#endif - data_type_x->data_type_float_t.value = (data_type_x->data_type_float_t.min + data_type_x->data_type_float_t.max) / 2; /* default value? */ - long_val = (long long)data_type_x->data_type_float_t.max; - dm_lltoa(long_val, temp_buf, 10); - data_type_x->data_type_float_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + 2 + data_type_x->data_type_float_t.precise + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_float_t.value_str); - sprintf_float_double_precise(data_type_x->data_type_float_t.value_str, data_type_x->data_type_float_t.value, - data_type_x->data_type_float_t.precise); - } else if (type == data_type_type_double) { - /* min */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_min, src, src_len); - data_type_x->data_type_double_t.min = atof(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_double_t.min_str, string_min, src, src_len); - data_type_x->data_type_double_t.min = atof(data_type_x->data_type_double_t.min_str); -#endif - /* max */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_max, src, src_len); - data_type_x->data_type_double_t.max = atof(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_double_t.max_str, string_max, src, src_len); - data_type_x->data_type_double_t.max = atof(data_type_x->data_type_double_t.max_str); -#endif - -#if 0 - /* precise */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, "precise"); - if (strlen(temp_buf)) { - data_type_x->data_type_double_t.precise = atoi(temp_buf); - } -#else - install_cjson_item_string((void**)&data_type_x->data_type_double_t.precise_str, data_type_obj, "precise"); - if (data_type_x->data_type_double_t.precise_str) { - data_type_x->data_type_double_t.precise = atoi(data_type_x->data_type_double_t.precise_str); - } -#endif -#else - data_type_x->data_type_double_t.precise = 16; -#endif - -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void**)&data_type_x->data_type_double_t.unit, "unit", src, src_len); - /* unitName */ - install_cjson_item_string((void**)&data_type_x->data_type_double_t.unit_name, "unitName", src, src_len); -#endif - data_type_x->data_type_double_t.value = (data_type_x->data_type_double_t.min + data_type_x->data_type_double_t.max) / 2; /* default value? */ - long_val = (long long)data_type_x->data_type_double_t.max; - dm_lltoa(long_val, temp_buf, 10); - data_type_x->data_type_double_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + 2 + data_type_x->data_type_double_t.precise + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_double_t.value_str); - sprintf_float_double_precise(data_type_x->data_type_double_t.value_str, data_type_x->data_type_double_t.value, data_type_x->data_type_double_t.precise); - }else if (type == data_type_type_enum) { - /* detect enum item number */ - - index = get_json_item_size((char*)src, src_len); - - data_type_x->data_type_enum_t.enum_item_number = index; - - if (data_type_x->data_type_enum_t.enum_item_number == 0) { - data_type_x->data_type_enum_t.enum_item_key = NULL; - data_type_x->data_type_enum_t.enum_item_value = NULL; - return; - } - -#ifdef LITE_THING_MODEL - data_type_x->data_type_enum_t.enum_item_key = (char**)dm_lite_calloc(1, data_type_x->data_type_enum_t.enum_item_number * sizeof(char **)); - assert(data_type_x->data_type_enum_t.enum_item_key); - if (data_type_x->data_type_enum_t.enum_item_key == NULL) { - data_type_x->data_type_enum_t.enum_item_number = 0; - return; - } -#else - data_type_x->data_type_enum_t.enum_item_key = (char**)dm_lite_calloc(1, data_type_x->data_type_enum_t.enum_item_number * sizeof(char **)); - data_type_x->data_type_enum_t.enum_item_value = (char**)dm_lite_calloc(1, data_type_x->data_type_enum_t.enum_item_number * sizeof(char **)); - - assert(data_type_x->data_type_enum_t.enum_item_key && data_type_x->data_type_enum_t.enum_item_value); - if (data_type_x->data_type_enum_t.enum_item_key == NULL || data_type_x->data_type_enum_t.enum_item_value == NULL) { - data_type_x->data_type_enum_t.enum_item_number = 0; - return; - } -#endif - for (index = 0; index < data_type_x->data_type_enum_t.enum_item_number; ++index) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", index); - current_key = data_type_x->data_type_enum_t.enum_item_key + index; - *current_key = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(*current_key); - strcpy(*current_key, temp_buf); -#ifndef LITE_THING_MODEL - current_val = data_type_x->data_type_enum_t.enum_item_value + index; - install_cjson_item_string((void **)current_val, temp_buf, src, src_len); -#endif - } - data_type_x->data_type_enum_t.value = atoi(*data_type_x->data_type_enum_t.enum_item_key); - data_type_x->data_type_enum_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_enum_t.value_str); - dm_sprintf(data_type_x->data_type_enum_t.value_str, "%d", data_type_x->data_type_enum_t.value); - - } else if (type == data_type_type_bool) { - data_type_x->data_type_bool_t.bool_item_number = 2; - data_type_x->data_type_bool_t.bool_item_key = (char**)dm_lite_calloc(1, data_type_x->data_type_bool_t.bool_item_number * sizeof(char **)); -#ifndef LITE_THING_MODEL - data_type_x->data_type_bool_t.bool_item_value = (char**)dm_lite_calloc(1, data_type_x->data_type_bool_t.bool_item_number * sizeof(char **)); - - assert(data_type_x->data_type_bool_t.bool_item_key && data_type_x->data_type_bool_t.bool_item_value); -#else - assert(data_type_x->data_type_bool_t.bool_item_key); -#endif - for (index = 0; index < data_type_x->data_type_bool_t.bool_item_number; ++index) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", index); - current_key = data_type_x->data_type_bool_t.bool_item_key + index; - *current_key = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(*current_key); - strcpy(*current_key, temp_buf); -#ifndef LITE_THING_MODEL - current_val = data_type_x->data_type_bool_t.bool_item_value + index; - install_cjson_item_string((void **)current_val, temp_buf, src, src_len); -#endif - } - - data_type_x->data_type_bool_t.value = 1; /* default value. */ - - data_type_x->data_type_bool_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_bool_t.value_str); - dm_sprintf(data_type_x->data_type_bool_t.value_str, "%d", data_type_x->data_type_bool_t.value); - } else if (type == data_type_type_text) { - /* length */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_length, src, src_len); - if (strlen(temp_buf)) { - data_type_x->data_type_text_t.length = atoi(temp_buf); - } -#else - install_cjson_item_string((void **)&data_type_x->data_type_text_t.length_str, string_length, src, src_len); - if (data_type_x->data_type_text_t.length_str) { - data_type_x->data_type_text_t.length = atoi(data_type_x->data_type_text_t.length_str); - } -#endif - if (data_type_x->data_type_text_t.length < 1) { - data_type_x->data_type_text_t.length = 1; - } -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void **)&data_type_x->data_type_text_t.unit, "unit", src, src_len); - /* unitName */ - install_cjson_item_string((void **)&data_type_x->data_type_text_t.unit_name, "unitName", src, src_len); -#endif - data_type_x->data_type_text_t.value = NULL; /* default value. */ - } else if (type == data_type_type_date) { - data_type_x->data_type_date_t.value = 1513406265000; /* ms, UTC. default value. */ -#if !(WIN32) - dm_lltoa(__LONG_LONG_MAX__, temp_buf, 10); -#else - dm_lltoa(LLONG_MAX, temp_buf, 10); -#endif - data_type_x->data_type_date_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_date_t.value_str); - dm_lltoa(data_type_x->data_type_date_t.value, data_type_x->data_type_date_t.value_str, 10); - } else if(type == data_type_type_array){ -#ifdef LITE_THING_MODEL - dm_snprintf(temp_identifiy, sizeof(temp_identifiy), "%s.%s", string_item, string_type); - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, string_size, src, src_len); - data_type_x->data_type_array_t.size = atoi(temp_buf); - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, temp_identifiy, src, src_len); - data_type_x->data_type_array_t.item_type = detect_data_type_type(temp_buf); -#else - install_cjson_item_string((void**)&p_tmp, string_size, src, src_len); - data_type_x->data_type_array_t.size = p_tmp ? atoi(p_tmp) : 0; - dm_lite_free(p_tmp); - p_tmp = NULL; - dm_snprintf(temp_identifiy, sizeof(temp_identifiy), "%s.%s", string_item, string_type); - install_cjson_item_string((void**)&p_tmp, temp_identifiy, src, src_len); - data_type_x->data_type_array_t.item_type = detect_data_type_type(p_tmp); - dm_lite_free(p_tmp); - p_tmp = NULL; -#endif - data_type_x->data_type_array_t.array = dm_lite_calloc(data_type_x->data_type_array_t.size, get_type_size(data_type_x->data_type_array_t.item_type)); - if (data_type_x->data_type_array_t.item_type != data_type_type_text) { - data_type_x->data_type_array_t.value_str = dm_lite_calloc(data_type_x->data_type_array_t.size, sizeof(char**)); - } - }else { - assert(0); - } -} - -static void install_cjson_item_data_type(void *dst, const char *key, const char *src, int src_len) -{ - char *val = NULL, *dm_val = NULL; - char _key_index[KEY_BUFF_SIZE] = {0}; - int val_len = 0, dm_len = 0; - data_type_t *data_type = (data_type_t *)dst; - size_t specs_array_size, index; - size_t size; - lite_property_t *lite_property_item; - - val = LITE_json_value_of_ext2((char*)key, (char*)src, src_len, &val_len); - if (!val) { - return; - } - - dm_val = LITE_json_value_of_ext2((char*)string_type, val, val_len, &dm_len); - if (dm_val) { - size = dm_len + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; - data_type->type_str = dm_lite_calloc(1, size); - assert(data_type->type_str); - memset(data_type->type_str, 0, size); - strncpy(data_type->type_str, dm_val, size - 1); - data_type->type = detect_data_type_type(data_type->type_str); - } - - dm_val = LITE_json_value_of_ext2((char*)string_specs, val, val_len, &dm_len); - if (!dm_val) { - return; - } - if (data_type->type != data_type_type_struct) { - if ('{' != *dm_val) { - return; - } - data_type->data_type_specs_number = 0; - data_type->specs = NULL; - install_cjson_item_data_type_value((void *)&data_type->value, data_type->type, dm_val, dm_len); - } else { - char *spec_val = NULL; - int spec_len = 0; - if ('[' != *dm_val) { - return; - } - specs_array_size = get_json_item_size(dm_val, dm_len); - - data_type->data_type_specs_number = specs_array_size; - if (data_type->data_type_specs_number == 0) { - data_type->specs = NULL; - } else { - data_type->specs = dm_lite_calloc(data_type->data_type_specs_number, sizeof(lite_property_t)); - assert(data_type->specs); - } - - memset(&data_type->value, 0, sizeof(data_type_x_t)); - - for (index = 0; index < data_type->data_type_specs_number; ++index) { - lite_property_item = (lite_property_t *)data_type->specs + index; - snprintf(_key_index, KEY_BUFF_SIZE - 1, "[%lu]", index + 1); - spec_val = LITE_json_value_of_ext2(_key_index, dm_val, dm_len, &spec_len); - if (spec_val) { - lite_property_item = (lite_property_t *)data_type->specs + index; - install_cjson_obj_lite_property(lite_property_item, spec_val, spec_len); - } - } - } -} - -static void install_cjson_obj_lite_property(void *dst, const char *src, int src_len) -{ - lite_property_t *lite_property_item = (lite_property_t *)dst; - - install_cjson_item_string((void **)&lite_property_item->identifier, string_identifier, src, src_len); -#ifndef LITE_THING_MODEL - install_cjson_item_string((void **)&lite_property_item->name, string_name, src, src_len); -#endif - install_cjson_item_data_type(&lite_property_item->data_type, string_dataType, src, src_len); -} - -static void install_cjson_item_input_data(void *dst, service_type_t service_type, const char *src, int src_len) -{ - input_data_t *input_data_item = (input_data_t *)dst; - int property_to_get_name_size = 0; - if (service_type == service_type_others) { - install_cjson_obj_lite_property(&input_data_item->lite_property, src, src_len); - } else if (service_type == service_type_property_set) { - install_cjson_obj_property(&input_data_item->property_to_set, src, src_len); - } else if (service_type == service_type_property_get) { - property_to_get_name_size = src_len + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; - input_data_item->property_to_get_name = (char*)dm_lite_calloc(1, property_to_get_name_size); - strncpy(input_data_item->property_to_get_name, src, property_to_get_name_size - 1); - } -} - -static int install_cjson_item_string(void **dst, const char *key, const char *src, int src_len) -{ - int val_len = 0; - char *val = LITE_json_value_of_ext2((char*)key, (char*)src, src_len, &val_len); - size_t size; - - if (*dst) dm_lite_free(*dst); - - if (val) { - size = val_len + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; - *dst = dm_lite_calloc(1, size); - assert(*dst); - memset(*dst, 0, size); - strncpy(*dst, val, val_len); - } else { - dm_log_err("parse key:%s from val:%.*s failed", key, src_len, src); - } - - return val ? 0 : -1; -} - -#ifdef LITE_THING_MODEL -static void install_cjson_item_string_without_malloc(void *dst, const char *key, const char *src, int src_len) -{ - int val_len = 0; - char *val = LITE_json_value_of_ext2((char*)key, (char*)src, src_len, &val_len); - if (val) { - strncpy(dst, val, val_len); - } else { - dm_log_err("parse key:%s from val:%.*s failed", key, src_len, src); - } - return; -} -#endif - -static void install_cjson_item_bool(void *dst, const char *key, const char *src, int src_len) -{ - char *bool_val = NULL; - int bool_val_len = 0; - int *val = dst; - - *val = 1; - bool_val = LITE_json_value_of_ext2((char*)key, (char*)src, src_len, &bool_val_len); - - if (bool_val) { - if (!strncmp(bool_val, string_false, bool_val_len)) { - *val = 0; - } - } - - return; -} - -static void install_cjson_obj_property(property_t *dst, const char *src, int src_len) -{ - property_t *property = dst; - char *temp_str = NULL; - - /* properties.identifier */ - install_cjson_item_string((void **)&property->identifier, string_identifier, src, src_len); -#ifdef LITE_THING_MODEL - property->name = NULL; - property->desc = NULL; -#else - /* properties.name */ - install_cjson_item_string((void **)&property->name, string_name, src, src_len); - /* properties.desc */ - install_cjson_item_string((void **)&property->desc, string_desc, src, src_len); -#endif - /* properties.required */ - install_cjson_item_bool((void *)&property->required, string_required, src, src_len); - /* properties.accessMode */ - install_cjson_item_string((void **)&temp_str, string_accessMode, src, src_len); - if (temp_str) { - property->access_mode = strlen(temp_str) == 2 ? property_access_mode_rw : - (strcmp(temp_str, "r") == 0 ? property_access_mode_r : property_access_mode_w); - dm_lite_free(temp_str); - } - install_cjson_item_data_type(&property->data_type, string_dataType, src, src_len); - return; -} - -static void parse_cjson_obj_to_dsl_template_properties(void *_self, const char *src, int src_len) -{ - char _key[KEY_BUFF_SIZE] = {0}; - char *val = NULL; - int val_len = 0; - - dm_thing_t *self = _self; - int properties_array_size; - int index; - property_t *property; - - properties_array_size = get_json_item_size((char*)src, src_len); - - self->dsl_template.property_number = properties_array_size; - - if (self->dsl_template.property_number == 0) { - return; - } - - self->dsl_template.properties = (property_t *)dm_lite_calloc(self->dsl_template.property_number, sizeof(property_t)); - - assert(self->dsl_template.properties); - if (self->dsl_template.properties == 0) { - self->dsl_template.property_number = 0; - return; - } - - if (src) { - for (index = 0; index < self->dsl_template.property_number; ++index) { - snprintf(_key, KEY_BUFF_SIZE - 1, "[%d]", index + 1); - property = self->dsl_template.properties + index; - - val = LITE_json_value_of_ext2(_key, (char*)src, src_len, &val_len); - if (val) { - install_cjson_obj_property(property, val, val_len); - } - - } - } -} - - -static void install_cjson_obj_event(event_t *dst, const char *src, int src_len) -{ - char _key_index[KEY_BUFF_SIZE] = {0}; - char *val = NULL; - int val_len = 0; - char *dm_val = NULL; - int dm_val_len = 0; - event_t *event = dst; - int output_data_array_size; - int output_data_index; - lite_property_t *output_data_item; - - /* events.identifier */ - install_cjson_item_string((void **)&event->identifier, string_identifier, src, src_len); -#ifndef LITE_THING_MODEL - /* events.name */ - install_cjson_item_string((void **)&event->name, string_name, src, src_len); - /* events.desc */ - install_cjson_item_string((void **)&event->desc, string_desc, src, src_len); -#endif - /* events.method */ - install_cjson_item_string((void **)&event->method, string_method, src, src_len); - /* events.required */ - install_cjson_item_bool((void *)&event->required, string_required, src, src_len); - /* events.type */ - install_cjson_item_string((void **)&event->event_type_str, string_type, src, src_len); - if (strcmp(event->event_type_str, string_info) == 0) { - event->event_type = event_type_info; - } else if (strcmp(event->event_type_str, string_alert) == 0) { - event->event_type = event_type_alert; - } else if (strcmp(event->event_type_str, string_error) == 0) { - event->event_type = event_type_error; - } - -#ifdef LITE_THING_MODEL - if (strcmp(event->method, string_thing_event_property_post) == 0) { - return; - } -#endif - - val = LITE_json_value_of_ext2((char*)string_outputData, (char*)src, src_len, &val_len); - if (val) { - output_data_array_size = get_json_item_size(val, val_len); - event->event_output_data_num = output_data_array_size; - if (event->event_output_data_num == 0) { - return; - } - - event->event_output_data = (lite_property_t *)dm_lite_calloc(event->event_output_data_num, sizeof(lite_property_t)); - assert(event->event_output_data); - - if (event->event_output_data == NULL) { - event->event_output_data_num = 0; - return; - } - } - - for (output_data_index = 0; output_data_index < event->event_output_data_num; ++output_data_index) { - output_data_item = event->event_output_data + output_data_index; - snprintf(_key_index, KEY_BUFF_SIZE - 1, "[%d]", output_data_index + 1); - dm_val = LITE_json_value_of_ext2(_key_index, val, val_len, &dm_val_len); - if (dm_val) { - install_cjson_obj_lite_property(output_data_item, dm_val, dm_val_len); - } - } -} - -static void parse_cjson_obj_to_dsl_template_events(void *_self, const char *src, int src_len) -{ - char *val = NULL; - char _key[KEY_BUFF_SIZE] = {0}; - dm_thing_t *self = _self; - int events_array_size; - int index; - int val_len = 0; - event_t *event; - - events_array_size = get_json_item_size((char*)src, src_len); - - self->dsl_template.event_number = events_array_size; - - if (self->dsl_template.event_number == 0) { - return; - } - - self->dsl_template.events = (event_t *)dm_lite_calloc(self->dsl_template.event_number, sizeof(event_t)); - - assert(self->dsl_template.events); - if (self->dsl_template.events == NULL) { - self->dsl_template.event_number = 0; - dm_log_err("events malloc fail"); - return; - } - - for (index = 0; index < self->dsl_template.event_number; ++index) { - event = self->dsl_template.events + index; - snprintf(_key, KEY_BUFF_SIZE - 1, "[%d]", index + 1); - val = LITE_json_value_of_ext2(_key, (char*)src, src_len, &val_len); - if (val) { - install_cjson_obj_event(event, val, val_len); - } - } -} - -static void install_cjson_obj_service(service_t *dst, const char *src, int src_len) -{ - char _key_index[KEY_BUFF_SIZE] = {0}; - char *val = NULL; - int val_len = 0; - char *dm_val = NULL; - int dm_val_len = 0; - - service_t *service = dst; - int output_data_array_size, input_data_array_size; - int output_data_index, input_data_index; - lite_property_t *output_data_item; - input_data_t *input_data_item; - - /* service.identifier */ - install_cjson_item_string((void **)&service->identifier, string_identifier, src, src_len); -#ifndef LITE_THING_MODEL - /* service.name */ - install_cjson_item_string((void **)&service->name, string_name, src, src_len); - /* service.desc */ - install_cjson_item_string((void **)&service->desc, string_desc, src, src_len); -#endif - /* service.method */ - install_cjson_item_string((void **)&service->method, string_method, src, src_len); - /* service.call_type */ - install_cjson_item_string((void **)&service->call_type, string_callType, src, src_len); - /* service.required */ - install_cjson_item_bool((void *)&service->required, string_required, src, src_len); - - if (strcmp(service->method, string_thing_service_property_set) == 0) { - service->service_type = service_type_property_set; - } else if (strcmp(service->method, string_thing_service_property_get) == 0) { - service->service_type = service_type_property_get; - } else { - service->service_type = service_type_others; - } - - /* output data process */ - val = LITE_json_value_of_ext2((char*)string_outputData, (char*)src, src_len, &val_len); -#ifdef LITE_THING_MODEL - if (val && (service->service_type != service_type_property_get)) -#else - if (val) -#endif - { - output_data_array_size = get_json_item_size(val, val_len); - service->service_output_data_num = output_data_array_size; - - if (service->service_output_data_num) { - if (service->service_output_data_num) { - service->service_output_data = (lite_property_t *)dm_lite_calloc(service->service_output_data_num, - sizeof(lite_property_t)); - assert(service->service_output_data); - if (service->service_output_data == NULL) { - service->service_output_data_num = 0; - } - } else { - service->service_output_data = NULL; - } - } - } - - for (output_data_index = 0; output_data_index < service->service_output_data_num; ++output_data_index) { - output_data_item = service->service_output_data + output_data_index; - snprintf(_key_index, KEY_BUFF_SIZE, "[%d]", output_data_index + 1); - dm_val = LITE_json_value_of_ext2(_key_index, val, val_len, &dm_val_len); - install_cjson_obj_lite_property(output_data_item, dm_val, dm_val_len); - } - - /* input data process */ - service->service_input_data_num = 0; - val = LITE_json_value_of_ext2((char*)string_inputData, (char*)src, src_len, &val_len); -#ifdef LITE_THING_MODEL - if (val && (service->service_type != service_type_property_set)) -#else - if (val) -#endif - { - input_data_array_size = get_json_item_size(val, val_len); - service->service_input_data_num = input_data_array_size; - service->service_input_data = (input_data_t *)dm_lite_calloc(service->service_input_data_num, sizeof(input_data_t)); - if (service->service_input_data == NULL) { - service->service_input_data_num = 0; - } - } - for (input_data_index = 0; input_data_index < service->service_input_data_num; ++input_data_index) { - input_data_item = service->service_input_data + input_data_index; - snprintf(_key_index, KEY_BUFF_SIZE, "[%d]", input_data_index + 1); - dm_val = LITE_json_value_of_ext2(_key_index, val, val_len, &dm_val_len); - if (dm_val) { - install_cjson_item_input_data(input_data_item, service->service_type, dm_val, dm_val_len); - } - } -} - -static void parse_cjson_obj_to_dsl_template_services(void *_self, const char *src, int src_len) -{ - char _key[KEY_BUFF_SIZE] = {0}; - dm_thing_t *self = _self; - - int sercives_array_size; - int index; - service_t *service; - - char *val = NULL; - int val_len = 0; - - sercives_array_size = get_json_item_size((char*)src, src_len); - - self->dsl_template.service_number = sercives_array_size; - self->dsl_template.services = (service_t *)dm_lite_calloc(self->dsl_template.service_number, sizeof(service_t)); - - if (self->dsl_template.services == NULL) { - self->dsl_template.service_number = 0; - dm_log_err("self->dsl_template.events malloc fail"); - return; - } - - for (index = 0; index < self->dsl_template.service_number; ++index) { - service = self->dsl_template.services + index; - snprintf(_key, KEY_BUFF_SIZE, "[%d]", index + 1); - val = LITE_json_value_of_ext2(_key, (char*)src, src_len, &val_len); - if (val) { - install_cjson_obj_service(service, val, val_len); - } - } -} - -static int parse_cjson_obj_to_dsl_template(void *_self, const char *src, int src_len) -{ - if(!_self || !src || src_len <= 0) { - return -1; - } - - dm_thing_t *self = _self; - char *val = NULL; - int val_len = 0; -#ifdef LITE_THING_MODEL - self->dsl_template.schema = NULL; - self->dsl_template.link = NULL; -#else - /* schema */ - if(0 != install_cjson_item_string((void **)&self->dsl_template.schema, "schema", src, src_len)) { - dm_log_err("parse schema fail"); - } - /* link */ - if(0 != install_cjson_item_string((void **)&self->dsl_template.link, "link", src, src_len)) { - dm_log_err("parse link fail"); - } -#endif - - /* profile */ - if(0 != install_cjson_item_string((void **)&self->dsl_template.profile.product_key, string_profile_productKey, src, src_len)) { - self->dsl_template.profile.product_key = NULL; - } - if(0 != install_cjson_item_string((void **)&self->dsl_template.profile.device_name, string_profile_deviceName, src, src_len)) { - self->dsl_template.profile.device_name = NULL; - } - - /* properties */ - val = LITE_json_value_of_ext2((char*)string_properties, (char*)src, src_len, &val_len); - if (val) { - parse_cjson_obj_to_dsl_template_properties(self, val, val_len); - }else { - return -1; - } - - /* events */ - val = LITE_json_value_of_ext2((char*)string_events, (char*)src, src_len, &val_len); - if (val) { - parse_cjson_obj_to_dsl_template_events(self, val, val_len); - }else { - return -1; - } - - /* services */ - val = LITE_json_value_of_ext2((char*)string_services, (char*)src, src_len, &val_len); - if (val) { - parse_cjson_obj_to_dsl_template_services(self, val, val_len); - }else { - return -1; - } - - return 0; -} - -static int dm_thing_set_dsl_string(void *_self, const char *src, int src_len) -{ - int ret; - dm_thing_t *self = _self; - ret = parse_cjson_obj_to_dsl_template(self, src, src_len); - - self->_json_object = 0; - - return ret; -} - -#else -static void install_cjson_item_data_type_value(void* dst, data_type_type_t type, const cJSON* const cjson_obj) -{ - data_type_x_t* data_type_x = (data_type_x_t*)dst; - const cJSON* const data_type_obj = cjson_obj; - cJSON* enum_item_obj; - int index = 0; - int enum_number = 0; - int enum_index = 0; - char temp_buf[24] = {0}; - char** current_key; -#ifndef LITE_THING_MODEL - char** current_val; -#endif - long long long_val; - - if (type == data_type_type_int) { - /* min */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_min); - data_type_x->data_type_int_t.min = atoi(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_int_t.min_str, data_type_obj, string_min); - data_type_x->data_type_int_t.min = atoi(data_type_x->data_type_int_t.min_str); -#endif - - /* max */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_max); - data_type_x->data_type_int_t.max = atoi(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_int_t.max_str, data_type_obj, string_max); - data_type_x->data_type_int_t.max = atoi(data_type_x->data_type_int_t.max_str); -#endif - -#if 0 - /* precise */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, "precise"); - if (strlen(temp_buf)) { - data_type_x->data_type_int_t.precise = atoi(temp_buf); - } -#else - install_cjson_item_string((void**)&data_type_x->data_type_int_t.precise_str, data_type_obj, "precise"); - if (data_type_x->data_type_int_t.precise_str) { - data_type_x->data_type_int_t.precise = atoi(data_type_x->data_type_int_t.precise_str); - } -#endif -#else - data_type_x->data_type_int_t.precise = 0; -#endif - -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void**)&data_type_x->data_type_int_t.unit, data_type_obj, "unit"); - /* unitName */ - install_cjson_item_string((void**)&data_type_x->data_type_int_t.unit_name, data_type_obj, "unitName"); -#endif - data_type_x->data_type_int_t.value = (data_type_x->data_type_int_t.min + data_type_x->data_type_int_t.max) / 2; /* default value? */ - - long_val = data_type_x->data_type_int_t.max; - dm_lltoa(long_val, temp_buf, 10); - data_type_x->data_type_int_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + 2 + data_type_x->data_type_int_t.precise + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_int_t.value_str); - dm_sprintf(data_type_x->data_type_int_t.value_str, "%d", data_type_x->data_type_int_t.value); - } else if (type == data_type_type_float) { - /* min */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_min); - data_type_x->data_type_float_t.min = atof(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_float_t.min_str, data_type_obj, string_min); - data_type_x->data_type_float_t.min = atof(data_type_x->data_type_float_t.min_str); -#endif - /* max */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_max); - data_type_x->data_type_float_t.max = atof(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_float_t.max_str, data_type_obj, string_max); - data_type_x->data_type_float_t.max = atof(data_type_x->data_type_float_t.max_str); -#endif - -#if 0 - /* precise */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, "precise"); - if (strlen(temp_buf)) { - data_type_x->data_type_float_t.precise = atoi(temp_buf); - } -#else - install_cjson_item_string((void**)&data_type_x->data_type_float_t.precise_str, data_type_obj, "precise"); - if (data_type_x->data_type_float_t.precise_str) { - data_type_x->data_type_float_t.precise = atoi(data_type_x->data_type_float_t.precise_str); - } -#endif -#else - data_type_x->data_type_float_t.precise = 7; -#endif - -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void**)&data_type_x->data_type_float_t.unit, data_type_obj, "unit"); - /* unitName */ - install_cjson_item_string((void**)&data_type_x->data_type_float_t.unit_name, data_type_obj, "unitName"); -#endif - data_type_x->data_type_float_t.value = (data_type_x->data_type_float_t.min + data_type_x->data_type_float_t.max) / 2; /* default value? */ - long_val = (long long)data_type_x->data_type_float_t.max; - dm_lltoa(long_val, temp_buf, 10); - data_type_x->data_type_float_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + 2 + data_type_x->data_type_float_t.precise + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_float_t.value_str); - sprintf_float_double_precise(data_type_x->data_type_float_t.value_str, data_type_x->data_type_float_t.value, data_type_x->data_type_float_t.precise); - } else if (type == data_type_type_double) { - /* min */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_min); - data_type_x->data_type_double_t.min = atof(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_double_t.min_str, data_type_obj, string_min); - data_type_x->data_type_double_t.min = atof(data_type_x->data_type_double_t.min_str); -#endif - /* max */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_max); - data_type_x->data_type_double_t.max = atof(temp_buf); -#else - install_cjson_item_string((void**)&data_type_x->data_type_double_t.max_str, data_type_obj, string_max); - data_type_x->data_type_double_t.max = atof(data_type_x->data_type_double_t.max_str); -#endif - -#if 0 - /* precise */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, "precise"); - if (strlen(temp_buf)) { - data_type_x->data_type_double_t.precise = atoi(temp_buf); - } -#else - install_cjson_item_string((void**)&data_type_x->data_type_double_t.precise_str, data_type_obj, "precise"); - if (data_type_x->data_type_double_t.precise_str) { - data_type_x->data_type_double_t.precise = atoi(data_type_x->data_type_double_t.precise_str); - } -#endif -#else - data_type_x->data_type_double_t.precise = 16; -#endif - -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void**)&data_type_x->data_type_double_t.unit, data_type_obj, "unit"); - /* unitName */ - install_cjson_item_string((void**)&data_type_x->data_type_double_t.unit_name, data_type_obj, "unitName"); -#endif - data_type_x->data_type_double_t.value = (data_type_x->data_type_double_t.min + data_type_x->data_type_double_t.max) / 2; /* default value? */ - long_val = (long long)data_type_x->data_type_double_t.max; - dm_lltoa(long_val, temp_buf, 10); - data_type_x->data_type_double_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + 2 + data_type_x->data_type_double_t.precise + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_double_t.value_str); - sprintf_float_double_precise(data_type_x->data_type_double_t.value_str, data_type_x->data_type_double_t.value, data_type_x->data_type_double_t.precise); - } else if (type == data_type_type_enum) { - /* find enum number */ - for (index = 0; index < 100; ++index) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", index); - enum_item_obj = cJSON_GetObjectItem(data_type_obj, temp_buf); - if (enum_item_obj) { - enum_number++; - } - } - - data_type_x->data_type_enum_t.enum_item_number = enum_number; - if (data_type_x->data_type_enum_t.enum_item_number == 0) { - data_type_x->data_type_enum_t.enum_item_key = NULL; - data_type_x->data_type_enum_t.enum_item_value = NULL; - return; - } -#ifdef LITE_THING_MODEL - data_type_x->data_type_enum_t.enum_item_key = (char**)dm_lite_calloc(1, data_type_x->data_type_enum_t.enum_item_number * sizeof(char**)); - - assert(data_type_x->data_type_enum_t.enum_item_key); - if (data_type_x->data_type_enum_t.enum_item_key == NULL) { - data_type_x->data_type_enum_t.enum_item_number = 0; - return; - } -#else - data_type_x->data_type_enum_t.enum_item_key = (char**)dm_lite_calloc(1, data_type_x->data_type_enum_t.enum_item_number * sizeof(char**)); - data_type_x->data_type_enum_t.enum_item_value = (char**)dm_lite_calloc(1, data_type_x->data_type_enum_t.enum_item_number * sizeof(char**)); - - assert(data_type_x->data_type_enum_t.enum_item_key && data_type_x->data_type_enum_t.enum_item_value); - if (data_type_x->data_type_enum_t.enum_item_key == NULL || data_type_x->data_type_enum_t.enum_item_value == NULL) { - data_type_x->data_type_enum_t.enum_item_number = 0; - return; - } -#endif - - for (index = 0; index < 100; ++index) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", index); - enum_item_obj = cJSON_GetObjectItem(data_type_obj, temp_buf); - if (enum_item_obj) { - current_key = data_type_x->data_type_enum_t.enum_item_key + enum_index; - *current_key = dm_lite_calloc(1, strlen(temp_buf) + 1); - assert(*current_key); - strcpy(*current_key, temp_buf); -#ifndef LITE_THING_MODEL - current_val = data_type_x->data_type_enum_t.enum_item_value + enum_index++; - install_cjson_item_string((void**)current_val, data_type_obj, temp_buf); -#else - enum_index++; -#endif - } - } - - data_type_x->data_type_enum_t.value = atoi(*data_type_x->data_type_enum_t.enum_item_key); /* default value. */ - data_type_x->data_type_enum_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_enum_t.value_str); - dm_sprintf(data_type_x->data_type_enum_t.value_str, "%d", data_type_x->data_type_enum_t.value); - - } else if (type == data_type_type_bool) { - data_type_x->data_type_bool_t.bool_item_number = 2; - data_type_x->data_type_bool_t.bool_item_key = (char**)dm_lite_calloc(1, data_type_x->data_type_bool_t.bool_item_number * sizeof(char**)); -#ifndef LITE_THING_MODEL - data_type_x->data_type_bool_t.bool_item_value = (char**)dm_lite_calloc(1, data_type_x->data_type_bool_t.bool_item_number * sizeof(char**)); - - assert(data_type_x->data_type_bool_t.bool_item_key && data_type_x->data_type_bool_t.bool_item_value); -#else - assert(data_type_x->data_type_bool_t.bool_item_key); -#endif - for (index = 0; index < data_type_x->data_type_bool_t.bool_item_number; ++index) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", index); - current_key = data_type_x->data_type_bool_t.bool_item_key + index; - *current_key = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(*current_key); - strcpy(*current_key, temp_buf); -#ifndef LITE_THING_MODEL - current_val = data_type_x->data_type_bool_t.bool_item_value + index; - install_cjson_item_string((void**)current_val, data_type_obj, temp_buf); -#endif - } - - data_type_x->data_type_bool_t.value = 1; /* default value. */ - - data_type_x->data_type_bool_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_bool_t.value_str); - dm_sprintf(data_type_x->data_type_bool_t.value_str, "%d", data_type_x->data_type_bool_t.value); - } else if (type == data_type_type_text) { - /* length */ -#ifdef LITE_THING_MODEL - memset(temp_buf, 0, sizeof(temp_buf)); - install_cjson_item_string_without_malloc(temp_buf, data_type_obj, string_length); - if (strlen(temp_buf)) { - data_type_x->data_type_text_t.length = atoi(temp_buf); - } -#else - install_cjson_item_string((void**)&data_type_x->data_type_text_t.length_str, data_type_obj, string_length); - if (data_type_x->data_type_text_t.length_str) { - data_type_x->data_type_text_t.length = atoi(data_type_x->data_type_text_t.length_str); - } -#endif - if (data_type_x->data_type_text_t.length < 1) data_type_x->data_type_text_t.length = 1; -#ifndef LITE_THING_MODEL - /* unit */ - install_cjson_item_string((void**)&data_type_x->data_type_text_t.unit, data_type_obj, "unit"); - /* unitName */ - install_cjson_item_string((void**)&data_type_x->data_type_text_t.unit_name, data_type_obj, "unitName"); -#endif - data_type_x->data_type_text_t.value = NULL; /* default value. */ - } else if (type == data_type_type_date) { - data_type_x->data_type_date_t.value = 1513406265000; /* ms, UTC. default value. */ - dm_lltoa(__LONG_LONG_MAX__, temp_buf, 10); - data_type_x->data_type_date_t.value_str = dm_lite_calloc(1, strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC); - assert(data_type_x->data_type_date_t.value_str); - dm_lltoa(data_type_x->data_type_date_t.value, data_type_x->data_type_date_t.value_str, 10); - } else { - assert(0); - } -} - -static void install_cjson_item_data_type(void* dst, const cJSON* const cjson_obj, const char* const item_name) -{ - const cJSON* const root_obj = cjson_obj; - data_type_t* data_type = (data_type_t*)dst; - cJSON* data_type_obj = NULL; - cJSON* type_obj; - cJSON* specs_obj; - cJSON* specs_struct_item_obj; - size_t size, specs_array_size, index; - lite_property_t* lite_property_item; - - data_type_obj = cJSON_GetObjectItem(root_obj, item_name); - if (!data_type_obj || !cJSON_IsObject(data_type_obj)) { - return; - } - - type_obj = cJSON_GetObjectItem(data_type_obj, string_type); - if (type_obj && cJSON_IsString(type_obj)) { -#ifdef CJSON_STRING_ZEROCOPY - size = type_obj->valuestring_length + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#else - size = strlen(type_obj->valuestring) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#endif - data_type->type_str = dm_lite_calloc(1, size); - assert(data_type->type_str); - memset(data_type->type_str, 0, size); -#ifdef CJSON_STRING_ZEROCOPY - strncpy(data_type->type_str, type_obj->valuestring, size - 1); -#else - strcpy(data_type->type_str, type_obj->valuestring); -#endif - data_type->type = detect_data_type_type(data_type->type_str); - } - - specs_obj = cJSON_GetObjectItem(data_type_obj, string_specs); - if (!specs_obj) { - return; - } - if (data_type->type != data_type_type_struct) { - assert(cJSON_IsObject(specs_obj)); - if (!cJSON_IsObject(specs_obj)) { - return; - } - data_type->data_type_specs_number = 0; - data_type->specs = NULL; - install_cjson_item_data_type_value((void*)&data_type->value, data_type->type, specs_obj); - } else { - assert(cJSON_IsArray(specs_obj)); - if (!cJSON_IsArray(specs_obj)) { - return; - } - - specs_array_size = cJSON_GetArraySize(specs_obj); - data_type->data_type_specs_number = specs_array_size; - if (data_type->data_type_specs_number == 0) { - data_type->specs = NULL; - } else { - data_type->specs = dm_lite_calloc(data_type->data_type_specs_number, sizeof(lite_property_t)); - assert(data_type->specs); - } - - memset(&data_type->value, 0, sizeof(data_type_x_t)); - for (index = 0; index < data_type->data_type_specs_number; ++index) { - specs_struct_item_obj = cJSON_GetArrayItem(specs_obj, index); - if (specs_struct_item_obj) { - lite_property_item = (lite_property_t*)data_type->specs + index; - install_cjson_obj_lite_property(lite_property_item, specs_struct_item_obj); - } - } - } -} - -static void install_cjson_obj_lite_property(void* dst, const cJSON* const cjson_obj) -{ - const cJSON* const output_data_item_obj = cjson_obj; - lite_property_t* lite_property_item = (lite_property_t*)dst; - - install_cjson_item_string((void**)&lite_property_item->identifier, output_data_item_obj, string_identifier); -#ifndef LITE_THING_MODEL - install_cjson_item_string((void**)&lite_property_item->name, output_data_item_obj, string_name); -#endif - install_cjson_item_data_type(&lite_property_item->data_type, output_data_item_obj, string_dataType); -} - -static void install_cjson_item_input_data(void* dst, const cJSON* const cjson_obj, service_type_t service_type) -{ - const cJSON* const input_output_data_item_obj = cjson_obj; - input_data_t* input_data_item = (input_data_t*)dst; - int property_to_get_name_size = 0; - - if (service_type == service_type_others) { - install_cjson_obj_lite_property(&input_data_item->lite_property, input_output_data_item_obj); - } - - else if (service_type == service_type_property_set) { - install_cjson_obj_property(&input_data_item->property_to_set, input_output_data_item_obj); - } - - else if (service_type == service_type_property_get) { - assert(cJSON_IsString(input_output_data_item_obj)); -#ifdef CJSON_STRING_ZEROCOPY - property_to_get_name_size = input_output_data_item_obj->valuestring_length + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#else - property_to_get_name_size = strlen(input_output_data_item_obj->valuestring) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#endif - input_data_item->property_to_get_name = (char*)dm_lite_calloc(1, property_to_get_name_size); -#ifdef CJSON_STRING_ZEROCOPY - strncpy(input_data_item->property_to_get_name, input_output_data_item_obj->valuestring, property_to_get_name_size - 1); -#else - strcpy(input_data_item->property_to_get_name, input_output_data_item_obj->valuestring); -#endif - } -} - -static int install_cjson_item_string(void** dst, const cJSON* const cjson_obj, const char* const item_name) -{ - const cJSON* const root_obj = cjson_obj; - cJSON* item_obj; - size_t size; - - int ret = -1; - item_obj = cJSON_GetObjectItem(root_obj, item_name); - if (item_obj && cJSON_IsString(item_obj)) { -#ifdef CJSON_STRING_ZEROCOPY - size = item_obj->valuestring_length + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#else - size = strlen(item_obj->valuestring) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#endif - *dst = dm_lite_calloc(1, size); - assert(*dst); - memset(*dst, 0, size); -#ifdef CJSON_STRING_ZEROCOPY - strncpy(*dst, item_obj->valuestring, size - 1); -#else - strcpy(*dst, item_obj->valuestring); -#endif - ret = 0; - } - return ret; -} - -#ifdef LITE_THING_MODEL -static void install_cjson_item_string_without_malloc(void* dst, const cJSON* const cjson_obj, const char* const item_name) -{ - const cJSON* const root_obj = cjson_obj; - cJSON* item_obj; -#ifdef CJSON_STRING_ZEROCOPY - size_t size; -#endif - item_obj = cJSON_GetObjectItem(root_obj, item_name); - if (item_obj && cJSON_IsString(item_obj)) { -#ifdef CJSON_STRING_ZEROCOPY - size = item_obj->valuestring_length + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; -#endif - -#ifdef CJSON_STRING_ZEROCOPY - strncpy(dst, item_obj->valuestring, size - 1); -#else - strcpy(dst, item_obj->valuestring); -#endif - } -} -#endif - -static void install_cjson_item_bool(void* dst, const cJSON* const cjson_obj, const char* const item_name) -{ - const cJSON* const root_obj = cjson_obj; - int* val = dst; - const cJSON* const item_obj = cJSON_GetObjectItem(root_obj, item_name); - - if (item_obj && cJSON_IsBool(item_obj)) { - *val = cJSON_IsTrue(item_obj) ? 1 : 0 ; - } else { - *val = 1; - } -} - -static void install_cjson_obj_property(property_t* dst, const cJSON* const cjson_obj) -{ - property_t* property = dst; - const cJSON* const property_item_obj = cjson_obj; - char* temp_str = NULL; - - /* properties.identifier */ - install_cjson_item_string((void**)&property->identifier, property_item_obj, string_identifier); -#ifdef LITE_THING_MODEL - property->name = NULL; - property->desc = NULL; -#else - /* properties.name */ - install_cjson_item_string((void**)&property->name, property_item_obj, string_name); - /* properties.desc */ - install_cjson_item_string((void**)&property->desc, property_item_obj, string_desc); -#endif - /* properties.required */ - install_cjson_item_bool((void*)&property->required, property_item_obj, string_required); - /* properties.accessMode */ - install_cjson_item_string((void**)&temp_str, property_item_obj, string_accessMode); - if (temp_str) { - property->access_mode = strlen(temp_str) == 2 ? property_access_mode_rw : - (strcmp(temp_str, "r") == 0 ? property_access_mode_r : property_access_mode_w); - dm_lite_free(temp_str); - } - install_cjson_item_data_type(&property->data_type, property_item_obj, string_dataType); -} - -static void parse_cjson_obj_to_dsl_template_properties(void* _self, const cJSON* cjson_obj) -{ - dm_thing_t* self = _self; - const cJSON* properties_obj = cjson_obj; - cJSON* property_item_obj; - int properties_array_size; - int index; - property_t* property; - - properties_array_size = cJSON_GetArraySize(properties_obj); - - self->dsl_template.property_number = properties_array_size; - - if (self->dsl_template.property_number == 0) return; - - self->dsl_template.properties = (property_t*)dm_lite_calloc(self->dsl_template.property_number, sizeof(property_t)); - - assert(self->dsl_template.properties); - - if (self->dsl_template.properties == 0) { - self->dsl_template.property_number = 0; - return; - } - - for (index = 0; index < self->dsl_template.property_number; ++index) { - property_item_obj = cJSON_GetArrayItem(properties_obj, index); - if (property_item_obj) { - property = self->dsl_template.properties + index; - install_cjson_obj_property(property, property_item_obj); - } - } -} - -static void install_cjson_obj_event(event_t* dst, const cJSON* const cjson_obj) -{ - event_t* event = dst; - const cJSON* const event_item_obj = cjson_obj; - const cJSON* output_data_array_obj; - const cJSON* output_data_item_obj; - int output_data_array_size; - int output_data_index; - lite_property_t* output_data_item; - - /* events.identifier */ - install_cjson_item_string((void**)&event->identifier, event_item_obj, string_identifier); -#ifndef LITE_THING_MODEL - /* events.name */ - install_cjson_item_string((void**)&event->name, event_item_obj, string_name); - /* events.desc */ - install_cjson_item_string((void**)&event->desc, event_item_obj, string_desc); -#endif - /* events.method */ - install_cjson_item_string((void**)&event->method, event_item_obj, string_method); - /* events.required */ - install_cjson_item_bool((void*)&event->required, event_item_obj, string_required); - /* events.type */ - install_cjson_item_string((void**)&event->event_type_str, event_item_obj, string_type); - if (strcmp(event->event_type_str, string_info) == 0) { - event->event_type = event_type_info; - } - - else if (strcmp(event->event_type_str, string_alert) == 0) { - event->event_type = event_type_alert; - } - - else if (strcmp(event->event_type_str, string_error) == 0) { - event->event_type = event_type_error; - } -#ifdef LITE_THING_MODEL - if (strcmp(event->method, string_thing_event_property_post) == 0) return; -#endif - output_data_array_obj = cJSON_GetObjectItem(event_item_obj, string_outputData); - if (output_data_array_obj) { - assert(cJSON_IsArray(output_data_array_obj)); - output_data_array_size = cJSON_GetArraySize(output_data_array_obj); - event->event_output_data_num = output_data_array_size; - if (event->event_output_data_num == 0) { - return; - } - event->event_output_data = (lite_property_t*)dm_lite_calloc(event->event_output_data_num, sizeof(lite_property_t)); - assert(event->event_output_data); - - if (event->event_output_data == NULL) { - event->event_output_data_num = 0; - return; - } - } - - for (output_data_index = 0; output_data_index < event->event_output_data_num; ++output_data_index) { - output_data_item = event->event_output_data + output_data_index; - output_data_item_obj = cJSON_GetArrayItem(output_data_array_obj, output_data_index); - install_cjson_obj_lite_property(output_data_item, output_data_item_obj); - } -} - -static void parse_cjson_obj_to_dsl_template_events(void* _self, const cJSON* cjson_obj) -{ - dm_thing_t* self = _self; - const cJSON* events_obj = cjson_obj; - cJSON* event_item_obj; - int events_array_size; - int index; - event_t* event; - - events_array_size = cJSON_GetArraySize(events_obj); - - self->dsl_template.event_number = events_array_size; - - if (self->dsl_template.event_number == 0) return; - - self->dsl_template.events = (event_t*)dm_lite_calloc(self->dsl_template.event_number, sizeof(event_t)); - - assert(self->dsl_template.events); - - if (self->dsl_template.events == NULL) { - self->dsl_template.event_number = 0; - dm_log_err("self->dsl_template.events malloc fail"); - return; - } - - for (index = 0; index < self->dsl_template.event_number; ++index) { - event_item_obj = cJSON_GetArrayItem(events_obj, index); - if (event_item_obj) { - event = self->dsl_template.events + index; - - install_cjson_obj_event(event, event_item_obj); - } - } -} - -static void install_cjson_obj_service(service_t* dst, const cJSON* const cjson_obj) -{ - const cJSON* service_item_obj = cjson_obj; - service_t* service = dst; - cJSON* output_data_array_obj; - cJSON* output_data_item_obj; - cJSON* input_data_array_obj; - cJSON* input_data_item_obj; - int output_data_array_size, input_data_array_size; - int output_data_index, input_data_index; - lite_property_t* output_data_item; - input_data_t* input_data_item; - - /* service.identifier */ - install_cjson_item_string((void**)&service->identifier, service_item_obj, string_identifier); -#ifndef LITE_THING_MODEL - /* service.name */ - install_cjson_item_string((void**)&service->name, service_item_obj, string_name); - /* service.desc */ - install_cjson_item_string((void**)&service->desc, service_item_obj, string_desc); -#endif - /* service.method */ - install_cjson_item_string((void**)&service->method, service_item_obj, string_method); - /* service.call_type */ - install_cjson_item_string((void**)&service->call_type, service_item_obj, "callType"); - /* service.required */ - install_cjson_item_bool((void*)&service->required, service_item_obj, string_required); - - if (strcmp(service->method, string_thing_service_property_set) == 0) { - service->service_type = service_type_property_set; - } - - else if (strcmp(service->method, string_thing_service_property_get) == 0) { - service->service_type = service_type_property_get; - } - - else { - service->service_type = service_type_others; - } - - /* output data process */ - output_data_array_obj = cJSON_GetObjectItem(service_item_obj, string_outputData); -#ifdef LITE_THING_MODEL - if (output_data_array_obj && service->service_type != service_type_property_get) { -#else - if (output_data_array_obj) { -#endif - assert(cJSON_IsArray(output_data_array_obj)); - output_data_array_size = cJSON_GetArraySize(output_data_array_obj); - service->service_output_data_num = output_data_array_size; - if (service->service_output_data_num) { - service->service_output_data = (lite_property_t*)dm_lite_calloc(service->service_output_data_num, sizeof(lite_property_t)); - assert(service->service_output_data); - if (service->service_output_data == NULL) { - service->service_output_data_num = 0; - } - } else { - service->service_output_data = NULL; - } - } - - for (output_data_index = 0; output_data_index < service->service_output_data_num; ++output_data_index) { - output_data_item = service->service_output_data + output_data_index; - output_data_item_obj = cJSON_GetArrayItem(output_data_array_obj, output_data_index); - if (output_data_item_obj) { - install_cjson_obj_lite_property(output_data_item, output_data_item_obj); - } - } - /* input data process */ - input_data_array_obj = cJSON_GetObjectItem(service_item_obj, string_inputData); - service->service_input_data_num = 0; -#ifdef LITE_THING_MODEL - if (input_data_array_obj && service->service_type != service_type_property_set) { -#else - if (input_data_array_obj) { -#endif - assert(cJSON_IsArray(input_data_array_obj)); - input_data_array_size = cJSON_GetArraySize(input_data_array_obj); - service->service_input_data_num = input_data_array_size; - service->service_input_data = (input_data_t*)dm_lite_calloc(service->service_input_data_num, sizeof(input_data_t)); - if (service->service_input_data == NULL) { - service->service_input_data_num = 0; - } - } - for (input_data_index = 0; input_data_index < service->service_input_data_num; ++input_data_index) { - input_data_item = service->service_input_data + input_data_index; - input_data_item_obj = cJSON_GetArrayItem(input_data_array_obj, input_data_index); - if (input_data_item_obj) { - install_cjson_item_input_data(input_data_item, input_data_item_obj, service->service_type); - } - } -} - -static void parse_cjson_obj_to_dsl_template_services(void* _self, const cJSON* cjson_obj) -{ - dm_thing_t* self = _self; - const cJSON* services_obj = cjson_obj; - cJSON* service_item_obj; - - int sercives_array_size; - int index; - service_t* service; - - sercives_array_size = cJSON_GetArraySize(services_obj); - - self->dsl_template.service_number = sercives_array_size; - self->dsl_template.services = (service_t*)dm_lite_calloc(self->dsl_template.service_number, sizeof(service_t)); - - if (self->dsl_template.services == NULL) { - self->dsl_template.service_number = 0; - dm_log_err("self->dsl_template.events malloc fail"); - return; - } - - for (index = 0; index < self->dsl_template.service_number; ++index) { - service_item_obj = cJSON_GetArrayItem(services_obj, index); - if (service_item_obj) { - service = self->dsl_template.services + index; - install_cjson_obj_service(service, service_item_obj); - } - } -} - -static int parse_cjson_obj_to_dsl_template(void* _self, const cJSON* cjson_obj) -{ - if(!_self || !cjson_obj) { - return -1; - } - - dm_thing_t* self = _self; - const cJSON* root_obj = cjson_obj; - cJSON* profile_obj; - cJSON* properties_obj; - cJSON* events_obj; - cJSON* sercives_obj; - - /* schema */ -#ifdef LITE_THING_MODEL - self->dsl_template.schema = NULL; - self->dsl_template.link = NULL; -#else - if(0 != install_cjson_item_string((void**)&self->dsl_template.schema, root_obj, "schema")) { - dm_log_err("parse schema fail"); - } - - /* link */ - if(0 != install_cjson_item_string((void**)&self->dsl_template.link, root_obj, "link")) { - dm_log_err("parse link fail"); - } -#endif - /* profile */ - profile_obj = cJSON_GetObjectItem(root_obj, "profile"); - if (profile_obj) { - install_cjson_item_string((void**)&self->dsl_template.profile.product_key, profile_obj, "productKey"); - install_cjson_item_string((void**)&self->dsl_template.profile.device_name, profile_obj, "deviceName"); - } else { - self->dsl_template.profile.product_key = NULL; - self->dsl_template.profile.device_name = NULL; - } - - /* properties */ - properties_obj = cJSON_GetObjectItem(root_obj, string_properties); - if (properties_obj) { - assert(cJSON_IsArray(properties_obj)); - parse_cjson_obj_to_dsl_template_properties(self, properties_obj); - } - else { - return -1; - } - /* events */ - events_obj = cJSON_GetObjectItem(root_obj, string_events); - if (events_obj) { - assert(cJSON_IsArray(events_obj)); - parse_cjson_obj_to_dsl_template_events(self, events_obj); - } else { - return -1; - } - /* events */ - sercives_obj = cJSON_GetObjectItem(root_obj, string_services); - if (sercives_obj) { - assert(cJSON_IsArray(sercives_obj)); - parse_cjson_obj_to_dsl_template_services(self, sercives_obj); - }else { - return -1; - } - - return 0; -} - -/* set dsl to thing model. */ -static int dm_thing_set_dsl_string(void* _self, const char* dsl, int dsl_str_len) -{ - int ret = -1; - dm_thing_t* self = _self; - - self->_json_object = cJSON_Parse(dsl); - - assert(self->_json_object); - ret = parse_cjson_obj_to_dsl_template(self, self->_json_object); - - cJSON_Delete(self->_json_object); - self->_json_object = 0; - - return ret; -} - -#endif - -/* get dsl from thing model. */ -static void* dm_thing_get_dsl_string(void* _self) -{ - dm_thing_t* self = _self; - - /* TODO */ - - return self->_dsl_string; -} - -static int dm_thing_get_property_number(const void* _self) -{ - const dm_thing_t* self = _self; - - return self->dsl_template.property_number; -} - -static int dm_thing_get_service_number(const void* _self) -{ - const dm_thing_t* self = _self; - - return self->dsl_template.service_number; -} - -static int dm_thing_get_event_number(const void* _self) -{ - const dm_thing_t* self = _self; - - return self->dsl_template.event_number; -} - -static int get_array_index_by_identifier(const char* identifier, char** arrpre_pos) -{ - int index = 0; - int ret = -1; - if(!identifier) { - return ret; - } - const char* p; - char* arr_pre = NULL; - char* arr_suf = NULL; - - arr_pre = strchr(identifier, '['); - if(arr_pre) { - arr_suf = strchr(identifier, ']'); - } - - if(arr_pre && arr_suf && arr_suf - arr_pre > 1) { - for(p = arr_pre + 1; p < arr_suf; p++) { - if (*p > '9' || *p < '0') { - return ret; - } - index *= 10; - index += *p - '0'; - } - ret = index; - *arrpre_pos = arr_pre; - } - - return ret; -} - - -static void* dm_thing_get_property_by_identifier(const void* _self, const char* const identifier) -{ - const dm_thing_t* self = _self; - property_t* property = NULL; - lite_property_t* lite_property = NULL; - size_t property_number = self->dsl_template.property_number; - size_t data_type_specs_number; - int index; - int arr_index; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - char* arrpre_pos = NULL; - - if (property_number == 0 || strlen(identifier) >= MAX_IDENTIFIER_LENGTH) { - return NULL; - } - - strcpy(id_buff, identifier); - - if (strchr(identifier, DEFAULT_DSL_DELIMITER)) { - p = strtok(id_buff, delimeter); - - for (index = 0; index < property_number; ++index) { - property = self->dsl_template.properties + index; - if (property) { - if (strcmp(property->identifier, p) == 0) { - break; - } - } - } - if (property && index < property_number) { - p = strtok(NULL, delimeter); - arr_index = get_array_index_by_identifier(p, &arrpre_pos); - data_type_specs_number = property->data_type.data_type_specs_number; - for (index = 0; index < data_type_specs_number; ++index) { - lite_property = (lite_property_t*)property->data_type.specs + index; - if (-1 != arr_index && strncmp(lite_property->identifier, p, arrpre_pos - p) == 0 && - lite_property->data_type.type == data_type_type_array) { - return lite_property; - }else if(strcmp(lite_property->identifier, p) == 0){ - return lite_property; - } - } - } - } else { - for (index = 0; index < property_number; ++index) { - property = self->dsl_template.properties + index; - arr_index = get_array_index_by_identifier(identifier, &arrpre_pos); - if (property) { - if(-1 != arr_index && strncmp(property->identifier, identifier, arrpre_pos - identifier) == 0 && - property->data_type.type == data_type_type_array) { - return property; - }else if (strcmp(property->identifier, identifier) == 0) { - return property; - } - } - } - } - - return NULL; -} - -static int dm_thing_get_property_identifier_by_index(const void* _self, int index, char* identifier) -{ - const dm_thing_t* self = _self; - property_t* property = NULL; - int ret = -1; - - if (index < self->dsl_template.property_number) { - property = self->dsl_template.properties + index; - strcpy(identifier, property->identifier); - ret = 0; - } - - return ret; -} - -static void* dm_thing_get_service_by_identifier(const void* _self, const char* const identifier) -{ - const dm_thing_t* self = _self; - service_t* service = NULL; - lite_property_t* lite_property = NULL; - input_data_t* input_data; - size_t service_number = self->dsl_template.service_number; - size_t service_output_data_num; - size_t service_input_data_num; - int index; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - char* p; - char* p_m; - char* p_l; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - char* arrpre_pos = NULL; - int arr_index; - if (service_number == 0 || strlen(identifier) >= MAX_IDENTIFIER_LENGTH) return NULL; - - strcpy(id_buff, identifier); - - if (strchr(identifier, DEFAULT_DSL_DELIMITER)) { - p = strtok(id_buff, delimeter); - - for (index = 0; index < service_number; ++index) { - service = self->dsl_template.services + index; - if (service) { - if (strcmp(service->identifier, p) == 0) { - break; - } - } - } - p_m = strtok(NULL, delimeter); - p_l = strtok(NULL, delimeter); - if (p_m && service && index < service_number && (p_l ? strcmp(p_l, string_input) == 0 : 1)) { - service_input_data_num = service->service_input_data_num; - arr_index = get_array_index_by_identifier(p_m, &arrpre_pos); - for (index = 0; index < service_input_data_num; ++index) { - input_data = service->service_input_data + index; - lite_property = &input_data->lite_property; - if (strcmp(lite_property->identifier, p_m) == 0 || (-1 != arr_index && strncmp(lite_property->identifier, p_m, arrpre_pos - p_m) == 0)) { - return lite_property; - } - } - } - if (p_m && service && index < service_number && (p_l ? strcmp(p_l, string_output) == 0 : 1)) { - service_output_data_num = service->service_output_data_num; - arr_index = get_array_index_by_identifier(p_m, &arrpre_pos); - for (index = 0; index < service_output_data_num; ++index) { - lite_property = service->service_output_data + index; - - if (strcmp(lite_property->identifier, p_m) == 0 || (-1 != arr_index && strncmp(lite_property->identifier, p_m, arrpre_pos - p_m) == 0)) { - return lite_property; - } - } - } - } else { - for (index = 0; index < service_number; ++index) { - service = self->dsl_template.services + index; - if (service) { - if (strcmp(service->identifier, identifier) == 0) { - return service; - } - } - } - } - - return NULL; -} - -static int dm_thing_get_service_identifier_by_index(const void* _self, int index, char* identifier) -{ - const dm_thing_t* self = _self; - service_t* service = NULL; - int ret = -1; - - assert(index < self->dsl_template.service_number); - - if (index < self->dsl_template.service_number) { - service = self->dsl_template.services + index; - strcpy(identifier, service->identifier); - ret = 0; - } - - return ret; -} - -static void* dm_thing_get_event_by_identifier(const void* _self, const char* const identifier) -{ - const dm_thing_t* self = _self; - int arr_index; - event_t* event = NULL; - lite_property_t* lite_property = NULL; - size_t event_number = self->dsl_template.event_number; - size_t event_output_data_num; - int index; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - char* arrpre_pos = NULL; - - if (event_number == 0 || strlen(identifier) >= MAX_IDENTIFIER_LENGTH) return NULL; - - strcpy(id_buff, identifier); - - if (strchr(identifier, DEFAULT_DSL_DELIMITER)) { - p = strtok(id_buff, delimeter); - - for (index = 0; index < event_number; ++index) { - event = self->dsl_template.events + index; - if (event) { - if (strcmp(event->identifier, p) == 0) { - break; - } - } - } - if (event && index < event_number) { - p = strtok(NULL, delimeter); - event_output_data_num = event->event_output_data_num; - arr_index = get_array_index_by_identifier(p, &arrpre_pos); - for (index = 0; index < event_output_data_num; ++index) { - lite_property = event->event_output_data + index; - if (-1 != arr_index && strncmp(lite_property->identifier, p, arrpre_pos - p) == 0 && - lite_property->data_type.type == data_type_type_array) { - return lite_property; - }else if (strcmp(lite_property->identifier, p) == 0) { - return lite_property; - } - } - } - } else { - for (index = 0; index < event_number; ++index) { - event = self->dsl_template.events + index; - if (event) { - if (strcmp(event->identifier, identifier) == 0) { - return event; - } - } - } - } - - return NULL; -} - -static int dm_thing_get_event_identifier_by_index(const void* _self, int index, char* identifier) -{ - const dm_thing_t* self = _self; - event_t* event = NULL; - int ret = -1; - - if (index < self->dsl_template.event_number) { - event = self->dsl_template.events + index; - strcpy(identifier, event->identifier); - ret = 0; - } - - return ret; -} - -static int dm_thing_get_schema(const void* _self, char* schema) -{ - const dm_thing_t* self = _self; - int ret = -1; - - assert(self->dsl_template.schema); - - if (self->dsl_template.schema) { - strcpy(schema, self->dsl_template.schema); - ret = 0; - } - return ret; -} - -static int dm_thing_get_link(const void* _self, char* link) -{ - const dm_thing_t* self = _self; - int ret = -1; - - assert(self->dsl_template.link); - - if (self->dsl_template.link) { - strcpy(link, self->dsl_template.link); - ret = 0; - } - return ret; -} - -static int dm_thing_get_product_key(const void* _self, char* product_key) -{ - const dm_thing_t* self = _self; - int ret = -1; - - assert(self->dsl_template.profile.product_key); - - if (self->dsl_template.profile.product_key) { - strcpy(product_key, self->dsl_template.profile.product_key); - ret = 0; - } - - return ret; -} - -static char* dm_thing_return_product_key(const void* _self) -{ - const dm_thing_t* self = _self; - - if (self->dsl_template.profile.product_key) { - return self->dsl_template.profile.product_key; - } - - return NULL; -} - -static int dm_thing_get_device_name(const void* _self, char* device_name) -{ - const dm_thing_t* self = _self; - int ret = -1; - - if (self->dsl_template.profile.device_name) { - strcpy(device_name, self->dsl_template.profile.device_name); - ret = 0; - } - return ret; -} - -static char* dm_thing_return_device_name(const void* _self) -{ - const dm_thing_t* self = _self; - - if (self->dsl_template.profile.device_name) { - return self->dsl_template.profile.device_name; - } - - return NULL; -} - -static int set_array_item_value(lite_property_t *lite_property, int arr_index, const void* value, const char* value_str) -{ - int ret = -1; - int val_int; - char temp_buf[24] = {0}; - int alloc_size; - double val_double; - float val_float; - int text_length; - const char* val_char_p; - data_type_x_t* data_type_x; - - if(!lite_property || !(value || value_str) || \ - lite_property->data_type.type != data_type_type_array || - arr_index < 0 ||arr_index >= lite_property->data_type.value.data_type_array_t.size) { - dm_log_err("invalid param"); - return ret; - } - - data_type_x = &lite_property->data_type.value; - switch(lite_property->data_type.value.data_type_array_t.item_type) { - case data_type_type_int: - val_int = value ? *(const int*)value : atoi(value_str); - *((int*)data_type_x->data_type_array_t.array + arr_index) = val_int; - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", val_int); - alloc_size = strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; - *((char**)data_type_x->data_type_array_t.value_str + arr_index) = (char*)dm_lite_calloc(1, alloc_size); - dm_snprintf(*((char**)data_type_x->data_type_array_t.value_str + arr_index), alloc_size, "%d", val_int); - ret = 0; - break; - case data_type_type_double: - val_double = value ? *(const double*)value : atof(value_str); - *((double*)data_type_x->data_type_array_t.array + arr_index) = val_double; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.16lf", val_double); - alloc_size = strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; - *((char**)data_type_x->data_type_array_t.value_str + arr_index) = (char*)dm_lite_calloc(1, alloc_size); - dm_snprintf(*((char**)data_type_x->data_type_array_t.value_str + arr_index), alloc_size, "%.16lf", val_double); - ret = 0; - break; - case data_type_type_float: - val_float = value ? *(const float*)value : atof(value_str); - *((float*)data_type_x->data_type_array_t.array + arr_index) = val_float; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.7f", val_float); - alloc_size = strlen(temp_buf) + DM_THING_EXTENTED_ROOM_FOR_STRING_MALLOC; - *((char**)data_type_x->data_type_array_t.value_str + arr_index) = (char*)dm_lite_calloc(1, alloc_size); - dm_snprintf(*((char**)data_type_x->data_type_array_t.value_str + arr_index), alloc_size, "%.7f", val_float); - ret = 0; - break; - case data_type_type_text: - - val_char_p = value ? (const char*)value : value_str; - text_length = strlen(val_char_p); - - if (*((char**)data_type_x->data_type_array_t.array + arr_index)) { - dm_lite_free(*((char**)data_type_x->data_type_array_t.array + arr_index)); - *((char**)data_type_x->data_type_array_t.array + arr_index) = NULL; - } - *((char**)data_type_x->data_type_array_t.array + arr_index) = dm_lite_calloc(1, text_length + 1); - if (*((char**)data_type_x->data_type_array_t.array + arr_index) == NULL) { - dm_log_err("calloc %d byte failed", text_length + 1); - break; - } - strcpy(*((char**)data_type_x->data_type_array_t.array + arr_index), val_char_p); - ret = 0; - break; - default: - dm_log_err("don't support %d", lite_property->data_type.type); - break; - } - return ret; -} - - - -static int set_lite_property_value(void* _self, void* property, const void* value, const char* value_str) -{ - dm_thing_t* self = _self; - lite_property_t* lite_property = NULL; - lite_property_t* lite_sub_property = NULL; - data_type_type_t type; - data_type_x_t* data_type_x; - int arr_index; - int val_int; - float val_float; - double val_double; - unsigned long long val_long; - const char* val_char_p; - int text_length; - int index; - char* enum_item_key_str; - const char* type_str[] = { - string_text, string_enum, string_bool, string_float, string_double, string_int, string_date, string_struct, string_array - }; - - assert(property); - - if (property == NULL) return -1; - - lite_property = property; - data_type_x = &lite_property->data_type.value; - type = lite_property->data_type.type; - - dm_log_debug("set property@%p\ttype = %d(%s)\n", lite_property, type, type_str[type]); - - /* at least one input is not null. */ - if (value == NULL && value_str == NULL) { - return -1; - } - - switch (type) { - case data_type_type_int: - val_int = value ? *(const int*)value : atoi(value_str); - val_int = val_int > data_type_x->data_type_int_t.max ? data_type_x->data_type_int_t.max : - (val_int < data_type_x->data_type_int_t.min ? data_type_x->data_type_int_t.min : val_int); - data_type_x->data_type_int_t.value = val_int; - dm_sprintf(data_type_x->data_type_int_t.value_str, "%d", data_type_x->data_type_int_t.value); - break; - case data_type_type_float: - val_float = value ? *(const float*)value : atof(value_str); - val_float = val_float > data_type_x->data_type_float_t.max ? data_type_x->data_type_float_t.max : - (val_float < data_type_x->data_type_float_t.min ? data_type_x->data_type_float_t.min : val_float); - data_type_x->data_type_float_t.value = val_float; - sprintf_float_double_precise(data_type_x->data_type_float_t.value_str, data_type_x->data_type_float_t.value, - data_type_x->data_type_float_t.precise); - break; - case data_type_type_double: - val_double = value ? *(const double*)value : atof(value_str); - val_double = val_double > data_type_x->data_type_double_t.max ? data_type_x->data_type_double_t.max : - (val_double < data_type_x->data_type_double_t.min ? data_type_x->data_type_double_t.min : val_double); - data_type_x->data_type_double_t.value = val_double; - sprintf_float_double_precise(data_type_x->data_type_double_t.value_str, data_type_x->data_type_double_t.value, - data_type_x->data_type_double_t.precise); - break; - case data_type_type_bool: - val_int = value ? *(const int*)value : atoi(value_str); - if (val_int) { - data_type_x->data_type_bool_t.value = 1; - dm_sprintf(data_type_x->data_type_bool_t.value_str, "%d", 1); - } else { - data_type_x->data_type_bool_t.value = 0; - dm_sprintf(data_type_x->data_type_bool_t.value_str, "%d", 0); - } - - break; - case data_type_type_enum: - val_int = value ? *(const int*)value : atoi(value_str); - /* check if match predefined keys. */ - for (index = 0; index < data_type_x->data_type_enum_t.enum_item_number; ++index) { - enum_item_key_str = *(data_type_x->data_type_enum_t.enum_item_key + index); - if (val_int == atoi(enum_item_key_str)) { - data_type_x->data_type_enum_t.value = val_int; - dm_sprintf(data_type_x->data_type_enum_t.value_str, "%d", data_type_x->data_type_enum_t.value); - return 0; - } - } - return -1; - break; - case data_type_type_text: - val_char_p = value ? (const char*)value : value_str; - text_length = strlen(val_char_p); - /* check if length restrict satisfied. */ - if (text_length <= data_type_x->data_type_text_t.length) { - if (data_type_x->data_type_text_t.value) { - dm_lite_free(data_type_x->data_type_text_t.value); - data_type_x->data_type_text_t.value = NULL; - } - - data_type_x->data_type_text_t.value = dm_lite_calloc(1, text_length + 1); - assert(data_type_x->data_type_text_t.value); - if (data_type_x->data_type_text_t.value == NULL) { - return -1; - } - - strcpy(data_type_x->data_type_text_t.value, val_char_p); - } else { - return -1; - } - break; - case data_type_type_date: - val_long = value ? *(const unsigned long long*)value : atoll(value_str); - data_type_x->data_type_date_t.value = val_long; - dm_lltoa(data_type_x->data_type_date_t.value, data_type_x->data_type_date_t.value_str, 10); - break; - case data_type_type_struct: - for(index = 0; index < lite_property->data_type.data_type_specs_number; ++index) { - lite_sub_property = (lite_property_t*)lite_property->data_type.specs + index; - -#ifdef CMP_SUPPORT_MEMORY_MAGIC - val_char_p = LITE_json_value_of_ext(lite_sub_property->identifier, (char*)value_str, MEM_MAGIC, DM_MODULE_NAME); -#else - val_char_p = LITE_json_value_of(lite_sub_property->identifier, (char*)value_str); -#endif - if(!val_char_p) return -1; - set_lite_property_value(self, lite_sub_property, NULL, val_char_p); - LITE_free(val_char_p); - } - break; - case data_type_type_array: - arr_index = self->_arr_index; - if(arr_index == -1) { - return -1; - } - if(-1 == set_array_item_value(lite_property, arr_index, value, value_str)) { - return -1; - } - break; - default: - break; - } - - return 0; -} - -static int dm_thing_set_property_value(void* _self, void* _property, const void* value, const char* value_str) -{ - dm_thing_t* self = _self; - property_t* property = _property; - lite_property_t* lite_property = NULL; - - assert(property); -#ifdef PROPERTY_ACCESS_MODE_ENABLED - if (property->access_mode == property_access_mode_r) { - dm_log_err("try to set value to readonly property, id:%s\n", property->identifier); - - return -1; - } -#endif - lite_property = (lite_property_t*)property; - - set_lite_property_value(self, lite_property, value, value_str); - - return 0; -} - -static int dm_thing_set_property_value_by_identifier(void* _self, const char* const identifier, const void* value, const char* value_str) -{ - dm_thing_t* self = _self; - lite_property_t* lite_property; - char *arrpre_pos; - int ret; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - property_t* property; - - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - const char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - - if (strchr(identifier, DEFAULT_DSL_DELIMITER)) { - strcpy(id_buff, identifier); - p = strtok(id_buff, delimeter); - } else { - p = identifier; - } - - /* do some checks. */ - property = dm_thing_get_property_by_identifier(self, p); - if (property->access_mode == property_access_mode_r) { - dm_log_err("try to set value to readonly property, id:%s\n", property->identifier); - return -1; - } -#endif - self->_arr_index = get_array_index_by_identifier(identifier, &arrpre_pos); - lite_property = dm_thing_get_property_by_identifier(self, identifier); - - if (lite_property == NULL) { - dm_log_err("property(%s) not find", identifier); - return -1; - } - ret = set_lite_property_value(self, lite_property, value, value_str); - self->_arr_index = -1; - return ret; -} - -static int get_array_item_value(const lite_property_t *lite_property, int arr_index, void* value, char** value_str) -{ - int val_int; - int ret = -1; - const data_type_x_t* data_type_x; - double val_double; - float val_float; - char *dst_text = NULL; - if (!lite_property || !(value || value_str) || lite_property->data_type.type != data_type_type_array || arr_index < 0 || arr_index >= lite_property->data_type.value.data_type_array_t.size) { - dm_log_err("invalid param"); - return ret; - } - data_type_x = &lite_property->data_type.value; - data_type_type_t type = data_type_x->data_type_array_t.item_type; - - if(type == data_type_type_int) { - val_int = *((int*)data_type_x->data_type_array_t.array + arr_index); - if (value) { - *(int*)value = val_int; - } - if (value_str) { - *value_str = *((char**)data_type_x->data_type_array_t.value_str + arr_index); - } - ret = 0; - }else if(type == data_type_type_double) { - val_double = *((double*)data_type_x->data_type_array_t.array + arr_index); - if (value) { - *(double*)value = val_double; - } - if (value_str) { - *value_str = *((char**)data_type_x->data_type_array_t.value_str + arr_index); - } - - ret = 0; - }else if(type == data_type_type_float) { - val_float = *((float*)data_type_x->data_type_array_t.array + arr_index); - if (value) { - *(float*)value = val_float; - } - if (value_str) { - *value_str = *((char**)data_type_x->data_type_array_t.value_str + arr_index); - } - - ret = 0; - }else if(type == data_type_type_text) { - dst_text = *((char**)data_type_x->data_type_array_t.array + arr_index); - if (value) { - if(dst_text) { - strcpy(value, dst_text); - }else { - *((char*)value) = '\0'; - } - } - if (value_str) { - *value_str = dst_text; - } - ret = 0; - }else { - dm_log_err("dont't support %d type", type); - } - return ret; -} - -static int dm_thing_get_lite_property_value(const void* _self, const void* const property, void* value, char** value_str) -{ - const dm_thing_t* self = _self; - const lite_property_t* lite_property = NULL; - data_type_type_t type; - const data_type_x_t* data_type_x; - int val_int; - float val_float; - double val_double; - int arr_index; - int ret = -1; - const char* type_str[] = { - string_text, string_enum, string_bool, string_float, string_double, string_int, string_date, string_struct, string_array - }; - - self = self; - if (property == NULL) { - dm_log_err("property(%p) not exit", property); - return -1; - } - - lite_property = property; - data_type_x = &lite_property->data_type.value; - type = lite_property->data_type.type; - - dm_log_debug("get property@%p\ttype:%d(%s)\n", lite_property, type, type_str[type]); - switch (type) { - case data_type_type_int: - val_int = data_type_x->data_type_int_t.value; - if (value) { - *(int*)value = val_int; - } - if (value_str) { - *value_str = data_type_x->data_type_int_t.value_str; - } - - ret = 0; - break; - case data_type_type_float: - val_float = data_type_x->data_type_float_t.value; - if (value) { - *(float*)value = val_float; - } - if (value_str) { - *value_str = data_type_x->data_type_float_t.value_str; - } - - ret = 0; - break; - case data_type_type_double: - val_double = data_type_x->data_type_double_t.value; - if (value) { - *(double*)value = val_double; - } - if (value_str) { - *value_str = data_type_x->data_type_double_t.value_str; - } - - ret = 0; - break; - case data_type_type_bool: - if (value) { - *(int*)value = 0; - if (data_type_x->data_type_bool_t.value) { - *(int*)value = 1; - } - } - if (value_str) { - *value_str = data_type_x->data_type_bool_t.value_str; - } - ret = 0; - break; - case data_type_type_enum: - if (value) { - *(int*)value = data_type_x->data_type_enum_t.value; - } - if (value_str) { - *value_str = data_type_x->data_type_enum_t.value_str; - } - ret = 0; - break; - case data_type_type_text: - if (value) { - if (data_type_x->data_type_text_t.value) { - strcpy(value, data_type_x->data_type_text_t.value); - } - } - if (value_str) { - *value_str = data_type_x->data_type_text_t.value; - } - ret = 0; - break; - case data_type_type_date: - if (value) { - *(unsigned long long*)value = data_type_x->data_type_date_t.value; - } - if (value_str) { - if (data_type_x->data_type_date_t.value_str) { - *value_str = data_type_x->data_type_date_t.value_str; - } - } - ret = 0; - break; - case data_type_type_array: - arr_index = self->_arr_index; - if(arr_index == -1) { - return -1; - } - - ret = get_array_item_value(lite_property, arr_index, value, value_str); - - break; - default: - *value_str = NULL; - break; - } - - return ret; - -} - -static int dm_thing_get_property_value(const void* _self, const void* const _property, void* value, char** value_str) -{ - const dm_thing_t* self = _self; - const lite_property_t* lite_property = NULL; - const property_t* property = _property; - - assert(property); -#ifdef PROPERTY_ACCESS_MODE_ENABLED - if (property->access_mode == property_access_mode_w) { - dm_log_err("try to set value to write only property, id:%s\n", property->identifier); - - return -1; - } -#endif - lite_property = (lite_property_t*)property; - - return dm_thing_get_lite_property_value(self, lite_property, value, value_str); -} - -static int dm_thing_get_property_value_by_identifier(const void* _self, const char* const identifier, void* value, char** value_str) -{ - const dm_thing_t* self = _self; - const lite_property_t* lite_property; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - property_t* property; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - const char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - - if (strchr(identifier, DEFAULT_DSL_DELIMITER)) { - strcpy(id_buff, identifier); - p = strtok(id_buff, delimeter); - } else { - p = identifier; - } - - /* do some checks. */ - property = dm_thing_get_property_by_identifier(self, p); - if (property->access_mode == property_access_mode_w) { - dm_log_err("try to set value to write only property, id:%s\n", property->identifier); - return -1; - } -#endif - lite_property = dm_thing_get_property_by_identifier(self, identifier); - - if (lite_property == NULL) { - dm_log_err("property(%s) not find", identifier); - return -1; - } - - return dm_thing_get_lite_property_value(self, lite_property, value, value_str); -} - -static void dm_thing_property_iterator(void* _self, handle_item_t handle_fp, va_list* params) -{ - dm_thing_t* self = _self; - property_t* property = NULL; - size_t property_number = self->dsl_template.property_number; - int index; - - for (index = 0; index < property_number; ++index) { - property = self->dsl_template.properties + index; - if (property) { - va_list args; - va_copy(args, *params); - handle_fp(property, index, &args); - va_end(args); - } - } -} - -static void dm_thing_event_iterator(void* _self, handle_item_t handle_fp, va_list* params) -{ - dm_thing_t* self = _self; - event_t* event = NULL; - size_t event_number = self->dsl_template.event_number; - int index; - - for (index = 0; index < event_number; ++index) { - event = self->dsl_template.events + index; - if (event) { - va_list args; - va_copy(args, *params); - handle_fp(event, index, &args); - va_end(args); - } - } -} - -static void dm_thing_service_iterator(void* _self, handle_item_t handle_fp, va_list* params) -{ - dm_thing_t* self = _self; - service_t* service = NULL; - size_t service_number = self->dsl_template.service_number; - int index; - - for (index = 0; index < service_number; ++index) { - service = self->dsl_template.services + index; - if (service) { - va_list args; - va_copy(args, *params); - handle_fp(service, index, &args); - va_end(args); - } - } -} - -void property_iterator(void* _self, handle_item_t handle_fp, ...) -{ - dm_thing_t* self = _self; - - va_list params; - va_start(params, handle_fp); - - dm_thing_property_iterator(self, handle_fp, ¶ms); - - va_end(params); -} - -void event_iterator(void* _self, handle_item_t handle_fp, ...) -{ - dm_thing_t* self = _self; - - va_list params; - va_start(params, handle_fp); - - dm_thing_event_iterator(self, handle_fp, ¶ms); - - va_end(params); -} - -void service_iterator(void* _self, handle_item_t handle_fp, ...) -{ - dm_thing_t* self = _self; - - va_list params; - va_start(params, handle_fp); - - dm_thing_service_iterator(self, handle_fp, ¶ms); - - va_end(params); -} -static void property_free_array_type(data_type_x_t* data_type_x) -{ - char *p = NULL; - int index; - if (!data_type_x) return; - switch (data_type_x->data_type_array_t.item_type) { - case data_type_type_int: - case data_type_type_double: - case data_type_type_float: - if(data_type_x->data_type_array_t.value_str) { - dm_lite_free(data_type_x->data_type_array_t.value_str); - data_type_x->data_type_array_t.value_str = NULL; - } - if(data_type_x->data_type_array_t.array) { - dm_lite_free(data_type_x->data_type_array_t.array); - data_type_x->data_type_array_t.array = NULL; - } - break; - case data_type_type_text: - for(index = 0; index < data_type_x->data_type_array_t.size; index++) { - p = *((char**)data_type_x->data_type_array_t.array + index); - if (p) { - dm_lite_free(p); - } - } - if(data_type_x->data_type_array_t.array) { - dm_lite_free(data_type_x->data_type_array_t.array); - data_type_x->data_type_array_t.array = NULL; - } - break; - default: - dm_log_err("don't support %d type", data_type_x->data_type_array_t.item_type); - break; - } - -} -static void property_free_data_type_info(void* dst) -{ - data_type_t* data_type = dst; - data_type_x_t* data_type_x; - lite_property_t* lite_property; - int index; - assert(data_type); - - data_type_x = &data_type->value; - - switch (data_type->type) { - case data_type_type_int: -#ifdef LITE_THING_MODEL - if (data_type_x->data_type_int_t.value_str) { - dm_lite_free(data_type_x->data_type_int_t.value_str); - } -#else - if (data_type_x->data_type_int_t.min_str) { - dm_lite_free(data_type_x->data_type_int_t.min_str); - } - if (data_type_x->data_type_int_t.max_str) { - dm_lite_free(data_type_x->data_type_int_t.max_str); - } - if (data_type_x->data_type_int_t.value_str) { - dm_lite_free(data_type_x->data_type_int_t.value_str); - } - if (data_type_x->data_type_int_t.precise_str) { - dm_lite_free(data_type_x->data_type_int_t.precise_str); - } - if (data_type_x->data_type_int_t.unit) { - dm_lite_free(data_type_x->data_type_int_t.unit); - } - if (data_type_x->data_type_int_t.unit_name) { - dm_lite_free(data_type_x->data_type_int_t.unit_name); - } -#endif - break; - case data_type_type_float: -#ifdef LITE_THING_MODEL - if (data_type_x->data_type_float_t.value_str) { - dm_lite_free(data_type_x->data_type_float_t.value_str); - } -#else - if (data_type_x->data_type_float_t.min_str) { - dm_lite_free(data_type_x->data_type_float_t.min_str); - } - if (data_type_x->data_type_float_t.max_str) { - dm_lite_free(data_type_x->data_type_float_t.max_str); - } - if (data_type_x->data_type_float_t.value_str) { - dm_lite_free(data_type_x->data_type_float_t.value_str); - } - if (data_type_x->data_type_float_t.precise_str) { - dm_lite_free(data_type_x->data_type_float_t.precise_str); - } - if (data_type_x->data_type_float_t.unit) { - dm_lite_free(data_type_x->data_type_float_t.unit); - } - if (data_type_x->data_type_float_t.unit_name) { - dm_lite_free(data_type_x->data_type_float_t.unit_name); - } -#endif - break; - case data_type_type_double: -#ifdef LITE_THING_MODEL - if (data_type_x->data_type_double_t.value_str) { - dm_lite_free(data_type_x->data_type_double_t.value_str); - } -#else - if (data_type_x->data_type_double_t.min_str) { - dm_lite_free(data_type_x->data_type_double_t.min_str); - } - if (data_type_x->data_type_double_t.max_str) { - dm_lite_free(data_type_x->data_type_double_t.max_str); - } - if (data_type_x->data_type_double_t.value_str) { - dm_lite_free(data_type_x->data_type_double_t.value_str); - } - if (data_type_x->data_type_double_t.precise_str) { - dm_lite_free(data_type_x->data_type_double_t.precise_str); - } - if (data_type_x->data_type_double_t.unit) { - dm_lite_free(data_type_x->data_type_double_t.unit); - } - if (data_type_x->data_type_double_t.unit_name) { - dm_lite_free(data_type_x->data_type_double_t.unit_name); - } -#endif - break; - case data_type_type_enum: - for (index = 0; index < data_type_x->data_type_enum_t.enum_item_number; ++index) { - dm_lite_free(*(data_type_x->data_type_enum_t.enum_item_key + index)); - if (data_type_x->data_type_enum_t.enum_item_value && *(data_type_x->data_type_enum_t.enum_item_value + index)) { - dm_lite_free(*(data_type_x->data_type_enum_t.enum_item_value + index)); - } - } - if (data_type_x->data_type_enum_t.value_str) { - dm_lite_free(data_type_x->data_type_enum_t.value_str); - } - - if (data_type_x->data_type_enum_t.enum_item_number) { - dm_lite_free(data_type_x->data_type_enum_t.enum_item_key); - if (data_type_x->data_type_enum_t.enum_item_value) { - dm_lite_free(data_type_x->data_type_enum_t.enum_item_value); - } - } - break; - case data_type_type_bool: - for (index = 0; index < data_type_x->data_type_bool_t.bool_item_number; ++index) { - dm_lite_free(*(data_type_x->data_type_bool_t.bool_item_key + index)); - if (data_type_x->data_type_bool_t.bool_item_value && *(data_type_x->data_type_bool_t.bool_item_value + index)) { - dm_lite_free(*(data_type_x->data_type_bool_t.bool_item_value + index)); - } - } - if (data_type_x->data_type_bool_t.value_str) { - dm_lite_free(data_type_x->data_type_bool_t.value_str); - } - - if (data_type_x->data_type_bool_t.bool_item_number) { - dm_lite_free(data_type_x->data_type_bool_t.bool_item_key); - if (data_type_x->data_type_bool_t.bool_item_value) { - dm_lite_free(data_type_x->data_type_bool_t.bool_item_value); - } - } - break; - case data_type_type_text: -#ifdef LITE_THING_MODEL - if (data_type_x->data_type_text_t.length_str) { - dm_lite_free(data_type_x->data_type_text_t.length_str); - } - if (data_type_x->data_type_text_t.value) { - dm_lite_free(data_type_x->data_type_text_t.value); - } -#else - if (data_type_x->data_type_text_t.length_str) { - dm_lite_free(data_type_x->data_type_text_t.length_str); - } - if (data_type_x->data_type_text_t.value) { - dm_lite_free(data_type_x->data_type_text_t.value); - } - if (data_type_x->data_type_text_t.unit) { - dm_lite_free(data_type_x->data_type_text_t.unit); - } - if (data_type_x->data_type_text_t.unit_name) { - dm_lite_free(data_type_x->data_type_text_t.unit_name); - } -#endif - break; - case data_type_type_struct: - for (index = 0; index < data_type->data_type_specs_number; ++index) { - lite_property = (lite_property_t*)data_type->specs + index; - free_lite_property(lite_property); - } - if (data_type->data_type_specs_number) { - dm_lite_free(data_type->specs); - } - break; - case data_type_type_date: - if (data_type_x->data_type_date_t.value_str) { - dm_lite_free(data_type_x->data_type_date_t.value_str); - } - break; - case data_type_type_array: - property_free_array_type(data_type_x); - break; - default: - dm_printf("unsupported type:%s\n", data_type->type_str); - break; - } - - if (data_type->type_str) { - dm_lite_free(data_type->type_str); - } -} - -static void free_lite_property(void* _lite_property) -{ - lite_property_t* lite_property = _lite_property; - - assert(lite_property); - - if (lite_property) { - if (lite_property->identifier) { - dm_lite_free(lite_property->identifier); - } - if (lite_property->name) { - dm_lite_free(lite_property->name); - } - } - property_free_data_type_info(&lite_property->data_type); -} - -static void free_input_data(void* _input_data, service_type_t service_type) -{ - input_data_t* input_data = _input_data; - - assert(input_data); - - if (input_data) { - switch (service_type) { - case service_type_property_set: - free_property(&input_data->property_to_set, string_property, 2); - break; - case service_type_others: - free_lite_property(&input_data->lite_property); - break; - case service_type_property_get: - if (input_data->property_to_get_name) { - dm_lite_free(input_data->property_to_get_name); - } - break; - default: - break; - } - } -} - -static void free_property(void* _property, ...) -{ - property_t* property = _property; - - assert(property); - - va_list params; - - va_start(params, _property); - free_item_memory(property, 0, ¶ms); - va_end(params); -} - -static void free_item_memory(void* _item, int index, va_list* params) -{ - property_t* property = NULL; - event_t* event = NULL; - service_t* service = NULL; - lite_property_t* lite_property; - input_data_t* input_data; - char* type_str; /* 0: property, 1: event, 2: service. */ - int i, j; - int output_data_numb; - int input_data_numb; - int number; - void* p; - - type_str = va_arg(*params, char*); - number = va_arg(*params, int); - - assert(type_str); - - if (strcmp(type_str, string_property) == 0) { - property = _item; - } - - else if (strcmp(type_str, string_event) == 0) { - event = _item; - } - - else if (strcmp(type_str, string_service) == 0) { - service = _item; - } - - else { - assert(0); - } - - if (property) { - if (property->identifier) { - dm_lite_free(property->identifier); - } - if (property->name) { - dm_lite_free(property->name); - } - if (property->desc) { - dm_lite_free(property->desc); - } - - property_free_data_type_info(&property->data_type); - if (index + 1 == number) { - p = property - index; - dm_lite_free(p); - } - - } else if (event) { - if (event->identifier) { - dm_lite_free(event->identifier); - } - if (event->name) { - dm_lite_free(event->name); - } - if (event->desc) { - dm_lite_free(event->desc); - } - if (event->event_type_str) { - dm_lite_free(event->event_type_str); - } - if (event->method) { - dm_lite_free(event->method); - } - - output_data_numb = event->event_output_data_num; - for (i = 0 ; i < output_data_numb; ++i) { - lite_property = event->event_output_data + i; - free_lite_property(lite_property); - } - if (output_data_numb) { - dm_lite_free(event->event_output_data); - } - - if (index + 1 == number) { - p = event - index; - dm_lite_free(p); - } - } else if (service) { - if (service->identifier) { - dm_lite_free(service->identifier); - } - if (service->name) { - dm_lite_free(service->name); - } - if (service->desc) { - dm_lite_free(service->desc); - } - if (service->call_type) { - dm_lite_free(service->call_type); - } - if (service->method) { - dm_lite_free(service->method); - } - - output_data_numb = service->service_output_data_num; - for (i = 0 ; i < output_data_numb; ++i) { - lite_property = service->service_output_data + i; - free_lite_property(lite_property); - } - if (output_data_numb) { - dm_lite_free(service->service_output_data); - } - - input_data_numb = service->service_input_data_num; - for (j = 0 ; j < input_data_numb; ++j) { - input_data = service->service_input_data + j; - free_input_data(input_data, service->service_type); - } - if (input_data_numb) { - dm_lite_free(service->service_input_data); - } - if (index + 1 == number) { - p = service - index; - dm_lite_free(p); - } - } -} -#ifdef ENABLE_THING_DEBUG -static void print_lite_property(void* dst) -{ - lite_property_t* lite_property = (lite_property_t*)dst; - - assert(lite_property); - - dm_printf("\tidentifier:%s, name:%s\n", lite_property->identifier, lite_property->name); - - property_print_data_type_info(&lite_property->data_type); -} - -static void print_property(void* dst, ...) -{ - property_t* property = dst; - - va_list params; - - va_start(params, dst); - - item_print_info(property, -1, ¶ms); - - va_end(params); -} - -static void print_input_data(void* dst, service_type_t service_type) -{ - input_data_t* input_data = (input_data_t*)dst; - - assert(input_data); - - switch (service_type) { - case service_type_property_set: - print_property(&input_data->property_to_set, 6, string_property, string_identifier, string_name, string_accessMode, string_required, string_dataType); - break; - case service_type_others: - print_lite_property(&input_data->lite_property); - break; - case service_type_property_get: - dm_printf("\t\"%s\"\n", input_data->property_to_get_name); - break; - default: - break; - } -} - -static void property_print_data_type_info(void* dst) -{ - data_type_t* data_type = dst; - data_type_x_t* data_type_x; - lite_property_t* lite_property; - int index; - assert(data_type); - - data_type_x = &data_type->value; - switch (data_type->type) { - case data_type_type_int: -#ifdef LITE_THING_MODEL - dm_printf("\tdataType:{type:%s,min:%d,max:%d\n\tvalue:%d}\n", - data_type->type_str, - data_type_x->data_type_int_t.min, - data_type_x->data_type_int_t.max, - data_type_x->data_type_int_t.value); - break; -#else - dm_printf("\tdataType:{type:%s,min:%d,max:%d,precise:%d,unit:%s,unitName:%s\n\tvalue:%d}\n", - data_type->type_str, - data_type_x->data_type_int_t.min, - data_type_x->data_type_int_t.max, - data_type_x->data_type_int_t.precise, - data_type_x->data_type_int_t.unit, - data_type_x->data_type_int_t.unit_name, - data_type_x->data_type_int_t.value); - break; -#endif - case data_type_type_float: -#ifdef LITE_THING_MODEL - dm_printf("\tdataType:{type:%s,min:%.2f,max:%.2f,precise:%d\n\tvalue:%.2f}\n", - data_type->type_str, - data_type_x->data_type_float_t.min, - data_type_x->data_type_float_t.max, - data_type_x->data_type_float_t.precise, - data_type_x->data_type_float_t.value); - break; -#else - dm_printf("\tdataType:{type:%s,min:%.2f,max:%.2f,precise:%d,unit:%s,unitName:%s\n\tvalue:%.2f}\n", - data_type->type_str, - data_type_x->data_type_float_t.min, - data_type_x->data_type_float_t.max, - data_type_x->data_type_float_t.precise, - data_type_x->data_type_float_t.unit, - data_type_x->data_type_float_t.unit_name, - data_type_x->data_type_float_t.value); - break; -#endif - - case data_type_type_double: -#ifdef LITE_THING_MODEL - dm_printf("\tdataType:{type:%s,min:%.2f,max:%.2f,precise:%d\n\tvalue:%.7f}\n", - data_type->type_str, - data_type_x->data_type_double_t.min, - data_type_x->data_type_double_t.max, - data_type_x->data_type_double_t.precise, - data_type_x->data_type_double_t.value); - break; -#else - dm_printf("\tdataType:{type:%s,min:%.2f,max:%.2f,precise:%d,unit:%s,unitName:%s\n\tvalue:%.7f}\n", - data_type->type_str, - data_type_x->data_type_double_t.min, - data_type_x->data_type_double_t.max, - data_type_x->data_type_double_t.precise, - data_type_x->data_type_double_t.unit, - data_type_x->data_type_double_t.unit_name, - data_type_x->data_type_double_t.value); - break; -#endif - case data_type_type_enum: - dm_printf("\tdataType:{type:%s,", data_type->type_str); - for (index = 0; index < data_type_x->data_type_enum_t.enum_item_number; ++index) { - dm_printf("key:%s|value:%s\t", *(data_type_x->data_type_enum_t.enum_item_key + index), -#ifdef LITE_THING_MODEL - "NULL"); -#else - *(data_type_x->data_type_enum_t.enum_item_value + index)); -#endif - - } - - dm_printf("\n\tvalue:%d}\n", data_type_x->data_type_enum_t.value); - break; - case data_type_type_bool: - dm_printf("\tdataType:{type:%s,", data_type->type_str); - for (index = 0; index < data_type_x->data_type_bool_t.bool_item_number; ++index) { - dm_printf("key:%s|value:%s\t", - *(data_type_x->data_type_bool_t.bool_item_key + index), -#ifdef LITE_THING_MODEL - "NULL"); -#else - *(data_type_x->data_type_bool_t.bool_item_value + index)); -#endif - - } - - dm_printf("\n\tvalue:%s}\n", data_type_x->data_type_bool_t.value ? string_true : string_false); - break; - case data_type_type_text: -#ifdef LITE_THING_MODEL - dm_printf("\tdataType:{type:%s,length:%d\n\tvalue:%s}\n", - data_type->type_str, - data_type_x->data_type_text_t.length, - data_type_x->data_type_text_t.value); -#else - dm_printf("\tdataType:{type:%s,length:%d,unit:%s,unitName:%s\n\tvalue:%s}\n", - data_type->type_str, - data_type_x->data_type_text_t.length, - data_type_x->data_type_text_t.unit, - data_type_x->data_type_text_t.unit_name, - data_type_x->data_type_text_t.value); -#endif - break; - case data_type_type_struct: - dm_printf("\tdataType:%s[\n", data_type->type_str); - for (index = 0; index < data_type->data_type_specs_number; ++index) { - lite_property = (lite_property_t*)data_type->specs + index; - print_lite_property(lite_property); - } - dm_printf("\t]\n"); - break; - case data_type_type_date: - dm_printf("\tdataType:{type:%s\n\tvalue:%lld}\n", - data_type->type_str, - data_type_x->data_type_date_t.value); - break; - default: - dm_printf("unsupported type:%s\n", data_type->type_str); - break; - } -} - -static void item_print_info(void* _item, int index, va_list* params) -{ - property_t* property = NULL; - event_t* event = NULL; - service_t* service = NULL; - lite_property_t* lite_property; - input_data_t* input_data; - char* type_str; /* 0: property, 1: event, 2: service. */ - int type; - char* control_str; - int length; - int i, j; - int output_data_numb; - int input_data_numb; - - length = va_arg(*params, int); - - assert(length > 1); /* at least type info and one control type. */ - - type_str = control_str = va_arg(*params, char*); - - assert(type_str); - - if (strcmp(type_str, string_property) == 0) { - type = 0; - property = _item; - } else if (strcmp(type_str, string_event) == 0) { - type = 1; - event = _item; - } else if (strcmp(type_str, string_service) == 0) { - type = 2; - service = _item; - } else { - assert(0); - } - - if (type_str && index != -1) { - dm_printf("%s information print strart\n", type_str); - dm_printf("index: %d\n", index); - } - - for (i = 1, control_str = va_arg(*params, char*); i < length ; ++i, control_str = va_arg(*params, char*)) { - if (strcmp(control_str, string_identifier) == 0) { - dm_printf("\tidentifier:%s\n", 0 == type ? property->identifier : (1 == type ? event->identifier : service->identifier)); - } - - else if (strcmp(control_str, string_name) == 0) { - dm_printf("\tname:%s\n", 0 == type ? property->name : (1 == type ? event->name : service->name)); - } - - else if (strcmp(control_str, string_accessMode) == 0) { - dm_printf("\taccessMode:%s\n", - property->access_mode == property_access_mode_rw ? "rw" : (property->access_mode == property_access_mode_r ? "r" : "w")); - } else if (strcmp(control_str, string_required) == 0) { - dm_printf("\trequired:%s\n", (0 == type ? property->required : (1 == type ? event->required : service->required)) ? string_true : string_false); - } - - else if (strcmp(control_str, string_desc) == 0) { - dm_printf("\tdesc:%s\n", 0 == type ? property->desc : (1 == type ? event->desc : service->desc)); - } - - else if (strcmp(control_str, string_dataType) == 0) { - property_print_data_type_info(&property->data_type); - } - - else if (strcmp(control_str, string_method) == 0) { - dm_printf("\tmethod:%s\n", 1 == type ? event->method : service->method); - } - - else if (strcmp(control_str, string_type) == 0) { - dm_printf("\ttype:%s\n", event->event_type_str); - } - - else if (strcmp(control_str, string_outputData) == 0) { - dm_printf("\toutputData:[\n"); - output_data_numb = 1 == type ? event->event_output_data_num : service->service_output_data_num; - for (j = 0 ; j < output_data_numb; ++j) { - lite_property = (1 == type ? event->event_output_data : service->service_output_data) + j; - print_lite_property(lite_property); - } - dm_printf("\t]\n"); - } else if (strcmp(control_str, string_inputData) == 0) { - dm_printf("\tinputData:[\n"); - input_data_numb = service->service_input_data_num; - for (j = 0 ; j < input_data_numb; ++j) { - input_data = service->service_input_data + j; - print_input_data(input_data, service->service_type); - } - dm_printf("\t]\n"); - } else { - break; - } - } - - if (type_str && index != -1) { - dm_printf("%s information print end\n\n", type_str); - } - -} - -static void dm_thing_print_property_lite_info(const void* _self) -{ - const thing_t* self = _self; - - property_iterator((thing_t*)self, item_print_info, 3, string_property, string_identifier, string_accessMode); -} - -static void dm_thing_print_property_detail_info(const void* _self) -{ - const thing_t* self = _self; - - property_iterator((thing_t*)self, item_print_info, 6, string_property, string_identifier, string_name, string_accessMode, string_required, string_dataType); -} - -static void dm_thing_print_event_lite_info(const void* _self) -{ - const thing_t* self = _self; - - event_iterator((thing_t*)self, item_print_info, 2, string_event, string_identifier); -} - -static void dm_thing_print_event_detail_info(const void* _self) -{ - const thing_t* self = _self; - - event_iterator((thing_t*)self, item_print_info, 8, string_event, string_identifier, string_name, string_desc, string_required, string_type, string_method, string_outputData); -} - -static void dm_thing_print_service_lite_info(const void* _self) -{ - const thing_t* self = _self; - - service_iterator((thing_t*)self, item_print_info, 2, string_service, string_identifier); -} - -static void dm_thing_print_service_detail_info(const void* _self) -{ - const thing_t* self = _self; - - service_iterator((thing_t*)self, item_print_info, 8, string_service, string_identifier, string_name, string_desc, string_required, string_method, string_inputData, string_outputData); -} -#endif /* ENABLE_THING_DEBUG */ -static int dm_thing_set_event_value_by_identifier(void* _self, const char* const identifier, const void* value, const char* value_str) -{ - dm_thing_t* self = _self; - lite_property_t* lite_property; - event_t* event; - char *arrpre_pos; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - int ret; - - assert(strchr(identifier, DEFAULT_DSL_DELIMITER)); /* set lite property value of outputData. */ - if (strchr(identifier, DEFAULT_DSL_DELIMITER) == NULL || strlen(identifier) >= MAX_IDENTIFIER_LENGTH) return -1; - /* do some checks. */ - strcpy(id_buff, identifier); - p = strtok(id_buff, delimeter); - - event = dm_thing_get_event_by_identifier(self, p); - /* not allowed to set value to this type of event. */ - if (event == NULL || strcmp(event->method, string_thing_event_property_post) == 0) return -1; - - lite_property = dm_thing_get_event_by_identifier(self, identifier); - - assert(lite_property); - if (lite_property == NULL) return -1; - self->_arr_index = get_array_index_by_identifier(identifier, &arrpre_pos); - ret = set_lite_property_value(self, lite_property, value, value_str); - self->_arr_index = -1; - return ret; -} - -static int dm_thing_get_event_value_by_identifier(void* _self, const char* const identifier, void* value, char** value_str) -{ - dm_thing_t* self = _self; - lite_property_t* lite_property; - int ret; - char* arrpre_pos = NULL; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - event_t* event; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; - char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; -#endif - assert(strchr(identifier, DEFAULT_DSL_DELIMITER)); /* set lite property value of outputData. */ - if (strchr(identifier, DEFAULT_DSL_DELIMITER) == NULL) return -1; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - /* do some checks. */ - strcpy(id_buff, identifier); - p = strtok(id_buff, delimeter); - event = dm_thing_get_event_by_identifier(self, p); - assert(strcmp(event->method, string_thing_event_property_post) != 0); /* not allowed to set value to this type of event. */ -#endif - lite_property = dm_thing_get_event_by_identifier(self, identifier); - - assert(lite_property); - - if (lite_property == NULL) return -1; - self->_arr_index = get_array_index_by_identifier(identifier, &arrpre_pos); - ret = dm_thing_get_lite_property_value(self, lite_property, value, value_str); - self->_arr_index = -1; - return ret; -} - -static int dm_thing_set_service_input_output_data_value_by_identifier(void* _self, const char* const identifier, - const void* value, const char* value_str) -{ - int ret; - dm_thing_t* self = _self; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - service_t* service; - char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; -#endif - lite_property_t* lite_property; - char *arrpre_pos; - assert(strchr(identifier, DEFAULT_DSL_DELIMITER)); /* set lite property value of inputData. */ - if (strchr(identifier, DEFAULT_DSL_DELIMITER) == NULL) return -1; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - /* do some checks. */ - strcpy(id_buff, identifier); - p = strtok(id_buff, delimeter); - - service = dm_thing_get_service_by_identifier(self, p); - - assert(strcmp(service->method, string_thing_service_property_get) != 0 && - strcmp(service->method, string_thing_service_property_set) != 0); /* not allowed to set value to this type of service. */ -#endif - lite_property = dm_thing_get_service_by_identifier(self, identifier); - if (lite_property == NULL) return -1; - self->_arr_index = get_array_index_by_identifier(identifier, &arrpre_pos); - ret = set_lite_property_value(self, lite_property, value, value_str); - self->_arr_index = -1; - return ret; -} - -static int dm_thing_get_service_input_output_data_value_by_identifier(void* _self, const char* const identifier, - void* value, char** value_str) -{ - int ret = -1; - dm_thing_t* self = _self; - char *arrpre_pos; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - service_t* service; - char* p; - char id_buff[MAX_IDENTIFIER_LENGTH] = {0}; - char delimeter[] = {DEFAULT_DSL_DELIMITER, 0}; -#endif - lite_property_t* lite_property; - - assert(strchr(identifier, DEFAULT_DSL_DELIMITER)); /* set lite property value of inputData. */ - if (strchr(identifier, DEFAULT_DSL_DELIMITER) == NULL) return -1; -#ifdef PROPERTY_ACCESS_MODE_ENABLED - /* do some checks. */ - strcpy(id_buff, identifier); - p = strtok(id_buff, delimeter); - - service = dm_thing_get_service_by_identifier(self, p); - assert(strcmp(service->method, string_thing_service_property_get) != 0 && - strcmp(service->method, string_thing_service_property_set) != 0); /* not allowed to set value to this type of service. */ -#endif - lite_property = dm_thing_get_service_by_identifier(self, identifier); - - if (lite_property == NULL) return -1; - - self->_arr_index = get_array_index_by_identifier(identifier, &arrpre_pos); - ret = dm_thing_get_lite_property_value(self, lite_property, value, value_str); - self->_arr_index = -1; - - return ret; -} - -static thing_t _dm_thing_class = { - sizeof(dm_thing_t), - string_dm_thing_class_name, - dm_thing_ctor, - dm_thing_dtor, - dm_thing_set_dsl_string, - dm_thing_get_dsl_string, - dm_thing_get_property_number, - dm_thing_get_service_number, - dm_thing_get_event_number, - dm_thing_get_property_by_identifier, - dm_thing_get_property_identifier_by_index, - dm_thing_get_service_by_identifier, - dm_thing_get_service_identifier_by_index, - dm_thing_get_event_by_identifier, - dm_thing_get_event_identifier_by_index, - dm_thing_get_schema, - dm_thing_get_link, - dm_thing_get_product_key, - dm_thing_return_product_key, - dm_thing_get_device_name, - dm_thing_return_device_name, - dm_thing_set_property_value_by_identifier, - dm_thing_set_property_value, - dm_thing_get_property_value_by_identifier, - dm_thing_get_property_value, - dm_thing_property_iterator, - dm_thing_event_iterator, - dm_thing_service_iterator, -#ifdef ENABLE_THING_DEBUG - dm_thing_print_property_lite_info, - dm_thing_print_property_detail_info, - dm_thing_print_event_lite_info, - dm_thing_print_event_detail_info, - dm_thing_print_service_lite_info, - dm_thing_print_service_detail_info, -#endif /* ENABLE_THING_DEBUG */ - dm_thing_set_event_value_by_identifier, - dm_thing_get_event_value_by_identifier, - dm_thing_set_service_input_output_data_value_by_identifier, - dm_thing_get_service_input_output_data_value_by_identifier, - dm_thing_get_lite_property_value, -}; - -const void* get_dm_thing_class() -{ - return &_dm_thing_class; -} diff --git a/iotkit-embedded/src/dm/src/dm_thing_manager.c b/iotkit-embedded/src/dm/src/dm_thing_manager.c deleted file mode 100644 index b974a0f..0000000 --- a/iotkit-embedded/src/dm/src/dm_thing_manager.c +++ /dev/null @@ -1,2118 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "interface/thing_manager_abstract.h" -#include "interface/message_info_abstract.h" -#include "interface/cmp_abstract.h" -#include "dm_thing_manager.h" -#include "logger.h" -#include "dm_thing.h" -#include "single_list.h" -#include "dm_import.h" -#include "cmp_message_info.h" -#include "cmp_abstract_impl.h" - -#include "iot_import.h" -#include "iot_export.h" -#include "class_interface.h" - -#include "cJSON.h" - - -static const char string_dm_thing_manager_class_name[] __DM_READ_ONLY__ = "dm_thg_mng_cls"; -static const char string_thing_service_property_set[] __DM_READ_ONLY__ = "thing.service.property.set"; -static const char string_thing_service_property_get[] __DM_READ_ONLY__ = "thing.service.property.get"; -static const char string_thing_event_property_post[] __DM_READ_ONLY__ = "thing.event.property.post"; -static const char string_method_name_thing_enable[] __DM_READ_ONLY__ = METHOD_NAME_THING_ENABLE; -static const char string_method_name_thing_disable[] __DM_READ_ONLY__ = METHOD_NAME_THING_DISABLE; -static const char string_method_name_thing_delete[] __DM_READ_ONLY__ = METHOD_NAME_THING_DELETE; -static const char string_method_name_thing_dsl_post_reply[] __DM_READ_ONLY__ = METHOD_NAME_THING_DSL_POST_REPLY; -static const char string_method_name_thing_dsl_get[] __DM_READ_ONLY__ = METHOD_NAME_THING_DSL_GET; -static const char string_method_name_thing_dsl_get_reply[] __DM_READ_ONLY__ = METHOD_NAME_THING_DSL_GET_REPLY; -static const char string_method_name_down_raw[] __DM_READ_ONLY__ = METHOD_NAME_DOWN_RAW; -static const char string_method_name_down_raw_reply[] __DM_READ_ONLY__ = METHOD_NAME_DOWN_RAW_PEPLY; -static const char string_method_name_up_raw[] __DM_READ_ONLY__ = METHOD_NAME_UP_RAW; -static const char string_method_name_up_raw_reply[] __DM_READ_ONLY__ = METHOD_NAME_UP_RAW_REPLY; -static const char string_method_name_property_set[] __DM_READ_ONLY__ = METHOD_NAME_PROPERTY_SET; -static const char string_method_name_property_get[] __DM_READ_ONLY__ = METHOD_NAME_PROPERTY_GET; -#ifdef DEVICEINFO_ENABLED -static const char string_method_name_deviceinfo_update[] __DM_READ_ONLY__ = METHOD_NAME_DEVICEINFO_UPDATE; -static const char string_method_name_deviceinfo_update_reply[] __DM_READ_ONLY__ = METHOD_NAME_DEVICEINFO_UPDATE_REPLY; -static const char string_method_name_deviceinfo_delete[] __DM_READ_ONLY__ = METHOD_NAME_DEVICEINFO_DELETE; -static const char string_method_name_deviceinfo_delete_reply[] __DM_READ_ONLY__ = METHOD_NAME_DEVICEINFO_DELETE_REPLY; -#endif /* DEVICEINFO_ENABLED */ -#ifdef RRPC_ENABLED -static const char string_method_name_rrpc_request_plus[] __DM_READ_ONLY__ = METHOD_NAME_RRPC_REQUEST_PLUS; -static const char string_method_name_rrpc_request[] __DM_READ_ONLY__ = METHOD_NAME_RRPC_REQUEST; -#endif /* RRPC_ENABLED */ -static const char string_cmp_event_handler_prompt_start[] __DM_READ_ONLY__ = "\ncmp_event_handler:\n###\n"; -static const char string_cmp_event_handler_prompt_end[] __DM_READ_ONLY__ = "\n###\n"; -static const char string_cmp_event_type_cloud_connected[] __DM_READ_ONLY__ = "cloud connected"; -static const char string_cmp_event_type_cloud_disconnect[] __DM_READ_ONLY__ = "cloud disconnect"; -static const char string_cmp_event_type_cloud_reconnect[] __DM_READ_ONLY__ = "cloud reconnect"; -static const char string_cmp_event_type_found_device[] __DM_READ_ONLY__ = "found device"; -static const char string_cmp_event_type_remove_device[] __DM_READ_ONLY__ = "remove device"; -static const char string_cmp_event_type_register_result[] __DM_READ_ONLY__ = "register result"; -static const char string_cmp_event_type_unregister_result[] __DM_READ_ONLY__ = "unregister result"; -static const char string_cmp_event_type_send_result[] __DM_READ_ONLY__ = "send result"; -static const char string_cmp_event_type_new_data_received[] __DM_READ_ONLY__ = "new data received"; - -static const char string_local_thing_list[] __DM_READ_ONLY__ = "local thing"; -static const char string_local_thing_name_list[] __DM_READ_ONLY__ = "local thing name"; -static const char string_sub_thing_list[] __DM_READ_ONLY__ = "sub thing"; -static const char string_callback_list[] __DM_READ_ONLY__ = "callback list"; -static const char string_service_property_get_identifier_list[] __DM_READ_ONLY__ = "service property get id list"; - -static const char string_success[] __DM_READ_ONLY__ = "success"; -static const char string_fail[] __DM_READ_ONLY__ = "fail"; -static const char string_uri_type_sys[] __DM_READ_ONLY__ = "SYS"; -static const char string_uri_type_ext[] __DM_READ_ONLY__ = "EXT"; -static const char string_uri_type_undefine[] __DM_READ_ONLY__ = "UNDEFINE"; -static const char string_request[] __DM_READ_ONLY__ = "request"; -static const char string_response[] __DM_READ_ONLY__ = "response"; -static const char string_event[] __DM_READ_ONLY__ = "event"; -static const char string_service[] __DM_READ_ONLY__ = "service"; - -static void free_list_string(void* _thing_name, va_list* params); -static void free_list_thing(void* _thing_name, va_list* params); -static void local_thing_list_iterator(const void* _self, handle_fp_t handle_fp); -static void invoke_callback_func(void* _callback_fp, va_list* params); -static void callback_list_iterator(const void* _self, handle_fp_t handle_fp); -static void generate_subscribe_uri(void* _dm_thing_manager, void* _thing); -static void send_request_to_uri(void* _dm_thing_manager, const char *_uri); -static void clear_and_set_message_info(message_info_t** _message_info, dm_thing_manager_t* _dm_thing_manager); -static void get_product_key_device_name(char* _product_key, char* _device_name, void* _thing, void* _dm_thing_manager); -static void* dm_thing_manager_generate_new_local_thing(void* _self, const char* tsl, int tsl_len); -static int dm_thing_manager_set_thing_property_value(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - -static int dm_thing_manager_install_product_key_device_name(void *_self, const void* thing_id, char *product_key, char *device_name); - -#ifdef RRPC_ENABLED -static int dm_thing_manager_answer_service(void* _self, const void* thing_id, const void* identifier, int response_id, int code, int rrpc); -#else -static int dm_thing_manager_answer_service(void* _self, const void* thing_id, const void* identifier, int response_id, int code); -#endif /* RRPC_ENABLED */ - -static void cmp_register_handler(iotx_cmp_send_peer_t* _source, iotx_cmp_message_info_t* _msg, void* user_data); - -static void list_insert(void* _list, void* _data) -{ - list_t** list = (list_t**)_list; - - (*list)->insert(list, _data); -} - -static void invoke_callback_list(void* _dm_thing_manager, dm_callback_type_t dm_callback_type) -{ - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - list_t** list; - - assert(dm_callback_type < dm_callback_type_number); - - /* invoke callback funtions. */ - list = dm_thing_manager->_callback_list; - if (list && !(*list)->empty(list)) { - dm_thing_manager->_callback_type = dm_callback_type; - callback_list_iterator(dm_thing_manager, invoke_callback_func); - } -} - -static void local_thing_generate_subscribe_uri(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing); - - /* subscribe subjects. */ - generate_subscribe_uri(dm_thing_manager, thing); -} - -static void cmp_event_handler(void* pcontext, iotx_cmp_event_msg_t* msg, void* user_data) -{ - iotx_cmp_event_result_t* cmp_event_result; - dm_thing_manager_t* dm_thing_manager = user_data; - const char* event_str = NULL; - - dm_printf("%s", string_cmp_event_handler_prompt_start); - if (IOTX_CMP_EVENT_REGISTER_RESULT == msg->event_id) { - iotx_cmp_event_result_t* cmp_event_result = (iotx_cmp_event_result_t*)msg->msg; - - dm_log_info("register result:\tresult: %d(%s)\tURI: %s\tURI_type:%s", - cmp_event_result->result, cmp_event_result->result == 0 ? string_success : string_fail, - cmp_event_result->URI, cmp_event_result->URI_type == IOTX_CMP_URI_SYS ? - string_uri_type_sys : (cmp_event_result->URI_type == IOTX_CMP_URI_EXT ? string_uri_type_ext : string_uri_type_undefine)); - - event_str = string_cmp_event_type_register_result; - } else if (IOTX_CMP_EVENT_UNREGISTER_RESULT == msg->event_id) { - cmp_event_result = (iotx_cmp_event_result_t*)msg->msg; - - dm_log_info("un-register result:\tresult: %s,\tURI: %s,\tURI_type:%s", cmp_event_result->result, - cmp_event_result->URI, cmp_event_result->URI_type == IOTX_CMP_URI_SYS ? - string_uri_type_sys : (cmp_event_result->URI_type == IOTX_CMP_URI_EXT ? string_uri_type_ext : string_uri_type_undefine)); - - event_str = string_cmp_event_type_unregister_result; - } else if (IOTX_CMP_EVENT_CLOUD_DISCONNECT == msg->event_id) { - if (dm_thing_manager->_cloud_connected) { - dm_thing_manager->_cloud_connected = 0; - invoke_callback_list(dm_thing_manager, dm_callback_type_cloud_disconnected); - } - event_str = string_cmp_event_type_cloud_disconnect; - } else if (IOTX_CMP_EVENT_CLOUD_RECONNECT == msg->event_id) { - if (dm_thing_manager->_cloud_connected == 0) { - dm_thing_manager->_cloud_connected = 1; - invoke_callback_list(dm_thing_manager, dm_callback_type_cloud_connected); - } - event_str = string_cmp_event_type_cloud_reconnect; - } else if (IOTX_CMP_EVENT_CLOUD_CONNECTED == msg->event_id) { - if (dm_thing_manager->_cloud_connected == 0) { - dm_thing_manager->_cloud_connected = 1; - - if (dm_thing_manager->_destructing == 1) return; - /* subscribe uris not related to tsl. */ - generate_subscribe_uri(dm_thing_manager, NULL); - - if (dm_thing_manager->_get_tsl_from_cloud) { - /* get tsl template. */ - send_request_to_uri(dm_thing_manager, string_method_name_thing_dsl_get); - } - - local_thing_list_iterator(dm_thing_manager, local_thing_generate_subscribe_uri); - - invoke_callback_list(dm_thing_manager, dm_callback_type_cloud_connected); - } - event_str = string_cmp_event_type_cloud_connected; - } else if (IOTX_CMP_EVENT_FOUND_DEVICE == msg->event_id) { - /* currently do not process this. */ - event_str = string_cmp_event_type_found_device; - } else if (IOTX_CMP_EVENT_REMOVE_DEVICE == msg->event_id) { - /* currently do not process this. */ - event_str = string_cmp_event_type_remove_device; - } else if (IOTX_CMP_EVENT_SEND_RESULT == msg->event_id) { - event_str = string_cmp_event_type_send_result; - } else if (IOTX_CMP_EVENT_NEW_DATA_RECEIVED == msg->event_id) { - iotx_cmp_new_data_t* new_data = (iotx_cmp_new_data_t*)msg->msg; - cmp_register_handler(new_data->peer, new_data->message_info, dm_thing_manager); - - event_str = string_cmp_event_type_new_data_received; - } else { - dm_printf("unknown event %d\n", msg->event_id); - } - - dm_printf("\nevent %d(%s)%s", msg->event_id, event_str, string_cmp_event_handler_prompt_end); -} - -static void print_iotx_cmp_message_info(const void* _source, const void* _msg) -{ - const iotx_cmp_send_peer_t* iotx_cmp_send_peer = _source; - const iotx_cmp_message_info_t* iotx_cmp_message_info = _msg; - - dm_printf("***\nsource\t%s:%s\n", iotx_cmp_send_peer->product_key, iotx_cmp_send_peer->device_name); - - dm_printf("type\t%s\n", iotx_cmp_message_info->message_type == IOTX_CMP_MESSAGE_RAW ? - "RAW" : (iotx_cmp_message_info->message_type == IOTX_CMP_MESSAGE_REQUEST ? string_request : string_response)); - dm_printf("URI\t%s\n", iotx_cmp_message_info->URI); - - dm_printf("URI_type\t%s\n", iotx_cmp_message_info->URI_type == IOTX_CMP_URI_SYS ? - string_uri_type_sys : (iotx_cmp_message_info->URI_type == IOTX_CMP_URI_EXT ? string_uri_type_ext : string_uri_type_undefine)); - - dm_printf("code\t%d\n", iotx_cmp_message_info->code); - dm_printf("id\t%d\n", iotx_cmp_message_info->id); - - if (iotx_cmp_message_info->method) - dm_printf("method\t%s\n", iotx_cmp_message_info->method); - else - dm_printf("method\tNULL\n"); - - dm_printf("param:\n%s\n", (char*)iotx_cmp_message_info->parameter); - dm_printf("param len:\t%dbytes\n", iotx_cmp_message_info->parameter_length); - dm_printf("***\n"); -} - -static int check_set_lite_property_for_struct(cJSON* cjson_obj, lite_property_t *lite_property) -{ - int i; - lite_property_t* sub_property; - cJSON *subobject; - for(i = 0; i < lite_property->data_type.data_type_specs_number; i++) { - sub_property = (lite_property_t*)lite_property->data_type.specs + i; - subobject = cJSON_GetObjectItem(cjson_obj, sub_property->identifier); - if(!subobject) - return -1; - if(data_type_type_struct == sub_property->data_type.type) { - if(check_set_lite_property_for_struct(subobject, sub_property)) { - return -1; - } - } - } - return 0; -} - -static void find_and_set_array_item(dm_thing_manager_t* dm_thing_manager,thing_t** thing, cJSON* cjson_arr_obj, int item_index, lite_property_t *lite_property,data_type_type_t type) -{ - int int_val; - float float_val; - double double_val; - char temp_buf[64] = {0}; - char identifier[64] = {0}; - char* string_val = NULL; - cJSON *arr_json_item; - if(item_index > lite_property->data_type.value.data_type_array_t.size) { - dm_printf("input json array item:%d > lite json array size:%d ", item_index, lite_property->data_type.value.data_type_array_t.size); - return; - } - - arr_json_item = cJSON_GetArrayItem(cjson_arr_obj,item_index); - if(!arr_json_item) { - dm_log_err("get array[%d] failed", item_index); - goto do_exit; - } - switch(lite_property->data_type.value.data_type_array_t.item_type) { - case data_type_type_int: { - int_val = arr_json_item->valueint; - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", int_val); - }break; - case data_type_type_double: { - double_val = arr_json_item->valuedouble; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.16lf", double_val); - }break; - case data_type_type_float: { - float_val = arr_json_item->valuedouble; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.7f", float_val); - }break; - case data_type_type_text: { - string_val = dm_lite_calloc(1, strlen(arr_json_item->valuestring) + 1); - assert(string_val); - if (string_val == NULL) { - dm_printf("NO memory..."); - return; - } - strcpy(string_val, arr_json_item->valuestring); - }break; - default:{ - dm_log_err("don't support %d type", lite_property->data_type.value.data_type_array_t.item_type); - goto do_exit; - } - } - dm_thing_manager->_property_identifier_value_set = NULL; - if (string_val) { - dm_thing_manager->_property_identifier_value_set = string_val; - } else if (strlen(temp_buf)) { - dm_thing_manager->_property_identifier_value_set = dm_lite_calloc(1, strlen(temp_buf) + 1); - assert(dm_thing_manager->_property_identifier_value_set); - strcpy(dm_thing_manager->_property_identifier_value_set, temp_buf); - } - - if (dm_thing_manager->_property_identifier_set && dm_thing_manager->_property_identifier_value_set) { - dm_snprintf(identifier, sizeof(identifier), "%s[%d]",(char*)dm_thing_manager->_property_identifier_set, item_index); - dm_thing_manager_set_thing_property_value(dm_thing_manager, thing, identifier, - NULL, dm_thing_manager->_property_identifier_value_set); - - dm_lite_free(dm_thing_manager->_property_identifier_value_set); - dm_thing_manager->_property_identifier_value_set = NULL; - } -do_exit: - return; -} - - -static void find_and_set_lite_property_struct_for_service_property_set(void* _item, ...); -static void find_and_set_lite_property_for_service_property_set(void* _item, int _index, va_list* params) -{ - property_t* property = _item; - lite_property_t* lite_property; - lite_property_t* lite_property_struct; - dm_thing_manager_t* dm_thing_manager; - thing_t** thing; - cJSON* property_set_param_obj; - cJSON* temp_cjson_obj; - char temp_buf[64] = {0}; - int int_val; - float float_val; - double double_val; - char* string_val = NULL; - char* identifier_prefix = NULL; - char identifier_buff[128] = {0}; - int index; - int arrsize = 0; - - dm_thing_manager = va_arg(*params, dm_thing_manager_t*); - property_set_param_obj = va_arg(*params, cJSON*); - thing = va_arg(*params, thing_t**); - identifier_prefix = va_arg(*params, char*); - - _index = _index; - - assert(property && dm_thing_manager && property_set_param_obj && thing && *thing); - - lite_property = (lite_property_t*)property; - - temp_cjson_obj = cJSON_GetObjectItem(property_set_param_obj, lite_property->identifier); - if (temp_cjson_obj) { - if (identifier_prefix) { - dm_snprintf(identifier_buff, sizeof(identifier_buff), "%s%c%s", identifier_prefix, DEFAULT_DSL_DELIMITER, lite_property->identifier); - dm_thing_manager->_property_identifier_set = identifier_buff; - } else { - dm_thing_manager->_property_identifier_set = lite_property->identifier; - } - - if (lite_property->data_type.type == data_type_type_text) { -#ifndef CJSON_STRING_ZEROCOPY - string_val = dm_lite_calloc(1, strlen(temp_cjson_obj->valuestring) + 1); - assert(string_val); - if (string_val == NULL) { - dm_printf("NO memory..."); - return; - } - strcpy(string_val, temp_cjson_obj->valuestring); -#else - string_val = dm_lite_calloc(1, temp_cjson_obj->valuestring_length + 1); - assert(string_val); - if (string_val == NULL) { - dm_printf("NO memory..."); - return; - } - strncpy(string_val, temp_cjson_obj->valuestring, temp_cjson_obj->valuestring_length); -#endif - } else if (lite_property->data_type.type == data_type_type_float) { - float_val = temp_cjson_obj->valuedouble; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.7f", float_val); - } else if (lite_property->data_type.type == data_type_type_double) { - double_val = temp_cjson_obj->valuedouble; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.16lf", double_val); - } else if (lite_property->data_type.type == data_type_type_date) { - if(temp_cjson_obj->type == cJSON_String) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%s", temp_cjson_obj->valuestring); - }else if(temp_cjson_obj->type == cJSON_Number) { - dm_snprintf(temp_buf, sizeof(temp_buf), "%lf", temp_cjson_obj->valuedouble); - } - } else if (lite_property->data_type.type == data_type_type_enum || - lite_property->data_type.type == data_type_type_bool || - lite_property->data_type.type == data_type_type_int) { - - int_val = temp_cjson_obj->valueint; - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", int_val); - } else if (lite_property->data_type.type == data_type_type_struct) { - assert(cJSON_IsObject(temp_cjson_obj)); - if (!cJSON_IsObject(temp_cjson_obj)) return; - if(check_set_lite_property_for_struct(temp_cjson_obj, lite_property)) { - dm_printf("invalid json"); - return; - } - - for (index = 0; index < lite_property->data_type.data_type_specs_number; ++index) { - lite_property_struct = (lite_property_t*)lite_property->data_type.specs + index; - find_and_set_lite_property_struct_for_service_property_set(lite_property_struct, dm_thing_manager, - temp_cjson_obj, thing, lite_property->identifier); - } - dm_thing_manager->_identifier = lite_property->identifier; - invoke_callback_list(dm_thing_manager, dm_callback_type_property_value_set); - } else if(lite_property->data_type.type == data_type_type_array) { - if(!cJSON_IsArray(temp_cjson_obj)) { - dm_log_err("json type is not array"); - return; - } - arrsize = cJSON_GetArraySize(temp_cjson_obj); - if(arrsize > lite_property->data_type.value.data_type_array_t.size) { - dm_printf("input json array item:%d > lite json array item:%d ", arrsize, lite_property->data_type.value.data_type_array_t.size); - return; - } - for(index = 0; index < arrsize; index++){ - find_and_set_array_item(dm_thing_manager,thing, temp_cjson_obj, index, lite_property, lite_property->data_type.type); - } - dm_thing_manager->_identifier = lite_property->identifier; - invoke_callback_list(dm_thing_manager, dm_callback_type_property_value_set); - return; - } - - if (string_val) { - dm_thing_manager->_property_identifier_value_set = string_val; - } else if (strlen(temp_buf)) { - dm_thing_manager->_property_identifier_value_set = dm_lite_calloc(1, strlen(temp_buf) + 1); - assert(dm_thing_manager->_property_identifier_value_set); - strcpy(dm_thing_manager->_property_identifier_value_set, temp_buf); - } - } - - if (dm_thing_manager->_property_identifier_set && dm_thing_manager->_property_identifier_value_set) { - dm_thing_manager_set_thing_property_value(dm_thing_manager, thing, dm_thing_manager->_property_identifier_set, - NULL, dm_thing_manager->_property_identifier_value_set); - - dm_lite_free(dm_thing_manager->_property_identifier_value_set); - dm_thing_manager->_property_identifier_value_set = NULL; - } -} - -static void find_and_set_lite_property_struct_for_service_property_set(void* _item, ...) -{ - va_list params; - - va_start(params, _item); - - find_and_set_lite_property_for_service_property_set(_item, 0, ¶ms); - - va_end(params); -} - -static void find_thing_via_product_key_and_device_name(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - iotx_cmp_send_peer_t* iotx_cmp_send_peer; - - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - - dm_thing_manager = va_arg(*params, void*); - iotx_cmp_send_peer = va_arg(*params, iotx_cmp_send_peer_t*); - - assert(dm_thing_manager && thing && *thing); - - dm_thing_manager_install_product_key_device_name(dm_thing_manager,thing,product_key,device_name); - - if (strcmp(product_key, iotx_cmp_send_peer->product_key) == 0 && strcmp(device_name, iotx_cmp_send_peer->device_name) == 0) { - dm_thing_manager->_thing_id = thing; - } -} - -static int set_service_array_input(dm_thing_manager_t* _dm_thing_manager, thing_t** thing, cJSON* cjson_arr_obj, int item_index,lite_property_t *lite_property, data_type_type_t type, char *_identifier) -{ - int ret = -1; - int int_val; - float float_val; - double double_val; - char temp_buf[64] = {0}; - char identifier[64] = {0}; - cJSON *arr_json_item; - - if(!_dm_thing_manager || !thing || !cjson_arr_obj || item_index < 0 || !lite_property || !_identifier) { - dm_log_err("invalid params"); - goto do_exit; - } - if (item_index > lite_property->data_type.value.data_type_array_t.size) { - dm_printf("input json array item:%d > lite json array size:%d ", item_index, lite_property->data_type.value.data_type_array_t.size); - goto do_exit; - } - - - arr_json_item = cJSON_GetArrayItem(cjson_arr_obj,item_index); - if (!arr_json_item) { - dm_log_err("get array[%d] failed", item_index); - goto do_exit; - } - switch(lite_property->data_type.value.data_type_array_t.item_type) { - case data_type_type_int: { - int_val = arr_json_item->valueint; - dm_snprintf(temp_buf, sizeof(temp_buf), "%d", int_val); - }break; - case data_type_type_double: { - double_val = arr_json_item->valuedouble; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.16lf", double_val); - }break; - case data_type_type_float: { - float_val = arr_json_item->valuedouble; - dm_snprintf(temp_buf, sizeof(temp_buf), "%.7f", float_val); - }break; - case data_type_type_text: { - dm_snprintf(temp_buf, sizeof(temp_buf), "%s", arr_json_item->valuestring); - }break; - default:{ - dm_log_err("don't support %d type", lite_property->data_type.value.data_type_array_t.item_type); - goto do_exit; - } - } - - if (strlen(temp_buf) > 0) { - dm_snprintf(identifier, sizeof(identifier), "%s[%d]", _identifier, item_index); - (*thing)->set_service_input_output_data_value_by_identifier(thing, identifier, NULL, temp_buf); - ret = 0; - } -do_exit: - return ret; -} - -static int parse_and_set_service_input(dm_thing_manager_t *_dm_thing_manager,thing_t **thing, service_t *service, char* parameter) -{ - cJSON* obj = NULL; - cJSON* item; - int i; - char identifier[128] = {0}; - char* string_val; - int arr_size = 0; - int arr_index = 0; - input_data_t* service_input_data; - lite_property_t* property; - - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - - obj = cJSON_Parse(parameter); - if (!obj) return - 1; - - for (i = 0; i < service->service_input_data_num; i++) { - service_input_data = &service->service_input_data[i]; /* inputData */ - - property = &service_input_data->lite_property; - - item = cJSON_GetObjectItem(obj, property->identifier); - if (!item) continue; - - snprintf(identifier, sizeof(identifier), "%s.%s", service->identifier, property->identifier); - - switch (property->data_type.type) { - case data_type_type_text: - { -#ifndef CJSON_STRING_ZEROCOPY - string_val = dm_lite_calloc(1, strlen(item->valuestring) + 1); - - if (string_val == NULL) { - if (obj) cJSON_Delete(obj); - return -1; - } - strcpy(string_val, item->valuestring); -#else - string_val = dm_lite_calloc(1, item->valuestring_length + 1); - - if (string_val == NULL) { - cJSON_Delete(obj); - return -1; - } - strncpy(string_val, item->valuestring, item->valuestring_length); -#endif /* CJSON_STRING_ZEROCOPY */ - (*thing)->set_service_input_output_data_value_by_identifier(thing, identifier, NULL, string_val); - - dm_lite_free(string_val); - } - break; - case data_type_type_enum: - case data_type_type_bool: - case data_type_type_int: - (*thing)->set_service_input_output_data_value_by_identifier(thing, identifier, &item->valueint, NULL); - break; - case data_type_type_float: - case data_type_type_double: - case data_type_type_date: - (*thing)->set_service_input_output_data_value_by_identifier(thing, identifier, &item->valuedouble, NULL); - break; - case data_type_type_array: - arr_size = cJSON_GetArraySize(item); - for(arr_index = 0; arr_index < arr_size; arr_index++) { - set_service_array_input(dm_thing_manager, thing, item, arr_index, property, property->data_type.type, identifier); - } - break; - default: - break; - } - } - - if (obj) cJSON_Delete(obj); - - return 0; -} - -static void find_and_set_service_input(void* _item, int index, va_list* params) -{ - service_t* service; - thing_t **thing; - dm_thing_manager_t* dm_thing_manager; - iotx_cmp_message_info_t* iotx_cmp_message_info; - char* parameter = NULL; - - dm_thing_manager = va_arg(*params, void*); - iotx_cmp_message_info = va_arg(*params, iotx_cmp_message_info_t*); - thing = va_arg(*params, thing_t**); - - service = _item; - - assert(dm_thing_manager && iotx_cmp_message_info && service); - - if (strcmp(service->method, iotx_cmp_message_info->method) == 0) { - dm_thing_manager->_service_identifier_requested = service->identifier; - - if (strstr(iotx_cmp_message_info->URI, string_method_name_property_set) != NULL || strstr(iotx_cmp_message_info->URI, string_method_name_property_get) != NULL) return; - - parameter = iotx_cmp_message_info->parameter; - if (parameter) parse_and_set_service_input(dm_thing_manager, thing, service, parameter); - } -} - -static void cmp_register_handler(iotx_cmp_send_peer_t* _source, iotx_cmp_message_info_t* _msg, void* user_data) -{ - dm_thing_manager_t* dm_thing_manager = user_data; - iotx_cmp_send_peer_t* iotx_cmp_send_peer = _source; - iotx_cmp_message_info_t* iotx_cmp_message_info = _msg; - thing_t** thing; - list_t** list; - cJSON* property_set_param_obj; - cJSON* property_get_param_obj; - cJSON* property_get_param_item_obj; - int array_size, index; - char* property_get_param_identifier; - - assert(dm_thing_manager && iotx_cmp_send_peer && iotx_cmp_message_info); - - print_iotx_cmp_message_info(iotx_cmp_send_peer, iotx_cmp_message_info); - - list = dm_thing_manager->_local_thing_list; - - /* find thing id. */ - dm_thing_manager->_thing_id = NULL; - list_iterator(list, find_thing_via_product_key_and_device_name, dm_thing_manager, iotx_cmp_send_peer); - - if (dm_thing_manager->_thing_id == NULL && strstr(iotx_cmp_message_info->URI, string_method_name_thing_dsl_get_reply) == NULL) { - dm_log_err("thing id NOT match"); - - return; - } - - thing = dm_thing_manager->_thing_id; - - if (iotx_cmp_message_info->message_type == IOTX_CMP_MESSAGE_REQUEST) { - dm_thing_manager->_request_id = iotx_cmp_message_info->id; - - /* find service id trigged. */ - dm_thing_manager->_service_identifier_requested = NULL; - service_iterator(thing, find_and_set_service_input, dm_thing_manager, iotx_cmp_message_info, thing); - assert(dm_thing_manager->_service_identifier_requested); - if (dm_thing_manager->_service_identifier_requested == NULL) { - dm_log_err("method NOT match of service requested"); - return; - } - } else if (iotx_cmp_message_info->message_type == IOTX_CMP_MESSAGE_RAW) { - dm_thing_manager->_request_id = iotx_cmp_message_info->id; - dm_thing_manager->_raw_data = iotx_cmp_message_info->parameter; - dm_thing_manager->_raw_data_length = iotx_cmp_message_info->parameter_length; - - /* invoke callback funtions. */ - invoke_callback_list(dm_thing_manager, dm_callback_type_raw_data_arrived); - - dm_thing_manager->_raw_data = NULL; - dm_thing_manager->_raw_data_length = 0; - - return; - } - - if (iotx_cmp_message_info->URI) { - if (strstr(iotx_cmp_message_info->URI, string_method_name_thing_dsl_get_reply)) { /* thing/dsltemplate/get_reply match */ - thing = dm_thing_manager_generate_new_local_thing(dm_thing_manager, iotx_cmp_message_info->parameter, - iotx_cmp_message_info->parameter_length); - if(NULL == thing) { - dm_log_err("generate new thing failed"); - return; - } - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_property_set)) { /* thing/service/property/set match */ - assert(thing && iotx_cmp_message_info->parameter); - property_set_param_obj = cJSON_Parse(iotx_cmp_message_info->parameter); - assert(property_set_param_obj && cJSON_IsObject(property_set_param_obj)); - - property_iterator(thing, find_and_set_lite_property_for_service_property_set, dm_thing_manager, property_set_param_obj, thing, NULL); - - dm_log_info("%s triggerd", string_method_name_property_set); - -#ifdef RRPC_ENABLED - dm_thing_manager_answer_service(dm_thing_manager, thing, dm_thing_manager->_service_identifier_requested, - dm_thing_manager->_request_id, dm_thing_manager->_ret == 0 ? 200 : 400, 0); -#else - dm_thing_manager_answer_service(dm_thing_manager, thing, dm_thing_manager->_service_identifier_requested, - dm_thing_manager->_request_id, dm_thing_manager->_ret == 0 ? 200 : 400); -#endif /* RRPC_ENABLED */ - - cJSON_Delete(property_set_param_obj); - - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_property_get)) { /* thing/service/property/get match */ - assert(iotx_cmp_message_info->parameter); - list = dm_thing_manager->_service_property_get_identifier_list; - property_get_param_obj = cJSON_Parse(iotx_cmp_message_info->parameter); - - assert(property_get_param_obj && cJSON_IsArray(property_get_param_obj)); - - if (property_get_param_obj == NULL || cJSON_IsArray(property_get_param_obj) == 0) { - dm_log_err("UNABLE to resolve %s params format", string_method_name_property_get); - return; - } - - array_size = cJSON_GetArraySize(property_get_param_obj); - for (index = 0; index < array_size; ++index) { - property_get_param_item_obj = cJSON_GetArrayItem(property_get_param_obj, index); - assert(cJSON_IsString(property_get_param_item_obj)); -#ifndef CJSON_STRING_ZEROCOPY - property_get_param_identifier = dm_lite_calloc(1, strlen(property_get_param_item_obj->valuestring) + 1); - strcpy(property_get_param_identifier, property_get_param_item_obj->valuestring); -#else - property_get_param_identifier = dm_lite_calloc(1, property_get_param_item_obj->valuestring_length + 1); - strncpy(property_get_param_identifier, property_get_param_item_obj->valuestring, - property_get_param_item_obj->valuestring_length); -#endif - list_insert(list, property_get_param_identifier); - } - cJSON_Delete(property_get_param_obj); -#ifdef RRPC_ENABLED - dm_thing_manager_answer_service(dm_thing_manager, thing, dm_thing_manager->_service_identifier_requested, - dm_thing_manager->_request_id, 200, 0); -#else - dm_thing_manager_answer_service(dm_thing_manager, thing, dm_thing_manager->_service_identifier_requested, - dm_thing_manager->_request_id, 200); -#endif /* RRPC_ENABLED */ - - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_thing_enable)) { /* thing/enable match */ - /* invoke callback funtions. */ - invoke_callback_list(dm_thing_manager, dm_callback_type_thing_enabled); - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_thing_disable)) { /* thing/disable match */ - /* invoke callback funtions. */ - invoke_callback_list(dm_thing_manager, dm_callback_type_thing_disabled); -#ifdef RRPC_ENABLED - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_rrpc_request)) { /* rrpc/request match */ - char* p; -// "/sys/productKey/{productKey}/productKey/{deviceName}/rrpc/request/${messageId}" - p = strrchr(iotx_cmp_message_info->URI, '/'); - if (p) { - p++; - dm_thing_manager->_rrpc_message_id = atoi(p); - } - /* invoke callback funtions. */ - dm_thing_manager->_identifier = dm_thing_manager->_service_identifier_requested; - invoke_callback_list(dm_thing_manager, dm_callback_type_rrpc_requested); -#endif /* RRPC_ENABLED */ -#ifdef DEVICEINFO_ENABLED - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_deviceinfo_update_reply)) { /* deviceinfo/update_reply. */ - - } else if (strstr(iotx_cmp_message_info->URI, string_method_name_deviceinfo_delete_reply)) { /* deviceinfo/delete_reply. */ -#endif /* DEVICEINFO_ENABLED*/ - } else if (iotx_cmp_message_info->message_type == IOTX_CMP_MESSAGE_REQUEST) { /* normal service. */ - /* invoke callback funtions. */ - dm_thing_manager->_identifier = dm_thing_manager->_service_identifier_requested; - invoke_callback_list(dm_thing_manager, dm_callback_type_service_requested); - } else if (iotx_cmp_message_info->message_type == IOTX_CMP_MESSAGE_RESPONSE) { /* event resonse. */ - /* invoke callback funtions. */ - dm_thing_manager->_identifier = dm_thing_manager->_service_identifier_requested; - } - } - - if (iotx_cmp_message_info->URI) { - dm_lite_free(iotx_cmp_message_info->URI); - iotx_cmp_message_info->URI = NULL; - } - - if (iotx_cmp_message_info->method) { - dm_lite_free(iotx_cmp_message_info->method); - iotx_cmp_message_info->method = NULL; - } - - if (iotx_cmp_message_info->parameter) { - dm_lite_free(iotx_cmp_message_info->parameter); - iotx_cmp_message_info->parameter = NULL; - } - -} - -static void send_request_to_uri(void* _dm_thing_manager, const char* _uri) -{ - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - const char* uri = _uri; - message_info_t** message_info = dm_thing_manager->_message_info; - cmp_abstract_t** cmp = dm_thing_manager->_cmp; - thing_t** thing = dm_thing_manager->_thing_id; - char uri_buff[URI_MAX_LENGH] = {0}; - char method_buff[METHOD_MAX_LENGH] = {0}; - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - char* p; - int ret; - - assert(dm_thing_manager && uri && message_info && cmp); - - get_product_key_device_name(product_key, device_name, thing, dm_thing_manager); - - strcpy(method_buff, uri); - - /* subtitute '/' by '.' */ - do { - p = strchr(method_buff, '/'); - if (p) *p = '.'; - } while (p); - - dm_thing_manager->_method = method_buff; - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s", product_key, device_name, uri); - - clear_and_set_message_info(message_info, dm_thing_manager); - - (*message_info)->set_uri(message_info, uri_buff); - (*message_info)->set_message_type(message_info, CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST); - - ret = (*message_info)->serialize_to_payload_request(message_info); - - if (ret == -1) { - dm_log_err("serialize_to_payload_request FAIL"); - return; - } - (*cmp)->send(cmp, message_info, NULL); - -} - -static void* dm_thing_manager_ctor(void* _self, va_list* params) -{ - dm_thing_manager_t* self = _self; - cmp_abstract_t** cmp; - handle_dm_callback_fp_t callback_func; - list_t** list; - - self->_name = va_arg(*params, char*); - self->_get_tsl_from_cloud = va_arg(*params, int); - callback_func = va_arg(*params, void*); - self->_cloud_domain = va_arg(*params, int); - - assert(self->_name); - - self->_local_thing_list = new_object(SINGLE_LIST_CLASS, string_local_thing_list); - self->_local_thing_name_list = new_object(SINGLE_LIST_CLASS, string_local_thing_name_list); - self->_sub_thing_list = new_object(SINGLE_LIST_CLASS, string_sub_thing_list); - self->_callback_list = new_object(SINGLE_LIST_CLASS, string_callback_list); - self->_service_property_get_identifier_list = new_object(SINGLE_LIST_CLASS, string_service_property_get_identifier_list); - self->_local_thing_id = 0; - self->_thing_id = NULL; - self->_message_info = new_object(CMP_MESSAGE_INFO_CLASS); - self->_dm_version = DM_REQUEST_VERSION_STRING; - self->_id = 0; - self->_method = NULL; - self->_cmp = new_object(CMP_ABSTRACT_IMPL_CLASS); - self->_cmp_event_handle_func_fp = cmp_event_handler; - self->_cmp_register_func_fp = cmp_register_handler; - self->_cloud_connected = 0; - self->_property_identifier_set = NULL; - self->_destructing = 0; - - list = (list_t**)self->_callback_list; - if (callback_func) list_insert(list, callback_func); - - /* get relative information. */ - HAL_GetProductKey(self->_product_key); - HAL_GetDeviceName(self->_device_name); - HAL_GetDeviceSecret(self->_device_secret); - HAL_GetDeviceID(self->_device_id); - - assert(self->_product_key && self->_device_name && self->_device_secret && self->_device_id); - - cmp = self->_cmp; - - if(FAIL_RETURN == (*cmp)->init(cmp, self->_product_key, self->_device_name, self->_device_secret, self->_device_id, self->_cmp_event_handle_func_fp, self, self->_cloud_domain)) { - dm_log_err("cmp init failed"); - } - - cJSON_Hooks hook = { - dm_lite_malloc, - dm_lite_free_func, - }; - - cJSON_InitHooks(&hook); - - return self; -} - -static void* dm_thing_manager_dtor(void* _self) -{ - dm_thing_manager_t* self = _self; - list_t** list; - - self->_destructing = 1; - - local_thing_list_iterator(self, free_list_thing); - - list = self->_local_thing_name_list; - list_iterator(list, free_list_string, self); - - list = self->_service_property_get_identifier_list; - list_iterator(list, free_list_string, self); - - assert(self->_local_thing_list && self->_local_thing_name_list && self->_sub_thing_list && self->_callback_list && self->_message_info); - - delete_object(self->_local_thing_list); - delete_object(self->_local_thing_name_list); - delete_object(self->_service_property_get_identifier_list); - delete_object(self->_sub_thing_list); - delete_object(self->_callback_list); - delete_object(self->_message_info); - delete_object(self->_cmp); - - self->_dm_version = NULL; - self->_id = 0; - self->_method = NULL; - - return self; -} - -static void generate_thing_event_service_subscribe_uri(void* _item, int index, va_list* params) -{ - event_t* event = NULL; - service_t* service = NULL; - dm_thing_manager_t* dm_thing_manager; - thing_t** thing; - cmp_abstract_t** cmp; - - char method_buff[METHOD_MAX_LENGH] = {0}; - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - char delimeter[] = {'.', 0}; - char* uri_buff; - char* p; - char* type; - - dm_thing_manager = va_arg(*params, void*); - thing = va_arg(*params, void*); - uri_buff = va_arg(*params, char*); - type = va_arg(*params, char*); - - if (strcmp(type, string_event) == 0) { - event = _item; - } else if (strcmp(type, string_service) == 0) { - service = _item; - } else { - assert(0); - } - assert(dm_thing_manager && uri_buff && _item); - - get_product_key_device_name(product_key, device_name, thing, dm_thing_manager); - - dm_sprintf(uri_buff, "/sys/%s/%s", product_key, device_name); - - sprintf(method_buff, event ? "%s_reply" : "%s", event ? event->method : service->method); - - p = strtok(method_buff, delimeter); - while (p) { - dm_sprintf(uri_buff + strlen(uri_buff), "/%s", p); - p = strtok(NULL, delimeter); - } - - cmp = dm_thing_manager->_cmp; - (*cmp)->regist(cmp, uri_buff, dm_thing_manager->_cmp_register_func_fp, dm_thing_manager, NULL); -} - -static void generate_subscribe_uri(void* _dm_thing_manager, void* _thing) -{ - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - thing_t** thing = _thing; - cmp_abstract_t** cmp = dm_thing_manager->_cmp; - - int index; - const char** uri; - char uri_buff[URI_MAX_LENGH] = {0}; - const char* uri_array[] = {string_method_name_thing_enable, string_method_name_thing_delete, string_method_name_thing_disable, - string_method_name_thing_dsl_get_reply, string_method_name_down_raw, string_method_name_up_raw_reply, -#ifdef DEVICEINFO_ENABLED - string_method_name_deviceinfo_update_reply, string_method_name_deviceinfo_delete_reply, -#endif /* DEVICEINFO_ENABLED*/ -#ifdef RRPC_ENABLED - string_method_name_rrpc_request_plus, -#endif /* RRPC_ENABLED */ - }; - - if (dm_thing_manager->_cloud_connected == 0) { - dm_log_err("subscribe not allowed when cloud not connected"); - return; - } - - if (thing) { - event_iterator(thing, generate_thing_event_service_subscribe_uri, dm_thing_manager, thing, uri_buff, string_event); - service_iterator(thing, generate_thing_event_service_subscribe_uri, dm_thing_manager, thing, uri_buff, string_service); - } else { - for (index = 0 ; index < sizeof(uri_array) / sizeof(char*); ++index) { - uri = uri_array + index; - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/", dm_thing_manager->_product_key, dm_thing_manager->_device_name); - strcat(uri_buff, *uri); - - (*cmp)->regist(cmp, uri_buff, dm_thing_manager->_cmp_register_func_fp, dm_thing_manager, NULL); - } - } -} - -static void* dm_thing_manager_generate_new_local_thing(void* _self, const char* tsl, int tsl_len) -{ - dm_thing_manager_t* self = _self; - thing_t** thing; - list_t** list; - char* thing_name; - size_t name_size; - - assert(tsl); - - name_size = sizeof(DM_LOCAL_THING_NAME_PATTERN) + 2; - thing_name = (char*)dm_lite_calloc(1, name_size); - - memset(thing_name, 0, name_size); - dm_sprintf(thing_name, DM_LOCAL_THING_NAME_PATTERN, self->_local_thing_id++); - - thing = (thing_t**)new_object(DM_THING_CLASS, thing_name); - - if(0 == (*thing)->set_dsl_string(thing, tsl, tsl_len)) { - list = self->_local_thing_list; - list_insert(list, thing); - - list = self->_local_thing_name_list; - list_insert(list, thing_name); - - self->_thing_id = thing; - - dm_log_debug("new thing created@%p", self->_thing_id); - - /* subscribe subjects. */ - generate_subscribe_uri(self, thing); - - /* invoke callback funtions. */ - invoke_callback_list(self, dm_callback_type_new_thing_created); - }else { - delete_object(thing); - thing = NULL; - } - - return thing; -} - -static int dm_thing_manager_add_callback_function(void* _self, handle_dm_callback_fp_t callback_func) -{ - dm_thing_manager_t* self = _self; - list_t** list; - - list = (list_t**)self->_callback_list; - - assert(list); - - if (callback_func) list_insert(list, callback_func); - - return 0; -} - -static void free_list_thing(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - (void)dm_thing_manager; - - assert(thing && *thing); - - delete_object(thing); -} - -static void free_list_string(void* _string, va_list* params) -{ - void* string = _string; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - (void)dm_thing_manager; - - assert(string && dm_thing_manager); - - dm_lite_free(string); - - string = NULL; -} - -static void get_service_input_output_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing && (*thing)->get_service_input_output_data_value_by_identifier); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = (*thing)->get_service_input_output_data_value_by_identifier(thing, dm_thing_manager->_identifier, - dm_thing_manager->_get_value, &dm_thing_manager->_get_value_str); - } -} - -static void set_service_input_output_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing && (*thing)->set_service_input_output_data_value_by_identifier); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = (*thing)->set_service_input_output_data_value_by_identifier(thing, dm_thing_manager->_identifier, - dm_thing_manager->_set_value, dm_thing_manager->_set_value_str); - } -} - -static void get_event_output_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing && (*thing)->get_event_value_by_identifier); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = (*thing)->get_event_value_by_identifier(thing, dm_thing_manager->_identifier, dm_thing_manager->_get_value, &dm_thing_manager->_get_value_str); - } -} - -static void set_event_output_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing && (*thing)->set_event_value_by_identifier); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = (*thing)->set_event_value_by_identifier(thing, dm_thing_manager->_identifier, - dm_thing_manager->_set_value, dm_thing_manager->_set_value_str); - } -} - -static void invoke_callback_func(void* _callback_fp, va_list* params) -{ - handle_dm_callback_fp_t callback_fp = _callback_fp; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && callback_fp); - - if (callback_fp && dm_thing_manager) { - callback_fp(dm_thing_manager->_callback_type, dm_thing_manager->_thing_id, dm_thing_manager->_identifier, - dm_thing_manager->_request_id, dm_thing_manager->_raw_data, dm_thing_manager->_raw_data_length); - } -} - -static void callback_list_iterator(const void* _self, handle_fp_t handle_fp) -{ - const dm_thing_manager_t* self = _self; - list_t** list = (list_t**)self->_callback_list; - - assert((*list)->iterator); - list_iterator(list, handle_fp, self); -} - -static void set_property_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing && (*thing)->set_property_value_by_identifier); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = (*thing)->set_property_value_by_identifier(thing, dm_thing_manager->_identifier, dm_thing_manager->_set_value, dm_thing_manager->_set_value_str); - - /* invoke callback funtions. */ - - if (strchr(dm_thing_manager->_identifier, '.') == NULL && - strchr(dm_thing_manager->_identifier, '[') == NULL && - strchr(dm_thing_manager->_identifier, ']') == NULL ) { - invoke_callback_list(dm_thing_manager, dm_callback_type_property_value_set); - - } - } -} - -static void get_property_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing && (*thing)->get_property_value_by_identifier); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = (*thing)->get_property_value_by_identifier(thing, dm_thing_manager->_identifier, dm_thing_manager->_get_value, &dm_thing_manager->_get_value_str); - } -} - -static void local_thing_list_iterator(const void* _self, handle_fp_t handle_fp) -{ - const dm_thing_manager_t* self = _self; - list_t** list = (list_t**)self->_local_thing_list; - - assert((*list)->iterator); - list_iterator(list, handle_fp, self); -} - -static int dm_thing_manager_set_thing_property_value(void* _self, const void* thing_id, const void* identifier, - const void* value, const char* value_str) -{ - dm_thing_manager_t* self = _self; - - assert(thing_id && identifier && (value || value_str)); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_set_value = (void*)value; - self->_set_value_str = (char*)value_str; - self->_ret = -1; - - local_thing_list_iterator(self, set_property_value); - - return self->_ret; -} - -static int dm_thing_manager_get_thing_property_value(void* _self, const void* thing_id, const void* identifier, - void* value, char** value_str) -{ - dm_thing_manager_t* self = _self; - - assert(thing_id && identifier && (value || value_str)); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_get_value = value; - self->_ret = -1; - self->_get_value_str = NULL; - - local_thing_list_iterator(self, get_property_value); - - if (value_str) *value_str = self->_get_value_str; - - return self->_ret; -} - -static int dm_thing_manager_set_thing_event_output_value(void* _self, const void* thing_id, const void* identifier, - const void* value, const char* value_str) -{ - dm_thing_manager_t* self = _self; - - assert(thing_id && identifier && (value || value_str)); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_set_value = (void*)value; - self->_set_value_str = (char*)value_str; - self->_ret = -1; - - local_thing_list_iterator(self, set_event_output_value); - - return self->_ret; -} - -static int dm_thing_manager_get_thing_event_output_value(void* _self, const void* thing_id, const void* identifier, - void* value, char** value_str) -{ - dm_thing_manager_t* self = _self; - - assert(thing_id && identifier && (value || value_str)); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_get_value = value; - self->_ret = -1; - - local_thing_list_iterator(self, get_event_output_value); - - if (value_str) *value_str = self->_get_value_str; - - return self->_ret; -} - -static int dm_thing_manager_get_thing_service_input_value(void* _self, const void* thing_id, const void* identifier, - void* value, char** value_str) -{ - dm_thing_manager_t* self = _self; - - assert(thing_id && identifier && (value || value_str)); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_get_value = value; - self->_ret = -1; - - local_thing_list_iterator(self, get_service_input_output_value); - - if (value_str) *value_str = self->_get_value_str; - - return self->_ret; -} - -static int dm_thing_manager_get_thing_service_output_value(void* _self, const void* thing_id, const void* identifier, - void* value, char** value_str) -{ - dm_thing_manager_t* self = _self; - - return dm_thing_manager_get_thing_service_input_value(self, thing_id, identifier, value, value_str); -} - -static int dm_thing_manager_set_thing_service_output_value(void* _self, const void* thing_id, const void* identifier, - const void* value, const char* value_str) -{ - dm_thing_manager_t* self = _self; - - assert(thing_id && identifier && (value || value_str)); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_set_value = (void*)value; - self->_set_value_str = (char*)value_str; - self->_ret = -1; - - local_thing_list_iterator(self, set_service_input_output_value); - - return self->_ret; -} - -static int install_lite_property_to_message_info(dm_thing_manager_t* _thing_manager, message_info_t** _message_info, lite_property_t* _lite_property) -{ - lite_property_t* lite_property = _lite_property; - message_info_t** message_info = _message_info; - dm_thing_manager_t* dm_thing_manager = _thing_manager; - thing_t** thing = dm_thing_manager->_thing_id; - char* p = NULL; - - char* q = NULL; - dm_thing_t* dm_thing; - size_t params_buffer_len = 0; - size_t params_val_len = 0; - int ret, i; - char property_key_value_buff[PROPERTY_KEY_VALUE_BUFF_MAX_LENGTH] = {0}; - - ret = (*thing)->get_lite_property_value(thing, lite_property, NULL, &dm_thing_manager->_get_value_str); - - if ((lite_property->data_type.type == data_type_type_text || lite_property->data_type.type == data_type_type_date) && dm_thing_manager->_get_value_str) { - p = dm_lite_calloc(1, strlen(dm_thing_manager->_get_value_str) + 3); - assert(p); - - dm_sprintf(p, "\"%s\"", dm_thing_manager->_get_value_str); - dm_thing_manager->_get_value_str = p; - } - - if (ret != 0 && lite_property->data_type.type == data_type_type_array) { - dm_thing = (dm_thing_t*)thing; - property_key_value_buff[0] = '['; - property_key_value_buff[1] = '\0'; - - params_buffer_len = sizeof(property_key_value_buff); - for (i = 0; i < lite_property->data_type.value.data_type_array_t.size; i++) { - dm_thing->_arr_index = i; - dm_thing_manager->_get_value_str = NULL; - ret = (*thing)->get_lite_property_value(thing, lite_property, NULL, &dm_thing_manager->_get_value_str); - params_val_len = strlen(property_key_value_buff); - - if (ret != 0 || !dm_thing_manager->_get_value_str) { - dm_thing_manager->_get_value_str = NULL; - } - if (lite_property->data_type.value.data_type_array_t.item_type == data_type_type_text) { - dm_snprintf(property_key_value_buff + params_val_len, params_buffer_len - params_val_len, "\"%s\",", dm_thing_manager->_get_value_str ? dm_thing_manager->_get_value_str : ""); - } else { - dm_snprintf(property_key_value_buff + params_val_len, params_buffer_len - params_val_len, "%s,", dm_thing_manager->_get_value_str ? dm_thing_manager->_get_value_str : "0"); - } - } - q = property_key_value_buff + strlen(property_key_value_buff) - 1; - if (*q == '[') *(q+1) = ']'; - if (*q == ',') *(q) = ']'; - - dm_thing->_arr_index = -1; - - (*message_info)->add_params_data_item(message_info, lite_property->identifier, property_key_value_buff); - - return 0; - } - - if (ret == 0 && lite_property->identifier && dm_thing_manager->_get_value_str) { - (*message_info)->add_params_data_item(message_info, lite_property->identifier, dm_thing_manager->_get_value_str); - } - - if (p) dm_lite_free(p); - - return ret; -} - -static void get_product_key_device_name(char* _product_key, char* _device_name, void* _thing, void* _dm_thing_manager) -{ - char* product_key = _product_key; - char* device_name = _device_name; - - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - if (thing && *thing) { - dm_thing_manager_install_product_key_device_name(dm_thing_manager, thing, product_key, device_name); - } else { - strcpy(product_key, dm_thing_manager->_product_key); - strcpy(device_name, dm_thing_manager->_device_name); - } -} - -static void clear_and_set_message_info(message_info_t** _message_info, dm_thing_manager_t* _dm_thing_manager) -{ - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - message_info_t** message_info = _message_info; - thing_t** thing; - - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - - assert(message_info && *message_info && dm_thing_manager); - - if (message_info == NULL || *message_info == NULL || dm_thing_manager == NULL) return; - - thing = dm_thing_manager->_thing_id; - - get_product_key_device_name(product_key, device_name, thing, dm_thing_manager); - if (0 == dm_thing_manager->_id) dm_thing_manager->_id++; - - (*message_info)->clear(message_info); - - (*message_info)->set_product_key(message_info, product_key); - (*message_info)->set_device_name(message_info, device_name); - (*message_info)->set_version(message_info, dm_thing_manager->_dm_version); - (*message_info)->set_id(message_info, dm_thing_manager->_id); - dm_thing_manager->_id = (dm_thing_manager->_id + 1) % INT32_MAX; - (*message_info)->set_method(message_info, dm_thing_manager->_method); -} - -static void install_property_to_message_info(void* _item, int index, va_list* params) -{ - property_t* property = _item; - lite_property_t* lite_property; - lite_property_t* struct_lite_property; - dm_thing_manager_t* dm_thing_manager; - thing_t** thing; - message_info_t** message_info; - size_t params_buffer_len = 0; - size_t params_val_len = 0; - char* target_property_identifier; - int ret, i; - char property_key_value_buff[PROPERTY_KEY_VALUE_BUFF_MAX_LENGTH] = {0}; - char* p; - char* q = NULL; - - dm_thing_manager = va_arg(*params, dm_thing_manager_t*); - thing = va_arg(*params, thing_t**); - message_info = va_arg(*params, message_info_t**); - target_property_identifier = va_arg(*params, char*); - - index = index; - - assert(property && dm_thing_manager && thing && *thing && message_info && *message_info); - - lite_property = (lite_property_t*)property; - - /* post all value, or specify identifier. */ - if (property && (target_property_identifier == NULL || (property->identifier && strcmp(property->identifier, target_property_identifier) == 0))) { - ret = install_lite_property_to_message_info(dm_thing_manager, message_info, lite_property); - - params_buffer_len = sizeof(property_key_value_buff); - if (ret == -1) { - if(property->data_type.type == data_type_type_struct) { - property_key_value_buff[0] = '{'; - property_key_value_buff[1] = '\0'; - for (i = 0; i < property->data_type.data_type_specs_number; ++i) { - struct_lite_property = (lite_property_t*)property->data_type.specs + i; - ret = (*thing)->get_lite_property_value(thing, struct_lite_property, NULL, &dm_thing_manager->_get_value_str); - if (ret == 0 && dm_thing_manager->_get_value_str) { - params_val_len = strlen(property_key_value_buff); - p = property_key_value_buff + params_val_len - 1; - - /* not the last item, chang from '}' to ','. */ - if (p && *p == '}') *p = ','; - - if (struct_lite_property->data_type.type == data_type_type_text && dm_thing_manager->_get_value_str) { - q = dm_lite_calloc(1, strlen(dm_thing_manager->_get_value_str) + 3); - assert(q); - - dm_snprintf(q, strlen(dm_thing_manager->_get_value_str) + 3, "\"%s\"", dm_thing_manager->_get_value_str); - dm_thing_manager->_get_value_str = q; - } - - dm_snprintf(property_key_value_buff + params_val_len, params_buffer_len - params_val_len, "\"%s\":%s}", - struct_lite_property->identifier, dm_thing_manager->_get_value_str); - - if (q) dm_lite_free(q); - } - } - - } - (*message_info)->add_params_data_item(message_info, property->identifier, property_key_value_buff); - } - dm_thing_manager->_ret = 0; - } -} - -static void handle_event_key_value(void* _item, int index, va_list* params) -{ - event_t* event; - lite_property_t* lite_property; - dm_thing_manager_t* dm_thing_manager; - message_info_t** message_info; - thing_t** thing; - char method_buff[METHOD_MAX_LENGH] = {0}; - char uri_buff[URI_MAX_LENGH] = {0}; - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - - char* p; - int output_data_numb; - int i; - - (void)index; - dm_thing_manager = va_arg(*params, void*); - message_info = va_arg(*params, message_info_t**); - thing = va_arg(*params, thing_t**); - - assert(dm_thing_manager && message_info && *message_info && (*message_info)->set_message_type && thing && *thing); - - event = _item; - if (strcmp(event->identifier, dm_thing_manager->_identifier) != 0) return; - - dm_thing_manager->_method = event->method; - - clear_and_set_message_info(message_info, dm_thing_manager); - - (*message_info)->set_message_type(message_info, CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST); - - strcpy(method_buff, event->method); - /* subtitute '.' by '/' */ - do { - p = strchr(method_buff, '.'); - if (p) *p = '/'; - } while (p); - - dm_thing_manager_install_product_key_device_name(dm_thing_manager,thing,product_key,device_name); - - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s", product_key, device_name, method_buff); - (*message_info)->set_uri(message_info, uri_buff); - - if (strcmp(dm_thing_manager->_method, string_thing_event_property_post) != 0) { - output_data_numb = event->event_output_data_num; - for (i = 0; i < output_data_numb; ++i) { - lite_property = event->event_output_data + i; - assert(lite_property); - install_lite_property_to_message_info(dm_thing_manager, message_info, lite_property); - } - dm_thing_manager->_ret = 0; - } else { - property_iterator(thing, install_property_to_message_info, dm_thing_manager, thing, - dm_thing_manager->_message_info, dm_thing_manager->_property_identifier_post); - } - -} - -static void install_service_property_get_to_message_info(void* _string, va_list* params) -{ - char* identifier_to_get = _string; - dm_thing_manager_t* dm_thing_manager; - thing_t** thing; - message_info_t** message_info; - - dm_thing_manager = va_arg(*params, dm_thing_manager_t*); - thing = va_arg(*params, thing_t**); - message_info = va_arg(*params, message_info_t**); - - assert(identifier_to_get); - - property_iterator(thing, install_property_to_message_info, dm_thing_manager, thing, message_info, identifier_to_get); -} - -static void handle_service_key_value(void* _item, int index, va_list* params) -{ - service_t* service; - lite_property_t* lite_property; - dm_thing_manager_t* dm_thing_manager; - message_info_t** message_info; - thing_t** thing; - list_t** list; - int output_data_numb; - char method_buff[METHOD_MAX_LENGH] = {0}; - char uri_buff[URI_MAX_LENGH] = {0}; - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - - char* p; - int i; - - (void)index; - dm_thing_manager = va_arg(*params, void*); - message_info = va_arg(*params, message_info_t**); - thing = va_arg(*params, thing_t**); - - assert(dm_thing_manager && message_info && *message_info && thing && *thing); - - service = _item; - list = dm_thing_manager->_service_property_get_identifier_list; - - if (service && service->identifier && strcmp(service->identifier, dm_thing_manager->_identifier) != 0) return; - - dm_thing_manager->_method = service->method; - - clear_and_set_message_info(message_info, dm_thing_manager); - - strcpy(method_buff, service->method); - /* subtitute '.' by '/' */ - do { - p = strchr(method_buff, '.'); - if (p) *p = '/'; - } while (p); - - dm_thing_manager_install_product_key_device_name(dm_thing_manager,thing,product_key,device_name); -#ifdef RRPC_ENABLED - if (dm_thing_manager->_rrpc) { - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/rrpc/response/%d", product_key, device_name, dm_thing_manager->_rrpc_message_id); - } else { - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s_reply", product_key, device_name, method_buff); - } -#else - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s_reply", product_key, device_name, method_buff); -#endif /* RRPC_ENABLED */ - - (*message_info)->set_uri(message_info, uri_buff); - - (*message_info)->set_message_type(message_info, CMP_MESSAGE_INFO_MESSAGE_TYPE_RESPONSE); - (*message_info)->set_id(message_info, dm_thing_manager->_response_id); - (*message_info)->set_code(message_info, dm_thing_manager->_code); - - if (strcmp(dm_thing_manager->_method, string_thing_service_property_set) == 0) { - /* set property */ - } else if (strcmp(dm_thing_manager->_method, string_thing_service_property_get) == 0) { - assert((*list)->get_size(list)); - /* get property */ - list_iterator(list, install_service_property_get_to_message_info, dm_thing_manager, thing, dm_thing_manager->_message_info); - /* clear after use. */ - list_iterator(list, free_list_string, dm_thing_manager); - (*list)->clear(list); - } else { - /* normal service */ - output_data_numb = service->service_output_data_num; - for (i = 0; i < output_data_numb; ++i) { - lite_property = service->service_output_data + i; - assert(lite_property); - install_lite_property_to_message_info(dm_thing_manager, message_info, lite_property); - } - } -} - -static void get_event_key_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing); - - if (dm_thing_manager->_thing_id == thing) { - event_iterator(thing, handle_event_key_value, dm_thing_manager, dm_thing_manager->_message_info, thing); - } -} - -static void get_service_key_value(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing); - - if (dm_thing_manager->_thing_id == thing) { - service_iterator(thing, handle_service_key_value, dm_thing_manager, dm_thing_manager->_message_info, thing); - } -} - -static int dm_thing_manager_trigger_event(void* _self, const void* thing_id, const void* event_identifier, const char* property_identifier) -{ - dm_thing_manager_t* self = _self; - message_info_t** message_info = self->_message_info; - cmp_abstract_t** cmp = self->_cmp; - int ret; - - assert(thing_id && event_identifier && cmp && *cmp); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)event_identifier; - self->_property_identifier_post = (void*)property_identifier; - self->_ret = -1; - self->_get_value_str = NULL; - - local_thing_list_iterator(self, get_event_key_value); - - if(-1 != self->_ret) { - dm_log_debug("event(%s) triggered, method(%s)", self->_identifier, self->_method); - ret = (*message_info)->serialize_to_payload_request(message_info); - if (ret == -1) { - dm_log_err("serialize_to_payload_request FAIL"); - return ret; - } - - self->_ret = (*cmp)->send(cmp, message_info, NULL); - } - - return self->_ret; -} - -#ifdef DEVICEINFO_ENABLED -static void check_thing_id(void* _thing, va_list* params) -{ - thing_t** thing = _thing; - dm_thing_manager_t* dm_thing_manager; - - dm_thing_manager = va_arg(*params, void*); - - assert(dm_thing_manager && thing && *thing); - - if (dm_thing_manager->_thing_id == thing) { - dm_thing_manager->_ret = 0; - } -} - -static int check_deviceinfo_params(const char* params) -{ - cJSON* params_obj; - int array_size; - - params_obj = cJSON_Parse(params); - - if (!cJSON_IsArray(params_obj)) { - dm_log_err("input params format errorm, MUST be json array type"); - return -1; - } - - array_size = cJSON_GetArraySize(params_obj); - - if (array_size <= 0) return -1; - - cJSON_Delete(params_obj); - - return 0; -} - -static int dm_thing_manager_trigger_deviceinfo_update(void* _self, const void* thing_id, const char* params) -{ - dm_thing_manager_t* self = _self; - message_info_t** message_info = self->_message_info; - cmp_abstract_t** cmp = self->_cmp; - thing_t** thing; - - char method_buff[METHOD_MAX_LENGH] = {0}; - char uri_buff[URI_MAX_LENGH] = {0}; - - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - - char* p; - - assert(thing_id && cmp && *cmp && message_info && *message_info); - - self->_thing_id = (void*)thing_id; - self->_ret = -1; - self->_get_value_str = NULL; - - check_deviceinfo_params(params); - - local_thing_list_iterator(self, check_thing_id); - - if (self->_ret != 0) return -1; - - thing = (thing_t**)thing_id; - - strcpy(method_buff, string_method_name_deviceinfo_update); - /* subtitute '/' by '.' */ - do { - p = strchr(method_buff, '/'); - if (p) *p = '.'; - } while (p); - - self->_method = method_buff; - - clear_and_set_message_info(message_info, self); - - (*message_info)->set_message_type(message_info, CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST); - - dm_thing_manager_install_product_key_device_name(self,thing,product_key,device_name); - - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s", product_key, device_name, string_method_name_deviceinfo_update); - (*message_info)->set_uri(message_info, uri_buff); - - (*message_info)->set_params_data(message_info, (char*)params); - - return (*cmp)->send(cmp, message_info, NULL); -} - -static int dm_thing_manager_trigger_deviceinfo_delete(void* _self, const void* thing_id, const char* params) -{ - dm_thing_manager_t* self = _self; - message_info_t** message_info = self->_message_info; - cmp_abstract_t** cmp = self->_cmp; - thing_t** thing; - - char method_buff[METHOD_MAX_LENGH] = {0}; - char uri_buff[URI_MAX_LENGH] = {0}; - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - char* p; - - assert(thing_id && cmp && *cmp && message_info && *message_info); - - self->_thing_id = (void*)thing_id; - self->_ret = -1; - self->_get_value_str = NULL; - - check_deviceinfo_params(params); - - local_thing_list_iterator(self, check_thing_id); - - if (self->_ret != 0) return -1; - - thing = (thing_t**)thing_id; - - strcpy(method_buff, string_method_name_deviceinfo_delete); - /* subtitute '/' by '.' */ - do { - p = strchr(method_buff, '/'); - if (p) *p = '.'; - } while (p); - - self->_method = method_buff; - - clear_and_set_message_info(message_info, self); - - (*message_info)->set_message_type(message_info, CMP_MESSAGE_INFO_MESSAGE_TYPE_REQUEST); - - dm_thing_manager_install_product_key_device_name(self,thing,product_key,device_name); - - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s", product_key, device_name, string_method_name_deviceinfo_delete); - (*message_info)->set_uri(message_info, uri_buff); - - (*message_info)->set_params_data(message_info, (char*)params); - - return (*cmp)->send(cmp, message_info, NULL); -} -#endif /* DEVICEINFO_ENABLED*/ -static int generate_raw_message_info(void* _dm_thing_manager, void* _thing, void* _message_info, const char* raw_topic) -{ - dm_thing_manager_t* dm_thing_manager = _dm_thing_manager; - thing_t** thing = _thing; - message_info_t** message_info = _message_info; - - char product_key[PRODUCT_KEY_MAXLEN] = {0}; - char device_name[DEVICE_NAME_MAXLEN] = {0}; - - char uri_buff[URI_MAX_LENGH] = {0}; - int ret; - - dm_thing_manager_install_product_key_device_name(dm_thing_manager,thing,product_key,device_name); - - dm_snprintf(uri_buff, sizeof(uri_buff), "/sys/%s/%s/%s", product_key, device_name, raw_topic); - - clear_and_set_message_info(message_info, dm_thing_manager); - - ret = (*message_info)->set_uri(message_info, uri_buff); - if (ret == -1) return ret; - - (*message_info)->set_message_type(message_info, CMP_MESSAGE_INFO_MESSAGE_TYPE_RAW); - - ret = (*message_info)->set_raw_data_and_length(message_info, dm_thing_manager->_raw_data, dm_thing_manager->_raw_data_length); - if (ret == -1) return ret; - - return 0; -} - -static int generate_raw_up_message_info(void* _dm_thing_manager, void* _thing, void* _message_info) -{ - return generate_raw_message_info(_dm_thing_manager, _thing, _message_info, string_method_name_up_raw); -} - -static int generate_raw_down_reply_message_info(void* _dm_thing_manager, void* _thing, void* _message_info) -{ - return generate_raw_message_info(_dm_thing_manager, _thing, _message_info, string_method_name_down_raw_reply); -} - -#ifdef RRPC_ENABLED -static int dm_thing_manager_answer_service(void* _self, const void* thing_id, const void* identifier, int response_id, int code, int rrpc) -#else -static int dm_thing_manager_answer_service(void* _self, const void* thing_id, const void* identifier, int response_id, int code) -#endif /* RRPC_ENABLED */ -{ - dm_thing_manager_t* self = _self; - message_info_t** message_info = self->_message_info; - cmp_abstract_t** cmp = self->_cmp; - int ret; - - assert(thing_id && identifier && cmp && *cmp); - - self->_thing_id = (void*)thing_id; - self->_identifier = (void*)identifier; - self->_ret = 0; - self->_get_value_str = NULL; - self->_code = code; - self->_response_id = response_id; - self->_method = NULL; - - /* response id matches request id. */ - if (self->_response_id == self->_request_id) { - dm_log_debug("response id(%d) matches request id(%d).", self->_response_id, self->_request_id); - self->_request_id = 0; - } else { - dm_log_warning("response id(%d) not matche request id(%d).", self->_response_id, self->_request_id); - } -#ifdef RRPC_ENABLED - self->_rrpc = rrpc; -#endif /* RRPC_ENABLED */ - local_thing_list_iterator(self, get_service_key_value); - - dm_log_debug("answer normal service(%s), method(%s)", self->_identifier, self->_method ? self->_method : "NULL"); - - ret = (*message_info)->serialize_to_payload_response(message_info); - - if (ret == -1) { - dm_log_err("serialize_to_payload_response FAIL"); - return ret; - } - - self->_ret = (*cmp)->send(cmp, message_info, NULL); - - return self->_ret; -} - -static int dm_thing_manager_invoke_raw_service(void* _self, const void* thing_id, void* raw_data, int raw_data_length) -{ - dm_thing_manager_t* self = _self; - message_info_t** message_info = self->_message_info; - cmp_abstract_t** cmp = self->_cmp; - - assert(thing_id); - - self->_thing_id = (void*)thing_id; - self->_ret = 0; - self->_raw_data = raw_data; - self->_raw_data_length = raw_data_length; - - dm_log_debug("invoke up raw service"); - - if (generate_raw_up_message_info(self, self->_thing_id, message_info) == -1) - { - dm_log_err("invoke up raw service FAIL!"); - return -1; - } - - self->_ret = (*cmp)->send(cmp, message_info, NULL); - - self->_raw_data = NULL; - self->_raw_data_length = 0; - - return self->_ret; -} - -static int dm_thing_manager_answer_raw_service(void* _self, const void* thing_id, void* raw_data, int raw_data_length) -{ - dm_thing_manager_t* self = _self; - message_info_t** message_info = self->_message_info; - cmp_abstract_t** cmp = self->_cmp; - - assert(thing_id); - - self->_thing_id = (void*)thing_id; - self->_ret = 0; - self->_raw_data = raw_data; - self->_raw_data_length = raw_data_length; - - dm_log_debug("invoke down raw reply service"); - - if (generate_raw_down_reply_message_info(self, self->_thing_id, message_info) == -1) - { - dm_log_err("invoke down raw reply service FAIL!"); - return -1; - } - - self->_ret = (*cmp)->send(cmp, message_info, NULL); - - self->_raw_data = NULL; - self->_raw_data_length = 0; - - return self->_ret; -} -#ifndef CMP_SUPPORT_MULTI_THREAD -static int dm_thing_manager_yield(void* _self, int timeout_ms) -{ - dm_thing_manager_t* self = _self; - cmp_abstract_t** cmp = self->_cmp; - - return (*cmp)->yield(cmp, timeout_ms); -} -#endif - - -static int dm_thing_manager_install_product_key_device_name(void *_self, const void* thing_id, char *product_key, char *device_name) -{ - char *dsl_product_key; - char *dsl_device_name; - char hal_product_key[PRODUCT_KEY_MAXLEN] = {0}; - char hal_device_name[DEVICE_NAME_MAXLEN] = {0}; - - dm_thing_manager_t* self = _self; - const thing_t** thing = (const thing_t**)thing_id; - - self->_ret = -1; - - if(HAL_GetProductKey(hal_product_key) <= 0 || - (HAL_GetDeviceName(hal_device_name) <= 0)) { - dm_log_err("get HAL DeviceInfo failed!"); - } - - dsl_product_key = (*thing)->return_product_key(thing); - dsl_device_name = (*thing)->return_device_name(thing); - - if(dsl_product_key && (0 == strcmp(dsl_product_key, hal_product_key))) { - strcpy(product_key, dsl_product_key); - }else { - dm_log_err("hal pk(%s) != dsl pk(%s)", hal_product_key, dsl_product_key ? dsl_product_key : "NULL"); - strcpy(product_key, hal_product_key); - } - if(dsl_device_name && (0 == strcmp(dsl_device_name, hal_device_name))) { - strcpy(device_name, dsl_device_name); - }else { - dm_log_err("hal dn(%s) != dsl dn(%s)", hal_device_name, dsl_device_name ? dsl_device_name : "NULL"); - strcpy(device_name, hal_device_name); - } - - self->_ret = 0; - - return self->_ret; -} - - -static thing_manager_t _dm_thing_manager_class = { - sizeof(dm_thing_manager_t), - string_dm_thing_manager_class_name, - dm_thing_manager_ctor, - dm_thing_manager_dtor, - dm_thing_manager_generate_new_local_thing, - dm_thing_manager_add_callback_function, - dm_thing_manager_set_thing_property_value, - dm_thing_manager_get_thing_property_value, - dm_thing_manager_set_thing_event_output_value, - dm_thing_manager_get_thing_event_output_value, - dm_thing_manager_get_thing_service_input_value, - dm_thing_manager_get_thing_service_output_value, - dm_thing_manager_set_thing_service_output_value, - dm_thing_manager_trigger_event, -#ifdef DEVICEINFO_ENABLED - dm_thing_manager_trigger_deviceinfo_update, - dm_thing_manager_trigger_deviceinfo_delete, -#endif /* DEVICEINFO_ENABLED*/ - dm_thing_manager_answer_service, - dm_thing_manager_invoke_raw_service, - dm_thing_manager_answer_raw_service, -#ifndef CMP_SUPPORT_MULTI_THREAD - dm_thing_manager_yield, -#endif - dm_thing_manager_install_product_key_device_name, - -}; - -const void* get_dm_thing_manager_class() -{ - return &_dm_thing_manager_class; -} diff --git a/iotkit-embedded/src/dm/src/logger.c b/iotkit-embedded/src/dm/src/logger.c deleted file mode 100644 index 3dc3e9e..0000000 --- a/iotkit-embedded/src/dm/src/logger.c +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include -#include -#include "class_interface.h" -#include "interface/log_abstract.h" -#include "logger.h" -#include "dm_import.h" - -#include "lite-log.h" -#include "iot_export.h" - -void* _g_default_logger = NULL; - -static const char string_log_class_name[] __DM_READ_ONLY__ = "log_cls"; -static const char string_log_level_invalid_pattern[] __DM_READ_ONLY__ = "invalid input level: %d out of [%d, %d]"; - -static void logger_close(const void* _self); -static void logger_open(void* _self, void* _log_name); - -static void* logger_ctor(void* _self, va_list* params) -{ - logger_t* self = _self; - int buffer_size = 0; - - self->_log_name = va_arg(*params, void*); - buffer_size = va_arg(*params, int); - - if (self->_log_name) logger_open(self, self->_log_name); - - self->_log_level = log_level_debug; /* debug level as default. */ - - if (buffer_size) { - self->_log_buffer = dm_lite_calloc(1, buffer_size); - } else { - self->_log_buffer = NULL; - } - /* first created logger consider as the default logger. */ - if (_g_default_logger == NULL) _g_default_logger = self; - - return self; -} - -static void* logger_dtor(void* _self) -{ - logger_t* self = _self; - - self->_log_level = log_level_debug; - self->_log_name = NULL; - - if (self->_log_buffer) dm_lite_free(self->_log_buffer); - self->_log_buffer = NULL; - - IOT_DumpMemoryStats(IOT_LOG_DEBUG); - - logger_close(self); - _g_default_logger = NULL; - - return self; -} - -static void logger_open(void* _self, void* _log_name) -{ - logger_t* self = _self; - - self->_log_name = _log_name; - - LITE_openlog(_log_name); -} - -static void logger_close(const void* _self) -{ - const logger_t* self = _self; - - self = self; - - LITE_closelog(); - - return; -} - -static void logger_set_log_level(void* _self, log_level_t _log_level) -{ - logger_t* self = _self; - - self->_log_level = _log_level; - - if (self->_log_level > log_level_debug) { - printf(string_log_level_invalid_pattern, - _log_level, - log_level_emerg, - log_level_debug); - return; - } - - LITE_set_loglevel(self->_log_level); -} - -static log_level_t logger_get_log_level(const void* _self) -{ - const logger_t* self = _self; - - return self->_log_level; -} - -static void* logger_get_log_name(const void* _self) -{ - const logger_t* self = _self; - - return self->_log_name; -} -#ifdef DM_LOG_ENABLE -static char* _log_level_names[] = { - "emg", "crt", "err", "wrn", "inf", "dbg", -}; -#endif -static void logger_print_log(const void* _self, const char* _func, const int _line, - const int _log_level, const char* fmt, va_list* params) -{ - const logger_t* self = _self; - if (self->_log_level < _log_level) return; - -#ifdef DM_LOG_ENABLE - /* temp implementation of log system. */ - fprintf(stdout, "[%s] %s(%d) ", _log_level_names[_log_level], _func, _line); - vsprintf(self->_log_buffer, fmt, *params); - fprintf(stdout, "%s", self->_log_buffer); -#else - /* use LITE-log functions. */ - LITE_syslog_routine(_func, _line, _log_level, fmt, params); -#endif - return; -} - -static void logger_log(const void* _self, const char* _func, const int _line, - log_level_t _log_level, const char* fmt, ...) -{ - const logger_t* self = _self; - va_list params; - - va_start(params, fmt); - - logger_print_log(self, _func, _line, _log_level, fmt, ¶ms); - - va_end(params); - return; -} - -static const log_t _logger_class = { - sizeof(logger_t), - string_log_class_name, - logger_ctor, - logger_dtor, - logger_open, - logger_close, - logger_set_log_level, - logger_get_log_level, - logger_get_log_name, - logger_print_log, - logger_log, -}; - -const void* get_logger_class() -{ - return &_logger_class; -} diff --git a/iotkit-embedded/src/dm/src/single_list.c b/iotkit-embedded/src/dm/src/single_list.c deleted file mode 100644 index 7d66483..0000000 --- a/iotkit-embedded/src/dm/src/single_list.c +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include "interface/list_abstract.h" -#include "single_list.h" -#include "logger.h" - -#include "dm_import.h" - -static const char string_single_list_class_name[] __DM_READ_ONLY__ = "slist_cls"; -static const char string_single_list_log_pattern[] __DM_READ_ONLY__ = "slist(%s) %s node,size:%d\n"; -static const char string_single_list_clear_pattern[] __DM_READ_ONLY__ = "slist(%s) cleared\n"; -static const char string_single_list_insert[] __DM_READ_ONLY__ = "insert"; -static const char string_single_list_remove[] __DM_READ_ONLY__ = "remove"; - -static void single_list_insert(void* _self, void* data); -static void single_list_clear(void* _self); - -static void* single_list_ctor(void* _self, va_list* params) -{ - single_list_t* self = _self; - - self->_head = (node_t*)dm_lite_calloc(1, sizeof(node_t)); - - if (self->_head == NULL) return NULL; - - self->_head->next = NULL; - self->_head->data = NULL; - self->_size = 0; - - self->_name = va_arg(*params, char*); - - if (self->_name == NULL) goto err_handler; - - return self; - -err_handler: - if (self->_head) dm_lite_free(self->_head); - if (self->_name) dm_lite_free(self->_name); - - return NULL; -} - -static void* single_list_dtor(void* _self) -{ - single_list_t* self = _self; - node_t** p = &self->_head; - - self->_size = 0; - - while ((*p) != NULL) { - node_t* node = *p; - *p = node->next; - dm_lite_free(node); - } - - return self; -} - -static void single_list_insert(void* _self, void* data) -{ - single_list_t* self = _self; - node_t* node = (node_t*)dm_lite_calloc(1, sizeof(node_t)); - - node_t** p = (node_t**)&self->_head; - for (; (*p) != NULL; p = &(*p)->next) - ; - - node->data = data; - node->next = *p; - *p = node; - self->_size++; - - printf(string_single_list_log_pattern, self->_name, string_single_list_insert, self->_size); -} - -static void single_list_remove(void* _self, void* data) -{ - single_list_t* self = _self; - node_t** p = (node_t**)&self->_head; - - while ((*p) != NULL) { - node_t* node = *p; - if (node->data == data) { - *p = node->next; - self->_size--; - printf(string_single_list_log_pattern, self->_name, string_single_list_remove, self->_size); - dm_lite_free(node); - } else { - p = &(*p)->next; - } - } -} - -static void single_list_clear(void* _self) -{ - single_list_t* self = _self; - node_t** p = (node_t**)&self->_head->next; - - while ((*p) != NULL) { - node_t* node = *p; - *p = node->next; - dm_lite_free(node); - } - self->_head->next = NULL; - self->_size = 0; - printf(string_single_list_clear_pattern, self->_name); -} - -static int single_list_empty(const void* _self) -{ - const single_list_t* self = _self; - - return self->_head == NULL; -} - -static int single_list_get_size(const void* _self) -{ - const single_list_t* self = _self; - - return self->_size; -} - -static void single_list_iterator(const void* _self, handle_fp_t handle_fn, va_list* params) -{ - const single_list_t* self = _self; - node_t** p = &self->_head->next; - - for (; (*p) != NULL; p = &(*p)->next) { - va_list args; - va_copy(args, *params); - handle_fn((*p)->data, &args); - va_end(args); - } -} - -void list_iterator(const void* _list, handle_fp_t handle_fn, ...) -{ - const list_t** list = (const list_t**)_list; - va_list params; - va_start(params, handle_fn); - - (*list)->iterator(list, handle_fn, ¶ms); - va_end(params); -} - -static void single_list_print(const void* _self, print_fp_t print_fn) -{ - const single_list_t* self = _self; - node_t** p = &self->_head->next; - - while ((*p) != NULL) { - print_fn((*p)->data); - p = &(*p)->next; - } -} - -static const list_t _single_list_class = { - sizeof(single_list_t), - string_single_list_class_name, - single_list_ctor, - single_list_dtor, - single_list_insert, - single_list_remove, - single_list_clear, - single_list_empty, - single_list_get_size, - single_list_iterator, - single_list_print, -}; - -const void* get_single_list_class() -{ - return &_single_list_class; -} diff --git a/iotkit-embedded/src/dynamic_register/dynreg.c b/iotkit-embedded/src/dynamic_register/dynreg.c new file mode 100644 index 0000000..29f6af7 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dynamic_register/dynreg_api.h b/iotkit-embedded/src/dynamic_register/dynreg_api.h new file mode 100644 index 0000000..d1fcf8f --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dynamic_register/dynreg_internal.h b/iotkit-embedded/src/dynamic_register/dynreg_internal.h new file mode 100644 index 0000000..79d7330 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dynamic_register/dynreg_wrapper.h b/iotkit-embedded/src/dynamic_register/dynreg_wrapper.h new file mode 100644 index 0000000..b7e52f5 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/dynamic_register/examples/dynreg_example.c b/iotkit-embedded/src/dynamic_register/examples/dynreg_example.c new file mode 100644 index 0000000..f42c219 --- /dev/null +++ b/iotkit-embedded/src/dynamic_register/examples/dynreg_example.c @@ -0,0 +1,34 @@ +#include +#include +#include "infra_types.h" +#include "infra_defs.h" +#include "dynreg_api.h" + +void HAL_Printf(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 main(int argc, char *argv[]) +{ + int32_t res = 0; + iotx_dev_meta_info_t meta; + iotx_http_region_types_t region = IOTX_HTTP_REGION_SHANGHAI; + HAL_Printf("dynreg example\n"); + + memset(&meta,0,sizeof(iotx_dev_meta_info_t)); + HAL_GetProductKey(meta.product_key); + HAL_GetProductSecret(meta.product_secret); + HAL_GetDeviceName(meta.device_name); + + res = IOT_Dynamic_Register(region, &meta); + if (res < 0) { + HAL_Printf("IOT_Dynamic_Register failed\n"); + return -1; + } + + HAL_Printf("\nDevice Secret: %s\n\n",meta.device_secret); + + return 0; +} + diff --git a/iotkit-embedded/src/dynamic_register/iot.mk b/iotkit-embedded/src/dynamic_register/iot.mk new file mode 100644 index 0000000..4674ef3 --- /dev/null +++ b/iotkit-embedded/src/dynamic_register/iot.mk @@ -0,0 +1,11 @@ +LIBA_TARGET := libiot_dynreg.a + +HDR_REFS := src/infra + +DEPENDS += wrappers +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +TARGET := dynreg-example + +LIB_SRCS_EXCLUDE := examples/dynreg_example.c +SRCS_dynreg-example += examples/dynreg_example.c diff --git a/iotkit-embedded/src/fota/CMakeLists.txt b/iotkit-embedded/src/fota/CMakeLists.txt deleted file mode 100644 index 3c6a181..0000000 --- a/iotkit-embedded/src/fota/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -file(GLOB C_SOURCES "service_ota.c") -add_library(fota STATIC ${C_SOURCES}) - -target_link_libraries(fota iot_sdk) - diff --git a/iotkit-embedded/src/fota/iot.mk b/iotkit-embedded/src/fota/iot.mk deleted file mode 100644 index 9cf33da..0000000 --- a/iotkit-embedded/src/fota/iot.mk +++ /dev/null @@ -1,2 +0,0 @@ -LIBA_TARGET := libiot_fota.a -HDR_REFS := src \ No newline at end of file diff --git a/iotkit-embedded/src/fota/service_ota.c b/iotkit-embedded/src/fota/service_ota.c deleted file mode 100644 index e0d45b7..0000000 --- a/iotkit-embedded/src/fota/service_ota.c +++ /dev/null @@ -1,266 +0,0 @@ -#include -#include -#include -#include - -#include "iot_import.h" -#include "class_interface.h" -#include "iot_export_dm.h" -#include "iot_export_fota.h" -#include "iot_export_cmp.h" -#include "iot_export_errno.h" -#include "lite-utils.h" - - -static void service_ota_handler(void* pcontext, iotx_cmp_fota_parameter_t* ota_parameter, void* user_data) -{ - iotx_cmp_fota_parameter_t* iotx_cmp_ota_parameter = ota_parameter; - service_ota_t* service_ota = user_data; - - log_info("\n\n%s\n\n", iotx_cmp_ota_parameter->purl); - - if (service_ota->_ota_version) service_ota_lite_free(service_ota->_ota_version); - - service_ota->_ota_version = service_ota_lite_calloc(1, strlen(iotx_cmp_ota_parameter->version) + 1); - if (service_ota->_ota_version == NULL) { - log_err("ota version malloc fail."); - return; - } - strcpy(service_ota->_ota_version, iotx_cmp_ota_parameter->version); - log_debug("new OTA version %s", service_ota->_ota_version); - - /* invoke callback funtions. */ - if (service_ota->_linkkit_callback_fp) { - ((handle_service_fota_callback_fp_t)service_ota->_linkkit_callback_fp)(service_fota_callback_type_new_version_detected, service_ota->_ota_version); - } -} - -static void service_ota_cmp_event_handler(void* pcontext, iotx_cmp_event_msg_t* msg, void* user_data) -{ - service_ota_t* service_ota = user_data; - int ret; - - log_info("\n###\n"); - - if (IOTX_CMP_EVENT_CLOUD_CONNECTED == msg->event_id) { - if (service_ota->_ota_inited == 0) { - if (service_ota->_destructing == 1) return; - - HAL_GetFirmwareVesion(service_ota->_current_verison); - - log_info("Current firmware version: %s", service_ota->_current_verison); - - ret = IOT_CMP_OTA_Start(service_ota->_current_verison, NULL); - if (ret == SUCCESS_RETURN) { - service_ota->_ota_inited = 1; - } - - ret = IOT_CMP_OTA_Set_Callback(IOTX_CMP_OTA_TYPE_FOTA, service_ota_handler, service_ota, NULL); - - log_debug("ret = IOT_CMP_OTA_Set_Callback() = %d\n", ret); - } - - log_info("event %d(%s)\n###\n", msg->event_id, "cloud connected"); - } -} - -static void* service_ota_ctor(void* _self, va_list* params) -{ - service_ota_t* self = _self; - int ret = 0; - iotx_cmp_init_param_t init_param; - - self->_data_buf = NULL; - self->_data_buf_length = 0; - self->_ota_inited = 0; - self->_current_verison = service_ota_lite_malloc(FIRMWARE_VERSION_MAXLEN); - if (self->_current_verison == NULL) return NULL; - memset(self->_current_verison, 0x0, FIRMWARE_VERSION_MAXLEN); - - init_param.event_func = service_ota_cmp_event_handler; - init_param.user_data = self; - init_param.domain_type = IOTX_CMP_CLOUD_DOMAIN_SH; - init_param.secret_type = IOTX_CMP_DEVICE_SECRET_DEVICE; - - ret = IOT_CMP_Init(&init_param, NULL); - - log_debug("ret = IOT_CMP_Init() = %d\n", ret); - - log_debug("service fota created@%p.", self); - - return self; -} - -static void* service_ota_dtor(void* _self) -{ - service_ota_t* self = _self; - - self->_destructing = 1; - self->_data_buf = NULL; - self->_data_buf_length = 0; - if (self->_ota_version) service_ota_lite_free(self->_ota_version); - if (self->_current_verison) service_ota_lite_free(self->_current_verison); - - return self; -} - -static void service_ota_start(void* _self) -{ - service_ota_t* self = _self; - - self = self; - - HAL_Firmware_Persistence_Start(); -} - -static int service_ota_write(void* _self, void* data, int data_length) -{ - service_ota_t* self = _self; - int ret; - - assert(self->_data_buf_length >= data_length && data_length && self->_data_buf == data); - - self->_data_buf = data; - - ret = HAL_Firmware_Persistence_Write(self->_data_buf, data_length); - - return ret; -} - -static int service_ota_end(void* _self) -{ - service_ota_t* self = _self; - int ret; - - self = self; - - /* this function should not return... */ - ret = HAL_Firmware_Persistence_Stop(); - -#if defined(_PLATFORM_IS_LINUX_) || defined(_PLATFORM_IS_WINDOWS_) - exit(0); -#else - log_emerg("OTA end, restarting..."); - HAL_Sys_reboot(); -#endif - return ret; -} - -static int service_ota_perform_ota_service(void* _self, void* _data_buf, int _data_buf_length) -{ - service_ota_t* self = _self; - int ret = -1; - iotx_cmp_ota_t* iotx_cmp_ota; - - assert(_data_buf && _data_buf_length); - - self->_data_buf = _data_buf; - self->_data_buf_length = _data_buf_length; - - iotx_cmp_ota = service_ota_lite_calloc(1, sizeof(iotx_cmp_ota_t)); - - assert(iotx_cmp_ota); - if (iotx_cmp_ota == NULL) return -1; - - iotx_cmp_ota->buffer = self->_data_buf; - iotx_cmp_ota->buffer_length = self->_data_buf_length; - iotx_cmp_ota->ota_type = IOTX_CMP_OTA_TYPE_FOTA; - - self->_total_len = 0; - - service_ota_start(self); - - while (1) { - /* reset buffer size every time after fetch */ - iotx_cmp_ota->buffer_length = self->_data_buf_length; - ret = IOT_CMP_OTA_Yield(iotx_cmp_ota); - - assert(iotx_cmp_ota->buffer && iotx_cmp_ota->buffer_length); - - if (ret == 0 && iotx_cmp_ota->buffer && iotx_cmp_ota->buffer_length) { - ret = service_ota_write(self, iotx_cmp_ota->buffer, iotx_cmp_ota->buffer_length); - if (ret == 0) { - self->_total_len += iotx_cmp_ota->buffer_length; - } - log_debug("\nservice fota write flash,\tret=%d,\tbuffer_length=%d,\ttotal len:%d\n", - ret, iotx_cmp_ota->buffer_length, self->_total_len); - if (ret) goto err_handler; - } - - if (ret || iotx_cmp_ota->result) { - log_debug("service fota fail, ret=%d,\tresult=%d", ret, iotx_cmp_ota->result); - goto err_handler; - } - - if (iotx_cmp_ota->is_more) continue; - - if(iotx_cmp_ota->is_more == 0 && iotx_cmp_ota->result == 0) { - ret = 0; - log_debug("\nservice fota complete\n"); - break; - } - } - -err_handler: - if (ret == 0 && iotx_cmp_ota->result == 0) { - ret = service_ota_end(self); - if (ret) { - log_err("service fota invoke end function error, ret=%d", ret); - } - } else { - ret = -1; - } - - if (iotx_cmp_ota) service_ota_lite_free(iotx_cmp_ota); - - return ret; -} - -static void service_ota_install_callback_function(void* _self, handle_service_fota_callback_fp_t linkkit_callback_fp) -{ - service_ota_t* self = _self; - - assert(linkkit_callback_fp); - - self->_linkkit_callback_fp = linkkit_callback_fp; -} - -void* service_ota_lite_calloc(size_t nmemb, size_t size) -{ -#ifdef CMP_SUPPORT_MEMORY_MAGIC - return LITE_calloc(nmemb, size, MEM_MAGIC, SERVICE_FOTA_MODULE_NAME); -#else - return LITE_calloc(nmemb, size); -#endif -} - -void* service_ota_lite_malloc(size_t size) -{ -#ifdef CMP_SUPPORT_MEMORY_MAGIC - return LITE_malloc(size, MEM_MAGIC, SERVICE_FOTA_MODULE_NAME); -#else - return LITE_malloc(size); -#endif -} - -void service_ota_lite_free_func(void* ptr) -{ - return LITE_free_internal(ptr); -} - -static const fota_t _service_ota_class = { - sizeof(service_ota_t), - "fota_cls", - service_ota_ctor, - service_ota_dtor, - service_ota_start, - service_ota_write, - service_ota_end, - service_ota_perform_ota_service, - service_ota_install_callback_function, -}; - -const void* get_service_ota_class() -{ - return &_service_ota_class; -} diff --git a/iotkit-embedded/src/http/CMakeLists.txt b/iotkit-embedded/src/http/CMakeLists.txt deleted file mode 100644 index 414234c..0000000 --- a/iotkit-embedded/src/http/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(iot_http OBJECT ${C_SOURCES}) diff --git a/iotkit-embedded/src/http/README.md b/iotkit-embedded/src/http/README.md new file mode 100644 index 0000000..e1a6de0 --- /dev/null +++ b/iotkit-embedded/src/http/README.md @@ -0,0 +1,33 @@ +# README.md: http + +## Contents + +```shell +├── aos.mk +├── CMakeLists.txt +├── Config.in +├── http_debug.h +├── iot.mk +├── iotx_http_api.c +└── README.md +``` + +## Introduction +A communication channel implemented in HTTP + + +### Features + + + +### Dependencies + +- **hal**. osal and hal to shield different os and hardware +- **infra**. Authentication, net and so on tool set. + +## API +Please refer to [http api](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Prog_Guide/API/HTTP_Provides#IOT_HTTP_Init) for API details. +## Reference +Please refer to [http connect](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Prog_Guide/HTTP_Connect) for example details. + + diff --git a/iotkit-embedded/src/http/examples/http_example.c b/iotkit-embedded/src/http/examples/http_example.c new file mode 100644 index 0000000..6b40a55 --- /dev/null +++ b/iotkit-embedded/src/http/examples/http_example.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include "infra_types.h" +#include "infra_defs.h" +#include "infra_httpc.h" +#include "http_api.h" +#include "http_wrapper.h" + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while (0) + +#define MAX_BUF_LEN 256 +#define DEFAULT_TIMEOUT_MS 5000 + +/* on line */ +#define IOTX_PRODUCT_KEY "a1KqSriAwh0" +#define IOTX_DEVICE_NAME "basic_test_01" +#define IOTX_DEVICE_SECRET "5gme06iFl3W1g8non2ksVs5e8Qlus4Hw" +#define IOTX_DEVICE_ID "a1KqSriAwh0.basic_test_01" + +static char request_buf[MAX_BUF_LEN]; +static char response_buf[MAX_BUF_LEN]; + +void looptest(void *handle) +{ + iotx_http_message_param_t msg; + char path[IOTX_URI_MAX_LEN + 1] = { 0 }; + int loop_cnt = 3; + int success_cnt = 0; + int cnt = 0; + + if (NULL == handle) { + return; + } + + HAL_Snprintf(request_buf, MAX_BUF_LEN, "{\"name\":\"hello world\"}"); + memset(response_buf, 0x00, MAX_BUF_LEN); + HAL_Snprintf(path, IOTX_URI_MAX_LEN, "/topic/%s/%s/user/update", + IOTX_PRODUCT_KEY, + IOTX_DEVICE_NAME); + msg.request_payload = request_buf; + msg.response_payload = response_buf; + msg.timeout_ms = 5000; + msg.request_payload_len = strlen(msg.request_payload) + 1; + msg.response_payload_len = MAX_BUF_LEN; + msg.topic_path = path; + + while (cnt++ < loop_cnt) { + if (0 == IOT_HTTP_SendMessage(handle, &msg)) { + success_cnt++; + } + } + EXAMPLE_TRACE("loop cnt is %d, success_cnt is %d\n", loop_cnt, success_cnt); +} + + +static int http_upload_test() +{ + iotx_device_info_t device_info; + iotx_http_param_t http_param; + void *handle = NULL; + memset(&http_param, 0, sizeof(http_param)); + + HAL_SetProductKey((char *)IOTX_PRODUCT_KEY); + HAL_SetDeviceName((char *)IOTX_DEVICE_NAME); + HAL_SetDeviceSecret((char *)IOTX_DEVICE_SECRET); + + strncpy(device_info.product_key, IOTX_PRODUCT_KEY, IOTX_PRODUCT_KEY_LEN); + strncpy(device_info.device_secret, IOTX_DEVICE_SECRET, IOTX_DEVICE_SECRET_LEN); + strncpy(device_info.device_name, IOTX_DEVICE_NAME, IOTX_DEVICE_NAME_LEN); + strncpy(device_info.device_id, IOTX_DEVICE_ID, IOTX_DEVICE_ID_LEN); + + http_param.device_info = &device_info; + http_param.timeout_ms = DEFAULT_TIMEOUT_MS; + + handle = IOT_HTTP_Init(&http_param); + if (NULL != handle) { + IOT_HTTP_DeviceNameAuth(handle); + HAL_Printf("IoTx HTTP Message Sent\r\n"); + } else { + HAL_Printf("IoTx HTTP init failed\r\n"); + return 0; + } + looptest(handle); + + IOT_HTTP_Disconnect(handle); + IOT_HTTP_DeInit(&handle); + return 0; +} + +int main(int argc, char **argv) +{ +#if (defined(ON_DAILY)) || (defined(ON_PRE)) + EXAMPLE_TRACE("the device name/device secrete/product name is only valid for ONLINE, EXIT!"); + return 0; +#endif + int ret; + ret = http_upload_test(); + return ret; +} diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_http.h b/iotkit-embedded/src/http/http_api.h similarity index 80% rename from iotkit-embedded/src/sdk-impl/exports/iot_export_http.h rename to iotkit-embedded/src/http/http_api.h index 2f11e30..ab02885 100644 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_http.h +++ b/iotkit-embedded/src/http/http_api.h @@ -1,24 +1,26 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * 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; @@ -131,13 +133,10 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) */ void IOT_HTTP_Disconnect(void *handle); -/* -TEST MACROS - Daily Test Environment: -DTEST_HTTP_DAILY - Pre-Online Test Environment: -DTEST_HTTP_PRE -*/ - /** @} */ /* end of api_http */ /** @} */ /* end of api */ +#if defined(__cplusplus) +} +#endif #endif diff --git a/iotkit-embedded/src/http/http_debug.h b/iotkit-embedded/src/http/http_debug.h new file mode 100644 index 0000000..9824000 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/http/http_wrapper.h b/iotkit-embedded/src/http/http_wrapper.h new file mode 100644 index 0000000..2e712ee --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/http/iot.mk b/iotkit-embedded/src/http/iot.mk index 00e5b64..c63a16c 100644 --- a/iotkit-embedded/src/http/iot.mk +++ b/iotkit-embedded/src/http/iot.mk @@ -1,2 +1,11 @@ -LIBA_TARGET := libiot_http.a -HDR_REFS := src +LIBA_TARGET := libiot_http.a + +HDR_REFS += src/infra + +DEPENDS += wrappers +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +TARGET := http-example + +LIB_SRCS_EXCLUDE := examples/http_example.c +SRCS_http-example += examples/http_example.c \ No newline at end of file diff --git a/iotkit-embedded/src/http/iotx_http_api.c b/iotkit-embedded/src/http/iotx_http_api.c index 97b58cc..2d2489c 100644 --- a/iotkit-embedded/src/http/iotx_http_api.c +++ b/iotkit-embedded/src/http/iotx_http_api.c @@ -1,32 +1,41 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#include #include +#include +#include -#include "iot_import.h" -#include "iot_export.h" +#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" -#include "lite-utils.h" -#include "utils_hmac.h" -#include "utils_httpc.h" -#include "utils_epoch_time.h" -#include "sdk-impl_internal.h" -#include "lite-system.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 @@ -55,25 +64,11 @@ "}" #endif -#define IOTX_HTTP_AUTH_STR "auth" - -#if defined(TEST_HTTP_DAILY) - #define IOTX_HTTP_ONLINE_SERVER_URL "http://10.101.83.159" - #define IOTX_HTTP_ONLINE_SERVER_PORT 80 - #define IOTX_HTTP_CA_GET NULL -#else - #define IOTX_HTTP_ONLINE_SERVER_URL "https://iot-as-http.cn-shanghai.aliyuncs.com" - #define IOTX_HTTP_ONLINE_SERVER_PORT 443 - #define IOTX_HTTP_CA_GET iotx_ca_get() -#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_MD5_METHOD "hmacmd5" - -/* By default we use hmac-md5 algorithm for hmac in PK/DN/DS case */ -#ifndef USING_SHA1_IN_HMAC -#define USING_SHA1_IN_HMAC (1) -#endif /* USING_SHA1_IN_HMAC */ +#define IOTX_SHA_METHOD "hmacsha1" #define IOTX_HTTP_HEADER_KEEPALIVE_STR "Connection: Keep-Alive\r\n" #define IOTX_HTTP_HEADER_PASSWORD_STR "password:" @@ -105,14 +100,9 @@ static iotx_http_t *iotx_http_context_bak = NULL; static int iotx_calc_sign(const char *p_device_secret, const char *p_msg, char *sign) { -#if USING_SHA1_IN_HMAC - log_info("| method: %s", IOTX_SHA_METHOD); + http_info("| method: %s", IOTX_SHA_METHOD); utils_hmac_sha1(p_msg, strlen(p_msg), sign, p_device_secret, strlen(p_device_secret)); -#else - log_info("| method: %s", IOTX_MD5_METHOD); - utils_hmac_md5(p_msg, strlen(p_msg), sign, p_device_secret, strlen(p_device_secret)); -#endif - return IOTX_SUCCESS; + return SUCCESS_RETURN; } static int calc_snprintf_string_length(char *fmt, ...) @@ -154,7 +144,7 @@ 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); - log_info("get_http_authenticate_url is %s", buf); + http_info("get_http_authenticate_url is %s", buf); return 0; } @@ -162,86 +152,32 @@ 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); - log_info("construct_full_http_upstream_url is %s", buf); + http_info("construct_full_http_upstream_url is %s", buf); return 0; } -/* report ModuleID */ -static int iotx_http_report_mid(iotx_http_t *handle) +static int http_report_func(void *handle, const char *topic_name, int req_ack, void *data, int len) { - int ret; - char topic_name[IOTX_URI_MAX_LEN + 1]; - char request_buf[1024]; iotx_http_message_param_t msg_param; - char requestId[MIDREPORT_REQID_LEN + 1] = {0}; - char pid[PID_STRLEN_MAX + 1] = {0}; - char mid[MID_STRLEN_MAX + 1] = {0}; - iotx_http_t *iotx_http_context = handle; - - if (0 == HAL_GetPartnerID(pid)) { - log_debug("PartnerID is Null."); - return SUCCESS_RETURN; - } - if (0 == HAL_GetModuleID(mid)) { - log_debug("ModuleID is Null."); - return SUCCESS_RETURN; - } - - log_debug("MID Report: started in HTTP"); + char request_buf[1024]; + char topic_path[100]; - iotx_midreport_reqid(requestId, - (char *)iotx_http_context->p_devinfo->product_key, - (char *)iotx_http_context->p_devinfo->device_name); - /* 1,generate json data */ - char *msg = HAL_Malloc(MIDREPORT_PAYLOAD_LEN); - if (NULL == msg) { - log_err("allocate mem failed"); - return FAIL_RETURN; + if (handle == NULL || topic_name == NULL || data == NULL) { + http_err("params err"); + return -1; } - iotx_midreport_payload(msg, - requestId, - mid, - pid); - log_debug("MID Report: json data = '%s'", msg); + 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 *)msg; + 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 = strlen(msg) + 1; + msg_param.request_payload_len = len; msg_param.response_payload_len = 1024; - msg_param.topic_path = topic_name; - - /* 2,generate topic name */ - ret = iotx_midreport_topic(topic_name, - "/topic", - (char *)iotx_http_context->p_devinfo->product_key, - (char *)iotx_http_context->p_devinfo->device_name); - - log_debug("MID Report: topic name = '%s'", topic_name); - - if (ret < 0) { - log_err("generate topic name of info failed"); - HAL_Free(msg); - return FAIL_RETURN; - } - /*3,send topic */ - ret = IOT_HTTP_SendMessage(iotx_http_context, &msg_param); - if (0 == ret) { - log_info("message response is '%s'", msg_param.response_payload); - } else { - log_err("ret = IOT_HTTP_SendMessage() = %d != 0", ret); - HAL_Free(msg); - return FAIL_RETURN; - } - - HAL_Free(msg); - - log_debug("MID Report: finished, IOT_HTTP_SendMessage() = %d", ret); - return SUCCESS_RETURN; + msg_param.topic_path = topic_path; + return IOT_HTTP_SendMessage(handle, &msg_param); } static void *verify_iotx_http_context(void *handle) @@ -251,7 +187,7 @@ static void *verify_iotx_http_context(void *handle) if (NULL == iotx_http_context || NULL == iotx_http_context_bak || iotx_http_context_bak != iotx_http_context) { - log_err("iotx_http_context not valid pointer!"); + http_err("iotx_http_context not valid pointer!"); iotx_http_context = NULL; } @@ -266,21 +202,27 @@ void *IOT_HTTP_Init(iotx_http_param_t *pInitParams) /* currently http is singleton, init twice not allowed. */ if (NULL != iotx_http_context_bak) { - log_err("Init twice not allowed, please deinit first"); + http_err("Init twice not allowed, please deinit first"); return NULL; } if (NULL == pInitParams || NULL == pInitParams->device_info) { - log_err("Invalid argument: pInitParams or device_info = NULL"); + http_err("Invalid argument: pInitParams or device_info = NULL"); return NULL; } p_devinfo = pInitParams->device_info; - iotx_http_context = (iotx_http_t *)LITE_malloc(sizeof(iotx_http_t)); +/* + 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) { - log_err("Allocate memory for iotx_http_context failed"); + http_err("Allocate memory for iotx_http_context failed"); return NULL; } @@ -288,9 +230,9 @@ void *IOT_HTTP_Init(iotx_http_param_t *pInitParams) iotx_http_context->keep_alive = pInitParams->keep_alive; iotx_http_context->timeout_ms = pInitParams->timeout_ms; - iotx_http_context->p_auth_token = LITE_malloc(IOTX_HTTP_AUTH_TOKEN_LEN); + iotx_http_context->p_auth_token = HTTP_API_MALLOC(IOTX_HTTP_AUTH_TOKEN_LEN); if (NULL == iotx_http_context->p_auth_token) { - log_err("Allocate memory for auth token failed"); + http_err("Allocate memory for auth token failed"); goto err; } memset(iotx_http_context->p_auth_token, 0x00, IOTX_HTTP_AUTH_TOKEN_LEN); @@ -298,27 +240,23 @@ void *IOT_HTTP_Init(iotx_http_param_t *pInitParams) iotx_http_context->auth_token_len = IOTX_HTTP_AUTH_TOKEN_LEN; /*Get deivce information*/ - iotx_http_context->p_devinfo = (iotx_device_info_t *)LITE_malloc(sizeof(iotx_device_info_t)); + iotx_http_context->p_devinfo = (iotx_device_info_t *)HTTP_API_MALLOC(sizeof(iotx_device_info_t)); if (NULL == iotx_http_context->p_devinfo) { - log_err("Allocate memory for iotx_http_context->p_devinfo failed"); + 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, IOTX_DEVICE_ID_LEN); - strncpy(iotx_http_context->p_devinfo->product_key, p_devinfo->product_key, IOTX_PRODUCT_KEY_LEN); - strncpy(iotx_http_context->p_devinfo->device_secret, p_devinfo->device_secret, IOTX_DEVICE_SECRET_LEN); - strncpy(iotx_http_context->p_devinfo->device_name, p_devinfo->device_name, IOTX_DEVICE_NAME_LEN); + 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_device_info_init(); - iotx_device_info_set(iotx_http_context->p_devinfo->product_key, iotx_http_context->p_devinfo->device_name, - iotx_http_context->p_devinfo->device_secret); - - iotx_http_context->httpc = LITE_malloc(sizeof(httpclient_t)); + iotx_http_context->httpc = HTTP_API_MALLOC(sizeof(httpclient_t)); if (NULL == iotx_http_context->httpc) { - log_err("Allocate memory for iotx_http_context->httpc failed"); + http_err("Allocate memory for iotx_http_context->httpc failed"); goto err; } memset(iotx_http_context->httpc, 0x00, sizeof(httpclient_t)); @@ -330,14 +268,14 @@ void *IOT_HTTP_Init(iotx_http_param_t *pInitParams) /* Error, release the memory */ if (NULL != iotx_http_context) { if (NULL != iotx_http_context->p_devinfo) { - LITE_free(iotx_http_context->p_devinfo); + HTTP_API_FREE(iotx_http_context->p_devinfo); } if (NULL != iotx_http_context->p_auth_token) { - LITE_free(iotx_http_context->p_auth_token); + HTTP_API_FREE(iotx_http_context->p_auth_token); } iotx_http_context->auth_token_len = 0; - LITE_free(iotx_http_context); + HTTP_API_FREE(iotx_http_context); } return NULL; } @@ -346,7 +284,7 @@ void IOT_HTTP_DeInit(void **handle) { iotx_http_t *iotx_http_context; if (NULL == handle) { - log_err("handle is NULL pointer"); + http_err("handle is NULL pointer"); return; } if (NULL == (iotx_http_context = verify_iotx_http_context(*handle))) { @@ -354,17 +292,17 @@ void IOT_HTTP_DeInit(void **handle) } if (NULL != iotx_http_context->p_devinfo) { - LITE_free(iotx_http_context->p_devinfo); + HTTP_API_FREE(iotx_http_context->p_devinfo); } if (NULL != iotx_http_context->p_auth_token) { - LITE_free(iotx_http_context->p_auth_token); + HTTP_API_FREE(iotx_http_context->p_auth_token); } if (NULL != iotx_http_context->httpc) { - LITE_free(iotx_http_context->httpc); + HTTP_API_FREE(iotx_http_context->httpc); } iotx_http_context->auth_token_len = 0; - LITE_free(iotx_http_context); + HTTP_API_FREE(iotx_http_context); iotx_http_context_bak = NULL; } @@ -385,18 +323,19 @@ int IOT_HTTP_DeviceNameAuth(void *handle) char p_msg_unsign[IOTX_HTTP_SIGN_SOURCE_LEN] = {0}; iotx_time_t timer; iotx_http_t *iotx_http_context; - /* - // 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 - // } - */ + 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; } @@ -406,7 +345,7 @@ int IOT_HTTP_DeviceNameAuth(void *handle) /* if(!utils_get_epoch_time_from_ntp(timestamp, sizeof(timestamp))) { - log_info("http time response: \r\n\r\n%s", timestamp); + http_info("http time response: \r\n\r\n%s", timestamp); goto do_exit; } */ @@ -428,11 +367,7 @@ int IOT_HTTP_DeviceNameAuth(void *handle) len = calc_snprintf_string_length(IOTX_HTTP_AUTH_DEVICENAME_STR, "default", iotx_http_context->p_devinfo->device_id, -#if USING_SHA1_IN_HMAC IOTX_SHA_METHOD, -#else - IOTX_MD5_METHOD, -#endif sign, iotx_http_context->p_devinfo->product_key, iotx_http_context->p_devinfo->device_name, @@ -443,31 +378,27 @@ int IOT_HTTP_DeviceNameAuth(void *handle) goto do_exit; } - req_payload = (char *)LITE_malloc(len + 1); + req_payload = (char *)HTTP_API_MALLOC(len + 1); memset(req_payload, 0, len + 1); - log_debug("allocate req_payload: len = %d", len); + 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, -#if USING_SHA1_IN_HMAC - IOTX_SHA_METHOD, -#else - IOTX_MD5_METHOD, -#endif - sign, - iotx_http_context->p_devinfo->product_key, - iotx_http_context->p_devinfo->device_name, - timestamp - ); - log_debug("len = %d,req_payload: \r\n%s", len, req_payload); + 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 *)LITE_malloc(HTTP_AUTH_RESP_MAX_LEN); + rsp_payload = (char *)HTTP_API_MALLOC(HTTP_AUTH_RESP_MAX_LEN); if (NULL == rsp_payload) { - log_err("Allocate HTTP rsp_payload buf failed!"); + http_err("Allocate HTTP rsp_payload buf failed!"); goto do_exit; } memset(rsp_payload, 0, HTTP_AUTH_RESP_MAX_LEN); @@ -495,11 +426,16 @@ int IOT_HTTP_DeviceNameAuth(void *handle) 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, - IOTX_HTTP_CA_GET, + pub_key, &httpc_data)) { goto do_exit; } @@ -510,11 +446,12 @@ int IOT_HTTP_DeviceNameAuth(void *handle) ret = httpclient_recv_response(httpc, iotx_time_left(&timer), &httpc_data); if (ret < 0) { - log_err("httpclient_recv_response error, ret = %d", ret); + 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); } /* @@ -527,24 +464,25 @@ int IOT_HTTP_DeviceNameAuth(void *handle) } } */ - log_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf); + http_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf); - pvalue = LITE_json_value_of("code", httpc_data.response_buf); + pvalue = HTTP_LITE_JSON_VALUE_OF("code", httpc_data.response_buf); if (!pvalue) { goto do_exit; } ret_code = atoi(pvalue); - log_info("ret_code = %d", ret_code); - LITE_free(pvalue); + http_info("ret_code = %d", ret_code); + HTTP_API_FREE(pvalue); pvalue = NULL; - pvalue = LITE_json_value_of("message", httpc_data.response_buf); + pvalue = HTTP_LITE_JSON_VALUE_OF("message", httpc_data.response_buf); if (NULL == pvalue) { goto do_exit; } response_message = pvalue; - log_info("response_message: %s", response_message); - LITE_free(pvalue); + http_info("response_message: %s", response_message); + (void)response_message; + HTTP_API_FREE(pvalue); pvalue = NULL; switch (ret_code) { @@ -560,23 +498,35 @@ int IOT_HTTP_DeviceNameAuth(void *handle) goto do_exit; } - pvalue = LITE_json_value_of("info.token", httpc_data.response_buf); + pvalue = HTTP_LITE_JSON_VALUE_OF("info.token", httpc_data.response_buf); if (NULL == pvalue) { - log_err("can't get token from json, Abort!"); + 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; - LITE_free(pvalue); + HTTP_API_FREE(pvalue); pvalue = NULL; - /* log_info("iotToken: %s", iotx_http_context->p_auth_token); */ + iotx_set_report_func(http_report_func); /* report module id */ - ret = iotx_http_report_mid(iotx_http_context); + 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) { - log_err("Send ModuleId message to server(Http) failed ret = %d", ret); + http_err("Send firmware message to server(Http) failed, ret = %d", ret); goto do_exit; } @@ -584,15 +534,15 @@ int IOT_HTTP_DeviceNameAuth(void *handle) do_exit: if (pvalue) { - LITE_free(pvalue); + HTTP_API_FREE(pvalue); pvalue = NULL; } if (req_payload) { - LITE_free(req_payload); + HTTP_API_FREE(req_payload); req_payload = NULL; } if (rsp_payload) { - LITE_free(rsp_payload); + HTTP_API_FREE(rsp_payload); rsp_payload = NULL; } @@ -609,11 +559,11 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) httpclient_data_t httpc_data = {0}; char *messageId = NULL; char *user_data = NULL; - char *response_message = 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 @@ -626,34 +576,34 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) } if (NULL == msg_param) { - log_err("iotx_http_context or msg_param NULL pointer!"); + http_err("iotx_http_context or msg_param NULL pointer!"); goto do_exit; } httpc = (httpclient_t *)iotx_http_context->httpc; if (NULL == httpc) { - log_err("httpc null pointer"); + http_err("httpc null pointer"); goto do_exit; } if (0 == iotx_http_context->is_authed) { - log_err("Device is not authed"); + http_err("Device is not authed"); goto do_exit; } if (NULL == msg_param->request_payload) { - log_err("IOT_HTTP_SendMessage request_payload NULL!"); + http_err("IOT_HTTP_SendMessage request_payload NULL!"); goto do_exit; } if (NULL == msg_param->response_payload) { - log_err("IOT_HTTP_SendMessage response_payload NULL!"); + http_err("IOT_HTTP_SendMessage response_payload NULL!"); goto do_exit; } if (NULL == msg_param->topic_path) { - log_err("IOT_HTTP_SendMessage topic_path NULL!"); + http_err("IOT_HTTP_SendMessage topic_path NULL!"); goto do_exit; } @@ -666,14 +616,14 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) 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 = LITE_malloc(len + 1); + httpc->header = HTTP_API_MALLOC(len + 1); if (NULL == httpc->header) { - log_err("Allocate memory for httpc->header failed"); + 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); - log_info("httpc->header = %s", httpc->header); + http_info("httpc->header = %s", httpc->header); httpc_data.post_content_type = "application/octet-stream"; httpc_data.post_buf = msg_param->request_payload; @@ -681,13 +631,18 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) httpc_data.response_buf = msg_param->response_payload; httpc_data.response_buf_len = msg_param->response_payload_len; - log_info("request_payload: \r\n\r\n%s\r\n", httpc_data.post_buf); + 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, - IOTX_HTTP_CA_GET, + pub_key, &httpc_data)) { goto do_exit_pre; } @@ -696,7 +651,7 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) ret = httpclient_recv_response(httpc, iotx_time_left(&timer), &httpc_data); if (ret < 0) { - log_err("httpclient_recv_response error, ret = %d", ret); + http_err("httpclient_recv_response error, ret = %d", ret); httpclient_close(httpc); goto do_exit_pre; } @@ -716,25 +671,24 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) } } */ - log_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf); + http_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf); - pvalue = LITE_json_value_of("code", 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); - LITE_free(pvalue); + HTTP_API_FREE(pvalue); pvalue = NULL; - log_info("response code: %d", response_code); + http_info("response code: %d", response_code); - pvalue = LITE_json_value_of("message", httpc_data.response_buf); + pvalue = HTTP_LITE_JSON_VALUE_OF("message", httpc_data.response_buf); if (NULL == pvalue) { goto do_exit_pre; } - response_message = LITE_strdup(pvalue); - log_info("response_message: %s", response_message); - LITE_free(pvalue); + http_info("response_message: %s", pvalue); + HTTP_API_FREE(pvalue); pvalue = NULL; switch (response_code) { @@ -756,28 +710,29 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) } /* info.messageId */ - pvalue = LITE_json_value_of("info.messageId", httpc_data.response_buf); + pvalue = HTTP_LITE_JSON_VALUE_OF("info.messageId", httpc_data.response_buf); if (NULL == pvalue) { - log_err("messageId: NULL"); + http_err("messageId: NULL"); goto do_exit_pre; } messageId = pvalue; - log_info("messageId: %s", messageId); - LITE_free(pvalue); + http_info("messageId: %s", messageId); + (void)messageId; + HTTP_API_FREE(pvalue); pvalue = NULL; /* info.data */ - pvalue = LITE_json_value_of("info.data", httpc_data.response_buf); + pvalue = HTTP_LITE_JSON_VALUE_OF("info.data", httpc_data.response_buf); user_data = pvalue; /* Maybe NULL */ if (user_data) { - log_info("user_data: %s", user_data); + http_info("user_data: %s", user_data); } else { - log_info("user_data: %p", user_data); + http_info("user_data: %p", user_data); } if (NULL != pvalue) { - LITE_free(pvalue); + HTTP_API_FREE(pvalue); } pvalue = NULL; @@ -786,16 +741,11 @@ int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) do_exit_pre: if (pvalue) { - LITE_free(pvalue); + HTTP_API_FREE(pvalue); } - if (response_message) { - LITE_free(response_message); - } - - if (httpc != NULL && httpc->header) { - LITE_free(httpc->header); + HTTP_API_FREE(httpc->header); } do_exit: diff --git a/iotkit-embedded/src/http2/examples/http2_example_break_resume.c b/iotkit-embedded/src/http2/examples/http2_example_break_resume.c new file mode 100644 index 0000000..1bfc936 --- /dev/null +++ b/iotkit-embedded/src/http2/examples/http2_example_break_resume.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include +#include "http2_upload_api.h" +#include "http2_wrapper.h" + + +#define HTTP2_ONLINE_SERVER_URL "a1IgnOND7vI.iot-as-http2.cn-shanghai.aliyuncs.com" +#define HTTP2_ONLINE_SERVER_PORT 443 +#define HTTP2_PRODUCT_KEY "a1IgnOND7vI" +#define HTTP2_DEVICE_NAME "H2_FS01" +#define HTTP2_DEVICE_SECRET "r9XSyeZOu6swgV8etCcCGmgQhBSpGBau" + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while (0) + +#define UPLOAD_RETRY_TIME 50 + +static int upload_result = 1; +static char g_upload_id[50] = {0}; +static uint8_t is_connected = 0; + +void upload_file_result(const char *file_path, int result, void *user_data) +{ + upload_result = result; + + EXAMPLE_TRACE("=========== file_path = %s, result = %d ===========", file_path, upload_result); +} + +void upload_id_received_handle(const char *file_path, const char *upload_id, void *user_data) +{ + EXAMPLE_TRACE("=========== file_path = %s, upload_id = %s ===========", file_path, upload_id); + + if (upload_id != NULL) { + memset(g_upload_id, 0, sizeof(g_upload_id)); + strncpy(g_upload_id, upload_id, sizeof(g_upload_id) - 1); + } +} + +static void _on_http2_reconnect(void) +{ + EXAMPLE_TRACE("http2 reconnected"); + + is_connected = 1; +} + +static void _on_http2_disconnect(void) +{ + EXAMPLE_TRACE("http2 disconnected"); + + is_connected = 0; +} + +static int http2_stream_test(char **argv,int argc) +{ + http2_upload_conn_info_t conn_info; + http2_status_cb_t status_cb; + http2_upload_result_cb_t result_cb; + void *handle; + uint32_t retry_time = 0; + int ret; + + memset(&conn_info, 0, sizeof( http2_upload_conn_info_t)); + conn_info.product_key = HTTP2_PRODUCT_KEY; + conn_info.device_name = HTTP2_DEVICE_NAME; + conn_info.device_secret = HTTP2_DEVICE_SECRET; + conn_info.url = HTTP2_ONLINE_SERVER_URL; + conn_info.port = HTTP2_ONLINE_SERVER_PORT; + + memset(&status_cb, 0, sizeof(http2_status_cb_t)); + status_cb.on_reconnect_cb = _on_http2_reconnect; + status_cb.on_disconnect_cb = _on_http2_disconnect; + + memset(&result_cb, 0, sizeof(http2_upload_result_cb_t)); + result_cb.upload_completed_cb = upload_file_result; + result_cb.upload_id_received_cb = upload_id_received_handle; + + handle = IOT_HTTP2_UploadFile_Connect(&conn_info, &status_cb); + if(handle == NULL) { + return -1; + } + is_connected = 1; + + http2_upload_params_t fs_params; + memset(&fs_params, 0, sizeof(fs_params)); + fs_params.file_path = argv[1]; + fs_params.opt_bit_map = UPLOAD_FILE_OPT_BIT_OVERWRITE; + + ret = IOT_HTTP2_UploadFile_Request(handle, &fs_params, &result_cb, NULL); + if(ret < 0) { + return -1; + } + + /* wait until upload end */ + while (upload_result == 1) { + HAL_SleepMs(200); + } + + /* check the result */ + if (upload_result == UPLOAD_SUCCESS) { + EXAMPLE_TRACE("upload succeed"); + ret = IOT_HTTP2_UploadFile_Disconnect(handle); + EXAMPLE_TRACE("close connect %d\n", ret); + return 0; + } + else { + /* check if upload_id receivced */ + if (g_upload_id[0] == '\0') { + EXAMPLE_TRACE("upload id is NULL, resume is impossible!"); + return -1; + } + } + + /* into resume routine */ + do { + /* TODO: assume that http2 disconnected */ + if (upload_result < 0 && is_connected == 1) { + HAL_SleepMs(30000); + } + + /* wait until connected */ + while (is_connected == 0) { + HAL_SleepMs(200); + } + + /* reset upload result */ + upload_result = 1; + + /* use resume option to upload file */ + fs_params.file_path = argv[1]; + fs_params.upload_len = 0; + fs_params.upload_id = g_upload_id; + fs_params.opt_bit_map = UPLOAD_FILE_OPT_BIT_RESUME; /* resume option used */ + ret = IOT_HTTP2_UploadFile_Request(handle, &fs_params, &result_cb, NULL); + if (ret < 0) { + EXAMPLE_TRACE("upload file request error"); + return -1; + } + + while (upload_result == 1) { + HAL_SleepMs(200); + } + + } while (upload_result != UPLOAD_SUCCESS && (++retry_time < UPLOAD_RETRY_TIME)); + + EXAMPLE_TRACE("upload succeed %d\n", ret); + + ret = IOT_HTTP2_UploadFile_Disconnect(handle); + EXAMPLE_TRACE("close connect %d\n", ret); + return 0; +} + +int main(int argc, char **argv) +{ + int ret; + + if (argc < 2) { + HAL_Printf("no file name input!\n"); + return 0; + } + + ret = http2_stream_test(argv, argc); + return ret; +} + diff --git a/iotkit-embedded/src/http2/examples/http2_example_stream.c b/iotkit-embedded/src/http2/examples/http2_example_stream.c new file mode 100644 index 0000000..4be8007 --- /dev/null +++ b/iotkit-embedded/src/http2/examples/http2_example_stream.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include +#include "http2_api.h" +#include "http2_wrapper.h" + +#ifndef ON_DAILY +#define ON_DAILY +#endif +#if defined(ON_DAILY) + #define HTTP2_ONLINE_SERVER_URL "10.101.12.205" + #define HTTP2_ONLINE_SERVER_PORT 9999 + #define HTTP2_PRODUCT_KEY "a1L5EUOh21s" + #define HTTP2_DEVICE_NAME "zhangmei_test01" + #define HTTP2_DEVICE_SECRET "KQCftfEDCx35LChyEwZoYY6FCYidTOp0" +#elif defined(ON_PRE) + #define HTTP2_ONLINE_SERVER_URL "100.67.141.158" + #define HTTP2_ONLINE_SERVER_PORT 8443 + #define HTTP2_PRODUCT_KEY "b1XVhqfan1X" + #define HTTP2_DEVICE_NAME "YvhjziEQmKusCFUgRpeo" + #define HTTP2_DEVICE_SECRET "QjkhCrAX0SbNWgKpIamuiDdLkk23Q1r7" +#else + #define HTTP2_ONLINE_SERVER_URL NULL + #define HTTP2_ONLINE_SERVER_PORT 443 + #define HTTP2_PRODUCT_KEY "DM5b8zbTWJs" + #define HTTP2_DEVICE_NAME "mydevice1" + #define HTTP2_DEVICE_SECRET "q4tiwQuICYfr6JQ8aUFjWxocuXJ5ruEx" +#endif + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while (0) + + +void* pid1; + +static const char UPLOAD_STRING[] = + "It was almost December, and Jonas was beginning to be frightened. No. Wrong word, Jonas thought." + "Frightened meant that deep, sickening feeling of something terrible about to happen. Frightened was" + " the way he had felt a year ago when an unidentified aircraft had overflown the community twice." + " He had seen it both times. Squinting toward the sky, he had seen the sleek jet, almost a blur at" + " its high speed, go past, and a second later heard the blast of sound that followed. Then one more time," + " a moment later, from the opposite direction, the same plane. At first, he had been only fascinated. " + "He had never seen aircraft so close, for it was against the rules for Pilots to fly over the community." + " Occasionally, when supplies were delivered by cargo planes to the landing field across the river," + " the children rode their bicycles to the riverbank and watched, intrigued, the unloading and then the " + "takeoff directed to the west, always away from the community. But the aircraft a year ago had been different." + " It was not a squat, fat-bellied cargo plane but a needle-nosed single-pilot jet. Jonas, looking around" + " anxiously, had seen others — adults as well as children — stop what they were doing and wait, confused," + " for an explanation of the frightening event. Then all of the citizens had been ordered to go into the nearest" + " building and stay there. IMMEDIATELY, the rasping voice through the speakers had said. LEAVE YOUR BICYCLES " + "WHERE THEY ARE. Instantly, obediently, Jonas had dropped his bike on its side on the path behind his family's " + "dwelling. He had run indoors and stayed there, alone. His parents were both at work, and his little sister," + " Lily, was at the Childcare Center where she spent her after-school hours. Looking through the front window," + " he had seen no people: none of the busy afternoon crew of Street Cleaners, Landscape Workers, and Food " + "Delivery people who usually populated the community at that time of day. He saw only the abandoned bikes here " + "and there on their sides; an upturned wheel on one was still revolving slowly. He had been frightened then. " + "The sense of his own community silent, waiting, had made his stomach churn. He had trembled. But it had been " + "nothing. Within minutes the speakers had crackled again, and the voice, reassuring now and less urgent, " + "had explained that a Pilot-in-Training had misread his navigational instructions and made a wrong turn. " + "Desperately the Pilot had been trying to make his way back before his error was noticed. NEEDLESS TO SAY, " + "HE WILL BE RELEASED, the voice had said, followed by silence. There was an ironic tone to that final message, " + "as if the Speaker found it amusing; and Jonas had smiled a little, though he knew what a grim statement it had" + " been. For a contributing citizen to be released from the community was a final decision, a terrible punishment," + " an overwhelming statement of failure. Even the children were scolded if they used the term lightly at play, " + "jeering at a teammate who missed a catch or stumbled in a race. Jonas had done it once, had shouted at his " + "best friend, "That's it, Asher! You're released!" when Asher's clumsy error had lost a match for " + "his team. He had been taken aside for a brief and serious talk by the coach, had hung his head with guilt and " + "embarrassment, and apologized to Asher after the game. Now, thinking about the feeling of fear as he pedaled " + "home along the river path, he remembered that moment of palpable, stomach-sinking terror when the aircraft had" + " streaked above. It was not what he was feeling now with December approaching. He searched for the right word" + " to describe his own feeling. Jonas was careful about language. Not like his friend, Asher, who talked too " + "fast and mixed things up, scrambling words and phrases until they were barely recognizable and often very funny. " + "Jonas grinned, remembering the morning that Asher had dashed into the classroom, late as usual, arriving " + "breathlessly in the middle of the chanting of the morning anthem. When the class took their seats at the " + "conclusion of the patriotic hymn, Asher remained standing to make his public apology as was required. " + ""I apologize for inconveniencing my learning community." Asher ran through the standard apology" + " phrase rapidly, still catching his breath. The Instructor and class waited patiently for his explanation." + " The students had all been grinning, because they had listened to Asher's explanations so many times before. " + ""I left home at the correct time but when I was riding along near the hatchery, the crew was separating " + "some salmon. I guess I just got distraught, watching them. "I apologize to my classmates," Asher" + " concluded. He smoothed his rumpled tunic and sat down. "We accept your apology, Asher." The class" + " recited the standard response in unison. Many of the students were biting their lips to keep from laughing." + " "I accept your apology, Asher," the Instructor said. He was smiling. "And I thank you, because " + "once again you have provided an opportunity for a lesson in language. "Distraught' is too strong an adjective" + " to describe salmon-viewing." He turned and wrote "distraught" on the instructional board. " + "Beside it he wrote "distracted." Jonas, nearing his home now, smiled at the recollection. Thinking, " + "still, as he wheeled his bike into its narrow port beside the door, he realized that frightened was the wrong " + "word to describe his feelings, now that December was almost here. It was too strong an adjective. He had waited a" + " long time for this special December. Now that it was almost upon him, he wasn't frightened, but he was ... eager," + " he decided. He was eager for it to come. And he was excited, certainly. All of the Elevens were excited about the" + " event that would be coming so soon. But there was a little shudder of nervousness when he thought about it, about" + " what might happen. Apprehensive, Jonas decided. That's what I am. "Who wants to be the first tonight, for " + "feelings?" Jonas's father asked, at the conclusion of their evening meal. It was one of the rituals," + " the evening telling of feelings. Sometimes Jonas and his sister, Lily, argued over turns, over who would get to go first." + " Their parents, of course, were part of the ritual; they, too, told their feelings each evening. But like all parents — " + "all adults — they didn't fight and wheedle for their turn. Nor did Jonas, tonight. His feelings were too complicated this evening."; + + +static void on_header(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) +{ + EXAMPLE_TRACE("~~~~~stream_id = %d, channel_id=%s, name = %s, value = %s, flag = %d user_data =%p\n", stream_id,channel_id,name,value,flags ,user_data); +} + +static void on_chunk_recv(uint32_t stream_id, char *channel_id,const uint8_t *data, uint32_t len,uint8_t flags,void *user_data) +{ + EXAMPLE_TRACE("~~~~~stream_id = %d, channel_id=%s, data = %.*s, len = %d flag = %d\n", stream_id, channel_id, len, data, len, flags); +} +static void on_stream_close(uint32_t stream_id, char *channel_id,uint32_t error_code,void *user_data) +{ + EXAMPLE_TRACE("~~~~~stream_id = %d channel_id=%s, error_code = %d\n", stream_id,channel_id,error_code); +} +static void on_stream_frame_send(uint32_t stream_id, char *channel_id, int type, uint8_t flags,void *user_data){ + EXAMPLE_TRACE("~~~~~stream_id = %d user_data =%p, type = %d\n", stream_id,user_data,type); +} + +static http2_stream_cb_t my_cb = { + .on_stream_header_cb = on_header, + .on_stream_chunk_recv_cb = on_chunk_recv, + .on_stream_close_cb = on_stream_close, + .on_stream_frame_send_cb = on_stream_frame_send, +}; + +static int test_user_data; + +static int http2_stream_test() +{ + int ret; + device_conn_info_t conn_info; + void *handle; + memset(&conn_info, 0, sizeof( device_conn_info_t)); + conn_info.product_key = HTTP2_PRODUCT_KEY; + conn_info.device_name = HTTP2_DEVICE_NAME; + conn_info.device_secret = HTTP2_DEVICE_SECRET; + conn_info.url = HTTP2_ONLINE_SERVER_URL; + conn_info.port = HTTP2_ONLINE_SERVER_PORT; + + handle = IOT_HTTP2_Connect(&conn_info,&my_cb); + if(handle == NULL) { + return -1; + } + + http2_header header[] = { + MAKE_HEADER("test_name", "test_http2_header"), + MAKE_HEADER("x-for-test", "hello world"), + }; + + header_ext_info_t my_header_info = { + header, + 2 + }; + stream_data_info_t info_upload, info_download; + memset(&info_upload,0,sizeof(stream_data_info_t)); + + //info_upload.identify = "com/aliyun/iotx/vision/picture/device/upstream"; + info_upload.identify = "iotx/vision/voice/intercom/live"; + + memset(&info_download, 0, sizeof(stream_data_info_t)); + info_download.identify = "iotx/vision/voice/intercom/live"; + info_download.user_data = (void *)&test_user_data; + + EXAMPLE_TRACE("----------usr_data =%p\n",(void *)&test_user_data); + ret = IOT_HTTP2_Stream_Open(handle, &info_download, &my_header_info); + if (ret < 0) { + EXAMPLE_TRACE("=========iotx_http2_downstream_open failed %d!!!!!\n", ret); + IOT_HTTP2_Disconnect(handle); + return -1; + } + + ret = IOT_HTTP2_Stream_Query(handle, &info_download, &my_header_info); + if (ret < 0) { + EXAMPLE_TRACE("=========iotx_http2_downstream_query failed %d!!!!!\n", ret); + IOT_HTTP2_Stream_Close(handle, &info_download); + IOT_HTTP2_Disconnect(handle); + return -1; + } + info_upload.user_data = (void *)&test_user_data; + ret = IOT_HTTP2_Stream_Open(handle, &info_upload, &my_header_info); + if(ret < 0) { + EXAMPLE_TRACE("=========iotx_http2_upstream_open failed %d!!!!!\n", ret); + IOT_HTTP2_Stream_Close(handle, &info_download); + IOT_HTTP2_Disconnect(handle); + return -1; + } + //send request 1 + info_upload.stream = (char *)UPLOAD_STRING; + info_upload.stream_len= sizeof(UPLOAD_STRING); + info_upload.send_len = 0; + info_upload.packet_len=2048; + + while(info_upload.send_len +#include +#include +#include "http2_upload_api.h" +#include "http2_wrapper.h" + + +#define HTTP2_ONLINE_SERVER_URL "a1IgnOND7vI.iot-as-http2.cn-shanghai.aliyuncs.com" +#define HTTP2_ONLINE_SERVER_PORT 443 +#define HTTP2_PRODUCT_KEY "a1IgnOND7vI" +#define HTTP2_DEVICE_NAME "H2_FS01" +#define HTTP2_DEVICE_SECRET "r9XSyeZOu6swgV8etCcCGmgQhBSpGBau" + + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while (0) + +static int upload_end = 0; +static char g_upload_id[50] = {0}; + +void upload_file_result(const char *file_path, int result, void *user_data) +{ + upload_end++; + EXAMPLE_TRACE("=========== file_path = %s, result = %d, finish num = %d ===========", file_path, result, upload_end); +} + +void upload_id_received_handle(const char *file_path, const char *upload_id, void *user_data) +{ + EXAMPLE_TRACE("=========== file_path = %s, upload_id = %s ===========", file_path, upload_id); + + if (upload_id != NULL) { + memset(g_upload_id, 0, sizeof(g_upload_id)); + strncpy(g_upload_id, upload_id, sizeof(g_upload_id) - 1); + } +} + +static int http2_stream_test(char **argv,int argc) +{ + int ret; + http2_upload_conn_info_t conn_info; + http2_upload_result_cb_t result_cb; + void *handle; + int goal_num = 0; + int i; + + memset(&conn_info, 0, sizeof(http2_upload_conn_info_t)); + conn_info.product_key = HTTP2_PRODUCT_KEY; + conn_info.device_name = HTTP2_DEVICE_NAME; + conn_info.device_secret = HTTP2_DEVICE_SECRET; + conn_info.url = HTTP2_ONLINE_SERVER_URL; + conn_info.port = HTTP2_ONLINE_SERVER_PORT; + + memset(&result_cb, 0, sizeof(http2_upload_result_cb_t)); + result_cb.upload_completed_cb = upload_file_result; + result_cb.upload_id_received_cb = upload_id_received_handle; + + handle = IOT_HTTP2_UploadFile_Connect(&conn_info, NULL); + if(handle == NULL) { + return -1; + } + + for (i=1; i +#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/iotkit-embedded/src/http2/http2_api.h b/iotkit-embedded/src/http2/http2_api.h new file mode 100644 index 0000000..1eda9fd --- /dev/null +++ b/iotkit-embedded/src/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; + +void *IOT_HTTP2_Connect(device_conn_info_t *conn_info, http2_stream_cb_t *user_cb); +int IOT_HTTP2_Stream_Open(void *handle, stream_data_info_t *info, header_ext_info_t *header); +int IOT_HTTP2_Stream_Send(void *handle, stream_data_info_t *info, header_ext_info_t *header); +int IOT_HTTP2_Stream_Query(void *handle, stream_data_info_t *info, header_ext_info_t *header); +int IOT_HTTP2_Stream_Close(void *handle, stream_data_info_t *info); +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); +int IOT_HTTP2_Disconnect(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* IOT_EXPORT_FILE_UPLOADER_H */ diff --git a/iotkit-embedded/src/http2/http2_config.h b/iotkit-embedded/src/http2/http2_config.h new file mode 100644 index 0000000..d1bc5d3 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/http2/http2_internal.h b/iotkit-embedded/src/http2/http2_internal.h new file mode 100644 index 0000000..0b97aa3 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/http2/http2_upload_api.c b/iotkit-embedded/src/http2/http2_upload_api.c new file mode 100644 index 0000000..0f9f206 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/http2/http2_upload_api.h b/iotkit-embedded/src/http2/http2_upload_api.h new file mode 100644 index 0000000..236a179 --- /dev/null +++ b/iotkit-embedded/src/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 */ +void *IOT_HTTP2_UploadFile_Connect(http2_upload_conn_info_t *conn_info, http2_status_cb_t *cb); + +/* http2 uploadfile start 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 */ +int IOT_HTTP2_UploadFile_Disconnect(void *handle); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef _HTTP2_UPLOAD_API_H_ */ + + diff --git a/iotkit-embedded/src/http2/http2_wrapper.h b/iotkit-embedded/src/http2/http2_wrapper.h new file mode 100644 index 0000000..454401b --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/http2/iot.mk b/iotkit-embedded/src/http2/iot.mk new file mode 100644 index 0000000..cffc110 --- /dev/null +++ b/iotkit-embedded/src/http2/iot.mk @@ -0,0 +1,16 @@ +LIBA_TARGET := libiot_http2.a + +HDR_REFS += src/infra + +DEPENDS += wrappers external_libs/nghttp2 +LDFLAGS += -liot_sdk -liot_hal -liot_tls -liot_nghttp2 + +LIB_SRCS_EXCLUDE := examples/http2_example_stream.c examples/http2_example_uploadfile.c examples/http2_example_break_resume.c + +SRCS_http2-example-stream += examples/http2_example_stream.c +SRCS_http2-example-uploadfile += examples/http2_example_uploadfile.c +SRCS_http2-example-break-resume += examples/http2_example_break_resume.c + +$(call Append_Conditional, TARGET, http2-example-stream, HTTP2_COMM_ENABLED) +$(call Append_Conditional, TARGET, http2-example-uploadfile http2-example-break-resume, HTTP2_COMM_ENABLED FS_ENABLED) + diff --git a/iotkit-embedded/src/http2/iotx_http2.c b/iotkit-embedded/src/http2/iotx_http2.c new file mode 100644 index 0000000..d73eb96 --- /dev/null +++ b/iotkit-embedded/src/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 < length) { + 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/iotkit-embedded/src/infra/infra_aes.c b/iotkit-embedded/src/infra/infra_aes.c new file mode 100644 index 0000000..90ccbba --- /dev/null +++ b/iotkit-embedded/src/infra/infra_aes.c @@ -0,0 +1,1016 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ +#include "infra_config.h" +#ifdef INFRA_AES + +#if !defined(INFRA_CONFIG_FILE) +#include "infra_aes_config.h" +#else +#include INFRA_CONFIG_FILE +#endif + +#if defined(INFRA_AES_C) + +#include + +#include "infra_aes.h" + +#if !defined(INFRA_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void infra_aes_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define 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 PUT_UINT32_LE +#define 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 + +#if defined(INFRA_PADLOCK_C) && \ + ( defined(INFRA_HAVE_X86) || defined(INFRA_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(INFRA_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* INFRA_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif /* INFRA_AES_ROM_TABLES */ + +void infra_aes_init( infra_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( infra_aes_context ) ); +} + +void infra_aes_free( infra_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + infra_aes_zeroize( ctx, sizeof( infra_aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +#if !defined(INFRA_AES_SETKEY_ENC_ALT) +int infra_aes_setkey_enc( infra_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(INFRA_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( INFRA_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(INFRA_PADLOCK_C) && defined(INFRA_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = infra_aes_padlock_has_support( INFRA_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = INFRA_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(INFRA_AESNI_C) && defined(INFRA_HAVE_X86_64) + if( infra_aesni_has_support( INFRA_AESNI_AES ) ) + return( infra_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !INFRA_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(INFRA_AES_SETKEY_DEC_ALT) +int infra_aes_setkey_dec( infra_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + infra_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + infra_aes_init( &cty ); + +#if defined(INFRA_PADLOCK_C) && defined(INFRA_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = infra_aes_padlock_has_support( INFRA_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = INFRA_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = infra_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(INFRA_AESNI_C) && defined(INFRA_HAVE_X86_64) + if( infra_aesni_has_support( INFRA_AESNI_AES ) ) + { + infra_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + infra_aes_free( &cty ); + + return( ret ); +} +#endif /* !INFRA_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption + */ +#if !defined(INFRA_AES_ENCRYPT_ALT) +int infra_aes_internal_aes_encrypt( infra_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !INFRA_AES_ENCRYPT_ALT */ + +/* + * AES-ECB block decryption + */ +#if !defined(INFRA_AES_DECRYPT_ALT) +int infra_aes_internal_aes_decrypt( infra_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !INFRA_AES_DECRYPT_ALT */ + +/* + * AES-ECB block encryption/decryption + */ +int infra_aes_crypt_ecb( infra_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ +#if defined(INFRA_AESNI_C) && defined(INFRA_HAVE_X86_64) + if( infra_aesni_has_support( INFRA_AESNI_AES ) ) + return( infra_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(INFRA_PADLOCK_C) && defined(INFRA_HAVE_X86) + if( aes_padlock_ace ) + { + if( infra_aes_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == INFRA_AES_ENCRYPT ) + return( infra_aes_internal_aes_encrypt( ctx, input, output ) ); + else + return( infra_aes_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(INFRA_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int infra_aes_crypt_cbc( infra_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( INFRA_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(INFRA_PADLOCK_C) && defined(INFRA_HAVE_X86) + if( aes_padlock_ace ) + { + if( infra_aes_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == INFRA_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + infra_aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + infra_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* INFRA_CIPHER_MODE_CBC */ + +#if defined(INFRA_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int infra_aes_crypt_cfb128( infra_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == INFRA_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + infra_aes_crypt_ecb( ctx, INFRA_AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + infra_aes_crypt_ecb( ctx, INFRA_AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int infra_aes_crypt_cfb8( infra_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + while( length-- ) + { + memcpy( ov, iv, 16 ); + infra_aes_crypt_ecb( ctx, INFRA_AES_ENCRYPT, iv, iv ); + + if( mode == INFRA_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == INFRA_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /*INFRA_CIPHER_MODE_CFB */ + +#if defined(INFRA_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int infra_aes_crypt_ctr( infra_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + infra_aes_crypt_ecb( ctx, INFRA_AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* INFRA_CIPHER_MODE_CTR */ + +#endif /* !INFRA_AES_ALT */ + +#endif /* INFRA_AES_C */ + +#endif /* INFRA_AES */ diff --git a/iotkit-embedded/src/infra/infra_aes.h b/iotkit-embedded/src/infra/infra_aes.h new file mode 100644 index 0000000..f7c1674 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_aes.h @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef INFRA_AES_H +#define INFRA_AES_H + +#if !defined(INFRA_AES_CONFIG_FILE) + #include "infra_aes_config.h" +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define INFRA_AES_ENCRYPT 1 +#define INFRA_AES_DECRYPT 0 + +#define INFRA_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define INFRA_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) + #define inline __inline +#endif + +#if !defined(INFRA_AES_ALT) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief AES context structure + * + * \note buf is able to hold 32 extra bytes, which can be used: + * - for alignment purposes if VIA padlock is used, and/or + * - to simplify key expansion in the 256-bit case by + * generating an extra round key + */ +typedef struct { + int nr; /*!< number of rounds */ + uint32_t *rk; /*!< AES round keys */ + uint32_t buf[68]; /*!< unaligned data */ +} +infra_aes_context; + +/** + * \brief Initialize AES context + * + * \param ctx AES context to be initialized + */ +void infra_aes_init(infra_aes_context *ctx); + +/** + * \brief Clear AES context + * + * \param ctx AES context to be cleared + */ +void infra_aes_free(infra_aes_context *ctx); + +/** + * \brief AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or INFRA_ERR_AES_INVALID_KEY_LENGTH + */ +int infra_aes_setkey_enc(infra_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or INFRA_ERR_AES_INVALID_KEY_LENGTH + */ +int infra_aes_setkey_dec(infra_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int infra_aes_crypt_ecb(infra_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]); + +#if defined(INFRA_CIPHER_MODE_CBC) +/** + * \brief AES-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or INFRA_ERR_AES_INVALID_INPUT_LENGTH + */ +int infra_aes_crypt_cbc(infra_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); +#endif /* INFRA_CIPHER_MODE_CBC */ + +#if defined(INFRA_CIPHER_MODE_CFB) +/** + * \brief AES-CFB128 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * infra_aes_setkey_enc() for both INFRA_AES_ENCRYPT and INFRA_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int infra_aes_crypt_cfb128(infra_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); + +/** + * \brief AES-CFB8 buffer encryption/decryption. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * infra_aes_setkey_enc() for both INFRA_AES_ENCRYPT and INFRA_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx AES context + * \param mode INFRA_AES_ENCRYPT or INFRA_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int infra_aes_crypt_cfb8(infra_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); +#endif /*INFRA_CIPHER_MODE_CFB */ + +#if defined(INFRA_CIPHER_MODE_CTR) +/** + * \brief AES-CTR buffer encryption/decryption + * + * Warning: You have to keep the maximum use of your counter in mind! + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * infra_aes_setkey_enc() for both INFRA_AES_ENCRYPT and INFRA_AES_DECRYPT. + * + * \param ctx AES context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int infra_aes_crypt_ctr(infra_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output); +#endif /* INFRA_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see INFRA_AES_ENCRYPT_ALT) + * + * \param ctx AES context + * \param input Plaintext block + * \param output Output (ciphertext) block + * + * \return 0 if successful + */ +int infra_internal_aes_encrypt(infra_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); + +/** + * \brief Internal AES block decryption function + * (Only exposed to allow overriding it, + * see INFRA_AES_DECRYPT_ALT) + * + * \param ctx AES context + * \param input Ciphertext block + * \param output Output (plaintext) block + * + * \return 0 if successful + */ +int infra_internal_aes_decrypt(infra_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); + +#if !defined(INFRA_DEPRECATED_REMOVED) +#if defined(INFRA_DEPRECATED_WARNING) +#define INFRA_DEPRECATED __attribute__((deprecated)) +#else +#define INFRA_DEPRECATED +#endif +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see INFRA_AES_ENCRYPT_ALT) + * + * \deprecated Superseded by infra_aes_encrypt_ext() in 2.5.0 + * + * \param ctx AES context + * \param input Plaintext block + * \param output Output (ciphertext) block + */ +#if 0 +INFRA_DEPRECATED static inline void infra_aes_encrypt( + infra_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + infra_internal_aes_encrypt(ctx, input, output); +} +#endif + +/** + * \brief Internal AES block decryption function + * (Only exposed to allow overriding it, + * see INFRA_AES_DECRYPT_ALT) + * + * \deprecated Superseded by infra_aes_decrypt_ext() in 2.5.0 + * + * \param ctx AES context + * \param input Ciphertext block + * \param output Output (plaintext) block + */ +#if 0 +INFRA_DEPRECATED static inline void infra_aes_decrypt( + infra_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + infra_internal_aes_decrypt(ctx, input, output); +} +#endif + +#undef INFRA_DEPRECATED +#endif /* !INFRA_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* INFRA_AES_ALT */ +#include "aes_alt.h" +#endif /* INFRA_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int infra_aes_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/iotkit-embedded/src/infra/infra_aes_config.h b/iotkit-embedded/src/infra/infra_aes_config.h new file mode 100644 index 0000000..85c8f39 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_aes_config.h @@ -0,0 +1,2431 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef INFRA_AES_CONFIG_H +#define INFRA_AES_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) + #define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def INFRA_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/timing.c + * library/padlock.c + * include/mbedtls/bn_mul.h + * + * Comment to disable the use of assembly code. + */ + +/** + * \def INFRA_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ + +/** + * \def INFRA_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with INFRA_HAVE_TIME_DATE + * + * Defining INFRA_HAVE_TIME allows you to specify INFRA_PLATFORM_TIME_ALT, + * INFRA_PLATFORM_TIME_MACRO, INFRA_PLATFORM_TIME_TYPE_MACRO and + * INFRA_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ + +/** + * \def INFRA_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ + +/** + * \def INFRA_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling INFRA_PLATFORM_MEMORY without the + * INFRA_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling INFRA_PLATFORM_MEMORY and specifying + * INFRA_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: INFRA_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define INFRA_PLATFORM_MEMORY + +/** + * \def INFRA_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * INFRA_PLATFORM_STD_CALLOC and printf() to INFRA_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the INFRA_PLATFORM_STD_XXX defines, or enabling a + * INFRA_PLATFORM_XXX_MACRO. + * + * Requires: INFRA_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ + +/** + * \def INFRA_PLATFORM_EXIT_ALT + * + * INFRA_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment INFRA_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require INFRA_PLATFORM_C to be defined! + * + * \note INFRA_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning INFRA_PLATFORM_XXX_ALT cannot be defined at the same time as + * INFRA_PLATFORM_XXX_MACRO! + * + * Requires: INFRA_PLATFORM_TIME_ALT requires INFRA_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ + +/** + * \def INFRA_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use INFRA_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ + +/** + * \def INFRA_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def INFRA_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have INFRA_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ + +/** + * \def INFRA_AES_ALT + * + * INFRA__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the INFRA__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment INFRA_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + */ +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other INFRA__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ + +/** + * \def INFRA_MD2_PROCESS_ALT + * + * INFRA__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the INFRA__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment INFRA_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set + * INFRA_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ + +/** + * \def INFRA_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * INFRA_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the INFRA_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining INFRA_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment INFRA_ECP_INTERNAL_ALT and + * INFRA_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +/* Support for Weierstrass curves with Jacobi representation */ +/* Support for curves with Montgomery arithmetic */ + +/** + * \def INFRA_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the INFRA_ENTROPY_HARDWARE_ALT or the + * INFRA_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires INFRA_ENTROPY_C, INFRA_NO_DEFAULT_ENTROPY_SOURCES + * + */ + +/** + * \def INFRA_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ + +/** + * \def INFRA_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ + +/** + * \def INFRA_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ + +/** + * \def INFRA_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define INFRA_CIPHER_MODE_CBC + +/** + * \def INFRA_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define INFRA_CIPHER_MODE_CFB + +/** + * \def INFRA_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ + +/** + * \def INFRA_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires INFRA_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * INFRA_TLS_ECDH_ECDSA_WITH_NULL_SHA + * INFRA_TLS_ECDH_RSA_WITH_NULL_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * INFRA_TLS_ECDHE_RSA_WITH_NULL_SHA + * INFRA_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * INFRA_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * INFRA_TLS_ECDHE_PSK_WITH_NULL_SHA + * INFRA_TLS_DHE_PSK_WITH_NULL_SHA384 + * INFRA_TLS_DHE_PSK_WITH_NULL_SHA256 + * INFRA_TLS_DHE_PSK_WITH_NULL_SHA + * INFRA_TLS_RSA_WITH_NULL_SHA256 + * INFRA_TLS_RSA_WITH_NULL_SHA + * INFRA_TLS_RSA_WITH_NULL_MD5 + * INFRA_TLS_RSA_PSK_WITH_NULL_SHA384 + * INFRA_TLS_RSA_PSK_WITH_NULL_SHA256 + * INFRA_TLS_RSA_PSK_WITH_NULL_SHA + * INFRA_TLS_PSK_WITH_NULL_SHA384 + * INFRA_TLS_PSK_WITH_NULL_SHA256 + * INFRA_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ + +/** + * \def INFRA_CIPHER_PADDING_PKCS7 + * + * INFRA_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define INFRA_CIPHER_PADDING_PKCS7 +#define INFRA_CIPHER_PADDING_ZEROS + +/** + * \def INFRA_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * INFRA_TLS_RSA_WITH_DES_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ + +/** + * \def INFRA_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define INFRA_REMOVE_ARC4_CIPHERSUITES + +/** + * \def INFRA_ECP_DP_SECP192R1_ENABLED + * + * INFRA_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ + +/** + * \def INFRA_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ + +/** + * \def INFRA_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: INFRA_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ + +/** + * \def INFRA_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_PSK_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_PSK_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_PSK_WITH_RC4_128_SHA + */ +#define INFRA_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def INFRA_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_RC4_128_SHA + */ + +/** + * \def INFRA_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ + +/** + * \def INFRA_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_RSA_C, INFRA_PKCS1_V15, + * INFRA_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define INFRA_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def INFRA_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_RSA_C, INFRA_PKCS1_V15, + * INFRA_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_RSA_WITH_AES_256_CBC_SHA256 + * INFRA_TLS_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * INFRA_TLS_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * INFRA_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_RSA_WITH_RC4_128_SHA + * INFRA_TLS_RSA_WITH_RC4_128_MD5 + */ +#define INFRA_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def INFRA_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_DHM_C, INFRA_RSA_C, INFRA_PKCS1_V15, + * INFRA_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ + +/** + * \def INFRA_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_ECDH_C, INFRA_RSA_C, INFRA_PKCS1_V15, + * INFRA_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ + +/** + * \def INFRA_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_ECDH_C, INFRA_ECDSA_C, INFRA_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ + +/** + * \def INFRA_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_ECDH_C, INFRA_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * INFRA_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ + +/** + * \def INFRA_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: INFRA_ECDH_C, INFRA_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDH_RSA_WITH_RC4_128_SHA + * INFRA_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ + +/** + * \def INFRA_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: INFRA_ECJPAKE_C + * INFRA_SHA256_C + * INFRA_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ + +/** + * \def INFRA_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ + +/** + * \def INFRA_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when INFRA_ERROR_C is disabled + * (no effect when INFRA_ERROR_C is enabled). + * + * You can safely disable this if INFRA_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define INFRA_ERROR_STRERROR_DUMMY + +/** + * \def INFRA_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: INFRA_BIGNUM_C + */ +#define INFRA_GENPRIME + +/** + * \def INFRA_FS_IO + * + * Enable functions that use the filesystem. + */ + +/** + * \def INFRA_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ + +/** + * \def INFRA_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ + +/** + * \def INFRA_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: INFRA_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both INFRA_SHA256_C and + * INFRA_SHA512_C are defined. Otherwise the available hash module is used. + */ + +/** + * \def INFRA_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: INFRA_ENTROPY_C, INFRA_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (INFRA_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in INFRA_PLATFORM_STD_NV_SEED_FILE) and at + * least INFRA_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first INFRA_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ + +/** + * \def INFRA_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: INFRA_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ + +/** + * \def INFRA_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: INFRA_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ + +/** + * \def INFRA_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ + +/** + * \def INFRA_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: INFRA_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define INFRA_PKCS1_V15 + +/** + * \def INFRA_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: INFRA_MD_C, INFRA_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define INFRA_PKCS1_V21 + +/** + * \def INFRA_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ + +/** + * \def INFRA_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ + +/** + * \def INFRA_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ + +/** + * \def INFRA_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define INFRA_SSL_ALL_ALERT_MESSAGES + +/** + * \def INFRA_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ + +/** \def INFRA_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: INFRA_SSL_PROTO_TLS1 or + * INFRA_SSL_PROTO_TLS1_1 or + * INFRA_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ + +/** \def INFRA_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: INFRA_SSL_PROTO_TLS1 or + * INFRA_SSL_PROTO_TLS1_1 or + * INFRA_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ + +/** + * \def INFRA_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ + +/** + * \def INFRA_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ + +/** + * \def INFRA_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ + +/** + * \def INFRA_SSL_RENEGOTIATION + * + * Disable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + */ + +/** + * \def INFRA_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (INFRA_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ + +/** + * \def INFRA_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (INFRA_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ + +/** + * \def INFRA_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define INFRA_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def INFRA_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: INFRA_MD5_C + * INFRA_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ + +/** + * \def INFRA_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: INFRA_MD5_C + * INFRA_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ + +/** + * \def INFRA_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: INFRA_MD5_C + * INFRA_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ + +/** + * \def INFRA_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: INFRA_SHA1_C or INFRA_SHA256_C or INFRA_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define INFRA_SSL_PROTO_TLS1_2 + +/** + * \def INFRA_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and INFRA_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and INFRA_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: INFRA_SSL_PROTO_TLS1_1 + * or INFRA_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define INFRA_SSL_PROTO_DTLS + +/** + * \def INFRA_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ + +/** + * \def INFRA_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: INFRA_SSL_TLS_C + * INFRA_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ + +/** + * \def INFRA_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: INFRA_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define INFRA_SSL_DTLS_HELLO_VERIFY + +/** + * \def INFRA_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: INFRA_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define INFRA_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def INFRA_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: INFRA_SSL_PROTO_DTLS + */ + +/** + * \def INFRA_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintainance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by INFRA_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define INFRA_SSL_SESSION_TICKETS + +/** + * \def INFRA_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ + +/** + * \def INFRA_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: INFRA_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ + +/** + * \def INFRA_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ + +/** + * \def INFRA_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: INFRA_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ + +/** + * \def INFRA_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: INFRA_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ + +/** + * \def INFRA_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: INFRA_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ + +/** + * \def INFRA_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ + +/** + * \def INFRA_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ + +/** + * \def INFRA_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define INFRA_X509_CHECK_KEY_USAGE + +/** + * \def INFRA_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define INFRA_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def INFRA_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ + +/** + * \def INFRA_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def INFRA_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: INFRA_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ + +/** + * \def INFRA_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_RSA_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_RSA_WITH_AES_256_CBC_SHA256 + * INFRA_TLS_RSA_WITH_AES_256_CBC_SHA + * INFRA_TLS_RSA_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_RSA_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_RSA_WITH_AES_128_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * INFRA_TLS_PSK_WITH_AES_256_GCM_SHA384 + * INFRA_TLS_PSK_WITH_AES_256_CBC_SHA384 + * INFRA_TLS_PSK_WITH_AES_256_CBC_SHA + * INFRA_TLS_PSK_WITH_AES_128_GCM_SHA256 + * INFRA_TLS_PSK_WITH_AES_128_CBC_SHA256 + * INFRA_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define INFRA_AES_C + +/** + * \def INFRA_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * INFRA_TLS_ECDH_RSA_WITH_RC4_128_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * INFRA_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * INFRA_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * INFRA_TLS_DHE_PSK_WITH_RC4_128_SHA + * INFRA_TLS_RSA_WITH_RC4_128_SHA + * INFRA_TLS_RSA_WITH_RC4_128_MD5 + * INFRA_TLS_RSA_PSK_WITH_RC4_128_SHA + * INFRA_TLS_PSK_WITH_RC4_128_SHA + */ + +/** + * \def INFRA_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define INFRA_ASN1_PARSE_C + +/** + * \def INFRA_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ + +/** + * \def INFRA_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define INFRA_BASE64_C + +/** + * \def INFRA_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define INFRA_BIGNUM_C + +/** + * \def INFRA_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ + +/** + * \def INFRA_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * INFRA_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * INFRA_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * INFRA_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * INFRA_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * INFRA_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ + +/** + * \def INFRA_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: INFRA_AES_C or INFRA_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ + +/** + * \def INFRA_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define INFRA_CERTS_C + +/** + * \def INFRA_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define INFRA_CIPHER_C + +/** + * \def INFRA_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: INFRA_AES_C or INFRA_DES_C + * + */ + +/** + * \def INFRA_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: INFRA_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define INFRA_CTR_DRBG_C + +/** + * \def INFRA_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define INFRA_DEBUG_C + +/** + * \def INFRA_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * INFRA_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * INFRA_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ + +/** + * \def INFRA_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + */ + +/** + * \def INFRA_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: INFRA_ECP_C + */ + +/** + * \def INFRA_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: INFRA_ECP_C, INFRA_ASN1_WRITE_C, INFRA_ASN1_PARSE_C + */ + +/** + * \def INFRA_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: INFRA_ECP_C, INFRA_MD_C + */ + +/** + * \def INFRA_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: INFRA_BIGNUM_C and at least one INFRA_ECP_DP_XXX_ENABLED + */ + +/** + * \def INFRA_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: INFRA_SHA512_C or INFRA_SHA256_C + * + * This module provides a generic entropy pool + */ +#define INFRA_ENTROPY_C + +/** + * \def INFRA_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define INFRA_ERROR_C + +/** + * \def INFRA_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: INFRA_AES_C or INFRA_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ + +/** + * \def INFRA_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: INFRA_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ + +/** + * \def INFRA_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: INFRA_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ + +/** + * \def INFRA_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define INFRA_MD_C + +/** + * \def INFRA_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ + +/** + * \def INFRA_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ + +/** + * \def INFRA_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS and X.509. + * PEM_PARSE uses MD5 for decrypting encrypted keys. + */ + +/** + * \def INFRA_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: INFRA_PLATFORM_C + * INFRA_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ + +/** + * \def INFRA_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +#define INFRA_NET_C + +/** + * \def INFRA_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define INFRA_OID_C + +/** + * \def INFRA_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: INFRA_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ + +/** + * \def INFRA_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: INFRA_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define INFRA_PEM_PARSE_C + +/** + * \def INFRA_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: INFRA_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ + +/** + * \def INFRA_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: INFRA_RSA_C or INFRA_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define INFRA_PK_C + +/** + * \def INFRA_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: INFRA_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define INFRA_PK_PARSE_C + +/** + * \def INFRA_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: INFRA_PK_C + * + * Uncomment to enable generic public key write functions. + */ + +/** + * \def INFRA_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: INFRA_MD_C + * + * This module adds support for the PKCS#5 functions. + */ + +/** + * \def INFRA_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: INFRA_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ + +/** + * \def INFRA_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: INFRA_ASN1_PARSE_C, INFRA_CIPHER_C, INFRA_MD_C + * Can use: INFRA_ARC4_C + * + * This module enables PKCS#12 functions. + */ + +/** + * \def INFRA_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling INFRA_PLATFORM_C enables to use of INFRA_PLATFORM_XXX_ALT + * or INFRA_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define INFRA_PLATFORM_C + +/** + * \def INFRA_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ + +/** + * \def INFRA_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: INFRA_BIGNUM_C, INFRA_OID_C + */ +#define INFRA_RSA_C + +/** + * \def INFRA_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS and SHA1-signed certificates. + */ +#define INFRA_SHA1_C + +/** + * \def INFRA_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define INFRA_SHA256_C + +/** + * \def INFRA_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ + +/** + * \def INFRA_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: INFRA_SSL_CACHE_C + */ +#define INFRA_SSL_CACHE_C + +/** + * \def INFRA_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define INFRA_SSL_COOKIE_C + +/** + * \def INFRA_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: INFRA_CIPHER_C + */ +#define INFRA_SSL_TICKET_C + +/** + * \def INFRA_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: INFRA_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define INFRA_SSL_CLI_C + +/** + * \def INFRA_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: INFRA_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ + +/** + * \def INFRA_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: INFRA_CIPHER_C, INFRA_MD_C + * and at least one of the INFRA_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define INFRA_SSL_TLS_C + +/** + * \def INFRA_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either INFRA_THREADING_ALT or + * INFRA_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ + +/** + * \def INFRA_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c INFRA_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define INFRA_TIMING_C + +/** + * \def INFRA_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ + +/** + * \def INFRA_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: INFRA_ASN1_PARSE_C, INFRA_BIGNUM_C, INFRA_OID_C, + * INFRA_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define INFRA_X509_USE_C + +/** + * \def INFRA_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: INFRA_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define INFRA_X509_CRT_PARSE_C + +/** + * \def INFRA_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: INFRA_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ + +/** + * \def INFRA_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: INFRA_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ + +/** + * \def INFRA_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: INFRA_BIGNUM_C, INFRA_OID_C, INFRA_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ + +/** + * \def INFRA_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: INFRA_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ + +/** + * \def INFRA_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: INFRA_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ + +/** + * \def INFRA_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ + +/* CTR_DRBG options */ + +/* HMAC_DRBG options */ + +/* ECP options */ + +/* Entropy options */ + +/* Memory buffer allocator options */ + +/* Platform options */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ + +/* To Use Function Macros INFRA_PLATFORM_C must be enabled */ +/* INFRA_PLATFORM_XXX_MACRO and INFRA_PLATFORM_XXX_ALT cannot both be defined */ + +/* SSL Cache options */ + +/* SSL options */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ + +/* X509 options */ + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations */ + +#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_INFRA_TARGET_CONFIG_FILE) + #include YOTTA_CFG_INFRA_TARGET_CONFIG_FILE +#endif + +/* + * Allow user to override any previous default. + * + * Use two macro names for that, as: + * - with yotta the prefix YOTTA_CFG_ is forced + * - without yotta is looks weird to have a YOTTA prefix. + */ +#if defined(YOTTA_CFG_INFRA_USER_CONFIG_FILE) + #include YOTTA_CFG_INFRA_USER_CONFIG_FILE +#elif defined(INFRA_USER_CONFIG_FILE) + #include INFRA_USER_CONFIG_FILE +#endif + + +#endif /* INFRA_AES_CONFIG_H */ diff --git a/iotkit-embedded/src/infra/infra_cjson.c b/iotkit-embedded/src/infra/infra_cjson.c new file mode 100644 index 0000000..b2260ca --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_cjson.h b/iotkit-embedded/src/infra/infra_cjson.h new file mode 100644 index 0000000..77c14b5 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_compat.c b/iotkit-embedded/src/infra/infra_compat.c new file mode 100644 index 0000000..07737c4 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_compat.c @@ -0,0 +1,303 @@ +#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); + +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 + +#if defined(DEVICE_MODEL_GATEWAY) + extern int iot_linkkit_subdev_query_id(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]); +#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 +#if defined(DEVICE_MODEL_GATEWAY) + case IOTX_IOCTL_QUERY_DEVID: { + iotx_dev_meta_info_t *dev_info = (iotx_dev_meta_info_t *)data; + + res = iot_linkkit_subdev_query_id(dev_info->product_key, dev_info->device_name); + } + break; +#endif + case IOTX_IOCTL_SET_CUSTOMIZE_INFO: { + if (ctx->mqtt_customzie_info) { + HAL_Free(ctx->mqtt_customzie_info); + ctx->mqtt_customzie_info = NULL; + } + ctx->mqtt_customzie_info = HAL_Malloc(strlen((char *)data) + 1); + if (ctx->mqtt_customzie_info == NULL) { + return FAIL_RETURN; + } + memset(ctx->mqtt_customzie_info, 0, strlen((char *)data) + 1); + memcpy(ctx->mqtt_customzie_info, data, strlen((char *)data)); + res = SUCCESS_RETURN; + } + break; + 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_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_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/iotkit-embedded/src/infra/infra_compat.h b/iotkit-embedded/src/infra/infra_compat.h new file mode 100644 index 0000000..37a895a --- /dev/null +++ b/iotkit-embedded/src/infra/infra_compat.h @@ -0,0 +1,291 @@ +#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; + +void IOT_SetLogLevel(IOT_LogLevel level); +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_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) int iotx_register_for_##evt(cb); +#define DEFINE_EVENT_CALLBACK(evt, cb) 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_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 LIST_HEAD AOS_DLIST_HEAD +#define LIST_HEAD_INIT AOS_DLIST_INIT +#define INIT_LIST_HEAD INIT_AOS_DLIST_HEAD +#define 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; + char *mqtt_customzie_info; +} 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_QUERY_DEVID, /* value(iotx_dev_meta_info_t*): device meta info, only productKey and deviceName is required, ret value is subdev_id or -1 */ + IOTX_IOCTL_SET_CUSTOMIZE_INFO, /* value(char*): set mqtt clientID customize information */ +} 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/iotkit-embedded/src/infra/infra_config.h b/iotkit-embedded/src/infra/infra_config.h new file mode 100644 index 0000000..9a6f659 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_config.h @@ -0,0 +1,7 @@ +#ifndef _INFRA_CONFIG_H_ +#define _INFRA_CONFIG_H_ + +#include "rtconfig.h" + +#endif + diff --git a/iotkit-embedded/src/infra/infra_defs.c b/iotkit-embedded/src/infra/infra_defs.c new file mode 100644 index 0000000..45d97ca --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_defs.h b/iotkit-embedded/src/infra/infra_defs.h new file mode 100644 index 0000000..34b6d6e --- /dev/null +++ b/iotkit-embedded/src/infra/infra_defs.h @@ -0,0 +1,336 @@ +#ifndef _INFRA_DEFS_H_ +#define _INFRA_DEFS_H_ + +#include "infra_types.h" + +#ifdef __cplusplus +extern "C" { +#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]; + +extern int iotx_facility_json_print(const char *str, int level, ...); +#ifdef __cplusplus +} +#endif +#endif + + + diff --git a/iotkit-embedded/src/infra/infra_httpc.c b/iotkit-embedded/src/infra/infra_httpc.c new file mode 100644 index 0000000..9d02a87 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_httpc.c @@ -0,0 +1,583 @@ +/* + * 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. */ + ret = iotx_net_init(&client->net, host, port, ca_crt); + 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/iotkit-embedded/src/utils/misc/utils_httpc.h b/iotkit-embedded/src/infra/infra_httpc.h similarity index 82% rename from iotkit-embedded/src/utils/misc/utils_httpc.h rename to iotkit-embedded/src/infra/infra_httpc.h index 5c6706e..0148ede 100644 --- a/iotkit-embedded/src/utils/misc/utils_httpc.h +++ b/iotkit-embedded/src/infra/infra_httpc.h @@ -1,30 +1,15 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ -#ifndef _IOTX_COMMON_HTTPCLIENT_H_ -#define _IOTX_COMMON_HTTPCLIENT_H_ -#include "iot_import.h" -#include "iot_export.h" -#include "utils_net.h" -#include "utils_timer.h" +#ifndef _INFRA_HTTPC_H_ +#define _INFRA_HTTPC_H_ + +#include "infra_net.h" + #ifdef __cplusplus extern "C" { #endif @@ -119,3 +104,5 @@ void httpclient_close(httpclient_t *client); #endif /* __HTTPCLIENT_H__ */ + + diff --git a/iotkit-embedded/src/packages/LITE-utils/json_token.c b/iotkit-embedded/src/infra/infra_json_parser.c similarity index 63% rename from iotkit-embedded/src/packages/LITE-utils/json_token.c rename to iotkit-embedded/src/infra/infra_json_parser.c index be1570a..9de932e 100644 --- a/iotkit-embedded/src/packages/LITE-utils/json_token.c +++ b/iotkit-embedded/src/infra/infra_json_parser.c @@ -1,74 +1,455 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#include "infra_config.h" +#ifdef INFRA_JSON_PARSER -#include "lite-utils_internal.h" -#include "json_parser.h" +#include +#include +#include +#include -int contain_arr(const char *src, int src_len, const char **arr_pre) +#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) { - int i = 0; - int ret = -1; - int deep = 0; - const char *pre = NULL; + char *pos = NULL; + char ch = (type == JOBJECT) ? '{' : '['; - if (NULL == src || NULL == arr_pre || src_len <= 0) { - return -1; + if (!str || !str_end) { + return NULL; } - *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]; - } - } + 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; - case ']': { - if (deep != 1) { - return ret; - } - --deep; - if ('[' == src[i - 1]) { - return ret; - } - } + } else if (*p_cPos == '{') { + iValueType = JOBJECT; + p_cValue = p_cPos++; break; - default: { - if ((pre != NULL) && (0 == deep)) { - return ret; + } 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--; } } - break; + } 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 ((NULL != pre) && (pre < src + src_len) && (pre >= src)) { - *arr_pre = pre; - ret = 0; + + 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 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 LIST_HEAD(keylist); @@ -104,10 +485,10 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha json_key_t *entry = NULL; - entry = LITE_malloc(sizeof(json_key_t), magic, module_name); + entry = jparser_malloc(sizeof(json_key_t), magic, module_name); if (NULL == entry) { - log_err("LITE_malloc failed!"); + utils_err("jparser_malloc failed!"); return NULL; } memset(entry, 0, sizeof(json_key_t)); @@ -120,7 +501,7 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha } if (NULL == entry->key) { - LITE_free(entry); + jparser_free(entry); return NULL; } @@ -138,7 +519,7 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha } _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); - LITE_free(iter_pre); + jparser_free(iter_pre); } else if (JARRAY == vtype) { mlen = strlen(prefix) + klen + 1; if (module_name) { @@ -151,7 +532,7 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha } _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); - LITE_free(iter_pre); + jparser_free(iter_pre); } } } @@ -162,9 +543,9 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha json_key_t *entry = NULL; unsigned int tmp = 0; unsigned int arridxlen = 0; - entry = LITE_malloc(sizeof(json_key_t), magic, module_name); + entry = jparser_malloc(sizeof(json_key_t), magic, module_name); if (NULL == entry) { - log_err("LITE_malloc failed!"); + utils_err("jparser_malloc failed!"); return NULL; } memset(entry, 0, sizeof(json_key_t)); @@ -181,7 +562,7 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha entry->key = LITE_format_nstring(mlen, "%s[%d]", prefix, count); } if (NULL == entry->key) { - LITE_free(entry); + jparser_free(entry); return NULL; } @@ -199,7 +580,7 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha } _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); - LITE_free(iter_pre); + jparser_free(iter_pre); } else if (JARRAY == vtype) { mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen; if (module_name) { @@ -211,30 +592,79 @@ static list_head_t *_LITE_json_keys_of_ext(int type, char *src, int src_len, cha return NULL; } - _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); - LITE_free(iter_pre); + _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; } - ++count; } + break; } } - - if (!strcmp("", prefix)) { - json_key_t *entry = NULL; - - entry = LITE_malloc(sizeof(json_key_t), magic, module_name); - if (NULL == entry) { - log_err("LITE_malloc failed!"); - return NULL; - } - memset(entry, 0, sizeof(json_key_t)); - list_add_tail(&entry->list, &keylist); - - return &keylist; + if ((NULL != pre) && (pre < src + src_len) && (pre >= src)) { + *arr_pre = pre; + ret = 0; } - - return NULL; - + return ret; } static char *_json_value_by_arrname(char *src, int src_len, const char *key, int key_len, int *val_len) @@ -290,70 +720,6 @@ static char *_json_value_by_arrname(char *src, int src_len, const char *key, int return entry; } -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; - char *module_name = NULL; - - int key_len; - int value_len = -1; - int src_iter_len; - int magic = 0; - - if (NULL == key || NULL == src) { - return NULL; - } - -#if WITH_MEM_STATS_PER_MODULE - - 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 = LITE_malloc((value_len + 1) * sizeof(char), magic, module_name); - if (NULL == ret) { - return NULL; - } - LITE_snprintf(ret, value_len + 1, "%s", value); - return ret; -} - void LITE_json_keys_release(list_head_t *keylist) { json_key_t *pos, *tmp; @@ -364,121 +730,11 @@ void LITE_json_keys_release(list_head_t *keylist) list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) { if (pos->key) { - LITE_free(pos->key); + jparser_free(pos->key); } list_del(&pos->list); - LITE_free(pos); - } -} - -static list_head_t *_LITE_json_keys_of(char *src, int src_len, char *prefix, ...) -{ - static 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 = LITE_malloc(sizeof(json_key_t), magic, module_name); - if (NULL == entry) { - log_err("LITE_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) { - LITE_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); - LITE_free(iter_pre); - } - } - } - - if (!strcmp("", prefix)) { - json_key_t *entry = NULL; - - entry = LITE_malloc(sizeof(json_key_t), magic, module_name); - if (NULL == entry) { - log_err("LITE_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 *); + jparser_free(pos); } - va_end(ap); -#endif - - return _LITE_json_keys_of(src, strlen(src), prefix, magic, module_name); - } list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...) @@ -504,7 +760,6 @@ list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...) 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; @@ -584,88 +839,7 @@ static char *_LITE_json_value_of_ext(char *key, char *src, int src_len, int *val return value; } -char *LITE_json_value_of_ext(char *key, char *src, ...) -{ - char *ret = NULL; - char *value = NULL; - char *module_name = NULL; - int value_len = 0; - int magic = 0; - - if (NULL == key || NULL == src) { - return NULL; - } - -#if WITH_MEM_STATS_PER_MODULE - - 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 /* #if WITH_JSON_TOKEN_EXT */ +#endif /* #if WITH_JSON_KEYS_OF */ #endif - value = _LITE_json_value_of_ext(key, src, strlen(src), &value_len); - if (!value) { - return NULL; - } - - ret = LITE_malloc((value_len + 1) * sizeof(char), magic, module_name); - if (NULL == ret) { - return NULL; - } - LITE_snprintf(ret, value_len + 1, "%s", value); - - return ret; -} - -char *LITE_json_value_of_ext2(char *key, char *src, int src_len, int *value_len) -{ - if (NULL == key || NULL == src || NULL == value_len || src_len <= 0) { - return NULL; - } - - return _LITE_json_value_of_ext(key, src, src_len, value_len); -} - -int get_json_item_size(char *src, int src_len) -{ - char *iter_pos = NULL; - int iter_size = 0; - int iter_obj_deep = 0; - int iter_arr_deep = 0; - int iter_str_deep = 0; - if (!src || (src_len <= 0)) { - return 0; - } - - if ((('[' == *src) && (']' == *(src + 1))) \ - || (('{' == *src) && ('}' == *(src + 1)))) { - return 0; - } - - iter_pos = src + 1; - - while (iter_pos && (iter_pos < src + src_len)) { - if (*iter_pos == '[') { - iter_arr_deep++; - } else if (*iter_pos == ']') { - iter_arr_deep--; - } else if (*iter_pos == '{') { - iter_obj_deep++; - } else if (*iter_pos == '}') { - iter_obj_deep--; - } else if (*iter_pos == '\"') { - ++iter_str_deep; - iter_str_deep %= 2; - } - if (!iter_arr_deep && !iter_obj_deep && !iter_str_deep && *iter_pos == ',') { - iter_size ++; - } - ++iter_pos; - } - - return iter_size + 1; -} diff --git a/iotkit-embedded/src/packages/LITE-utils/json_parser.h b/iotkit-embedded/src/infra/infra_json_parser.h similarity index 87% rename from iotkit-embedded/src/packages/LITE-utils/json_parser.h rename to iotkit-embedded/src/infra/infra_json_parser.h index 5ca8bc4..4224964 100644 --- a/iotkit-embedded/src/packages/LITE-utils/json_parser.h +++ b/iotkit-embedded/src/infra/infra_json_parser.h @@ -1,26 +1,14 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ -#ifndef __JSON_PARSER_H__ -#define __JSON_PARSER_H__ -#include "lite-utils_internal.h" + +#ifndef _INFRA_JSON_PARSER_H_ +#define _INFRA_JSON_PARSER_H_ + +/* #include "iotx_utils_internal.h" */ typedef struct JSON_NV { int nLen; @@ -184,4 +172,8 @@ char *json_get_next_object(int type, char *str, char *str_end, char **key, int * *((char *)json_str + str_len) = register; \ } +char *LITE_json_value_of(char *key, char *src, ...); + #endif /* __JSON_PARSER_H__ */ + + diff --git a/iotkit-embedded/src/infra/infra_list.h b/iotkit-embedded/src/infra/infra_list.h new file mode 100644 index 0000000..b2d6c35 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/log/LITE-log/lite-log.c b/iotkit-embedded/src/infra/infra_log.c similarity index 59% rename from iotkit-embedded/src/log/LITE-log/lite-log.c rename to iotkit-embedded/src/infra/infra_log.c index e381ec6..add4f6e 100644 --- a/iotkit-embedded/src/log/LITE-log/lite-log.c +++ b/iotkit-embedded/src/infra/infra_log.c @@ -1,98 +1,47 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "lite-log_internal.h" - -#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[16 + 1] = {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_sprintf((char *)ascii + i % 16, "%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; -} - -#if defined(LITE_LOG_ENABLED) -static log_client logcb; +#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[] = { - "emg", "crt", "err", "wrn", "inf", "dbg", + "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(const char *f, const int l, const int level, const char *fmt, va_list* params) +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 (!strlen(LITE_get_logname()) || LITE_get_loglevel() < level || level < LOG_EMERG_LEVEL) { + 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)); @@ -112,43 +61,25 @@ void LITE_syslog_routine(const char *f, const int l, const int level, const char LITE_printf(" ..."); } - LITE_printf("\r\n"); + 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(const char *f, const int l, const int level, const char *fmt, ...) +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(f, l, level, fmt, &ap); + LITE_syslog_routine(m, f, l, level, fmt, &ap); va_end(ap); } -int LITE_log_enabled(void) -{ - return 1; -} - -void LITE_openlog(const char *ident) -{ - strncpy(logcb.name, ident, LOG_MOD_NAME_LEN); - logcb.name[LOG_MOD_NAME_LEN] = 0; - logcb.priority = 0; -} - -void LITE_closelog(void) -{ - strncpy(logcb.name, "", LOG_MOD_NAME_LEN); - logcb.name[LOG_MOD_NAME_LEN] = 0; - logcb.priority = 0; -} - -char *LITE_get_logname(void) -{ - return logcb.name; -} - int LITE_get_loglevel(void) { return logcb.priority; @@ -156,7 +87,23 @@ int LITE_get_loglevel(void) 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, @@ -169,10 +116,12 @@ void LITE_rich_hexdump(const char *f, const int l, return; } - LITE_printf(LOG_PREFIX_FMT, lvl_names[LITE_get_loglevel()], f, l); + 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; } @@ -219,69 +168,99 @@ int log_multi_line_internal(const char *f, const int l, return 0; } -#else /* defined(LITE_LOG_ENABLED) */ -void LITE_syslog(const char *f, const int l, const int level, const char *fmt, ...) +#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) { - va_list ap; + int i, j, written; + unsigned char ascii[20] = {0}; + char header[64] = {0}; + unsigned char *buf = (unsigned char *)buff; - HAL_Printf("%s/%d: ", f, l); - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - HAL_Printf("\r\n"); + LITE_snprintf(header, sizeof(header), "| %s: (len=%d) |\r\n", title, (int)len); - return; -} + LITE_HEXDUMP_DRAWLINE("+", strlen(header) - 4, "+"); + LITE_printf("%s", header); + LITE_printf("%s\r\n", HEXDUMP_SEP_LINE); -int log_multi_line_internal(const char *f, const int l, - const char *title, - int level, - char *payload, - const char *mark) -{ - HAL_Printf("%s(%d):\r\n\r\n", f, l); - HAL_Printf("%s\r\n", payload); + written = 0; + for (i = 0; i < len; ++ i) { + if (i % 16 == 0) { + LITE_printf("| %08X: ", (unsigned int)(i + (long)buff)); + written += 8; + } - return 0; -} + 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); -int LITE_log_enabled(void) -{ return 0; } -void LITE_openlog(const char *ident) + +void IOT_SetLogLevel(IOT_LogLevel level) { - return; + 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); } -void LITE_closelog(void) + +#else + +void IOT_SetLogLevel(IOT_LogLevel level) { return; } -char *LITE_get_logname(void) -{ - return NULL; -} -int LITE_get_loglevel(void) -{ - return -1; -} -void LITE_set_loglevel(int lvl) + +int log_multi_line_internal(const char *f, const int l, + const char *title, int level, char *payload, const char *mark) { - return; + 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) { - HAL_Printf("%s/%d: ", f, l); - HAL_Printf("HEXDUMP %s @ %p[%d]\r\n", buf_str, buf_ptr, buf_len); - LITE_hexdump(buf_str, buf_ptr, buf_len); - return; } -#endif /* defined(LITE_LOG_ENABLED) */ +#endif /* #if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED) */ diff --git a/iotkit-embedded/src/infra/infra_log.h b/iotkit-embedded/src/infra/infra_log.h new file mode 100644 index 0000000..1a8572e --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/utils/digest/utils_md5.c b/iotkit-embedded/src/infra/infra_md5.c similarity index 76% rename from iotkit-embedded/src/utils/digest/utils_md5.c rename to iotkit-embedded/src/infra/infra_md5.c index 066d039..cd8dc64 100644 --- a/iotkit-embedded/src/utils/digest/utils_md5.c +++ b/iotkit-embedded/src/infra/infra_md5.c @@ -1,33 +1,17 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#include "infra_config.h" - - +#ifdef INFRA_MD5 #include #include -#include "iot_import.h" -#include "iot_export.h" -#include "lite-log.h" -#include "utils_md5.h" -#define MD5_DIGEST_SIZE 16 +#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) @@ -221,9 +205,9 @@ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]) /* * MD5 process buffer */ -void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, size_t ilen) +void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen) { - size_t fill; + uint32_t fill; uint32_t left; if (ilen == 0) { @@ -298,7 +282,7 @@ void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]) /* * output = MD5( input buffer ) */ -void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16]) +void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16]) { iot_md5_context ctx; @@ -309,10 +293,59 @@ void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16] utils_md5_free(&ctx); } -int8_t utils_hb2hex(uint8_t hb) +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/iotkit-embedded/src/utils/digest/utils_md5.h b/iotkit-embedded/src/infra/infra_md5.h similarity index 65% rename from iotkit-embedded/src/utils/digest/utils_md5.h rename to iotkit-embedded/src/infra/infra_md5.h index f92c9b6..f850163 100644 --- a/iotkit-embedded/src/utils/digest/utils_md5.h +++ b/iotkit-embedded/src/infra/infra_md5.h @@ -1,29 +1,14 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#ifndef _INFRA_MD5_H_ +#define _INFRA_MD5_H_ -#ifndef _IOTX_COMMON_MD5_H_ -#define _IOTX_COMMON_MD5_H_ - -#include "iot_import.h" +#include "infra_types.h" typedef struct { uint32_t total[2]; /*!< number of bytes processed */ @@ -68,7 +53,7 @@ void utils_md5_starts(iot_md5_context *ctx); * \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, size_t ilen); +void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen); /** * \brief MD5 final digest @@ -88,11 +73,9 @@ void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]); * \param ilen length of the input data * \param output MD5 checksum result */ -void utils_md5(const unsigned char *input, size_t ilen, unsigned char output[16]); - - -int8_t utils_hb2hex(uint8_t hb); +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/iotkit-embedded/src/packages/LITE-utils/mem_stats.c b/iotkit-embedded/src/infra/infra_mem_stats.c similarity index 53% rename from iotkit-embedded/src/packages/LITE-utils/mem_stats.c rename to iotkit-embedded/src/infra/infra_mem_stats.c index 4b05586..21c96d3 100644 --- a/iotkit-embedded/src/packages/LITE-utils/mem_stats.c +++ b/iotkit-embedded/src/infra/infra_mem_stats.c @@ -1,27 +1,43 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#include "infra_config.h" + +#ifdef INFRA_MEM_STATS +#include +#include +#include +#include +#include + +#include "infra_mem_stats.h" +#ifdef INFRA_LOG + #include "infra_log.h" + #define utils_emerg(...) log_emerg("util", __VA_ARGS__) + #define utils_crit(...) log_crit("util", __VA_ARGS__) + #define utils_err(...) log_err("util", __VA_ARGS__) + #define utils_warning(...) log_warning("util", __VA_ARGS__) + #define utils_info(...) log_info("util", __VA_ARGS__) + #define utils_debug(...) log_debug("util", __VA_ARGS__) +#else + #define utils_emerg(...) + #define utils_crit(...) + #define utils_err(...) + #define utils_warning(...) + #define utils_info(...) + #define utils_debug(...) +#endif -#include "mem_stats.h" +extern void *HAL_Malloc(uint32_t size); +extern void HAL_Free(void *ptr); +void *HAL_MutexCreate(void); +void HAL_MutexDestroy(void *mutex); +void HAL_MutexLock(void *mutex); +void HAL_MutexUnlock(void *mutex); -LIST_HEAD(mem_recs); -#if WITH_MEM_STATS_PER_MODULE +LIST_HEAD(mem_recs); LIST_HEAD(mem_module_statis); typedef struct { @@ -33,7 +49,6 @@ typedef struct { typedef struct { char module_name[32]; calling_stack_t calling_stack; - int bytes_total_allocated; int bytes_total_freed; int bytes_total_in_use; @@ -50,24 +65,103 @@ typedef struct { list_head_t list; } module_mem_t; -#endif +/* sort module used */ +static int _mem_cmp_max_used(list_head_t *a, list_head_t *b) +{ + module_mem_t *temp_a = list_entry(a, module_mem_t, list); + module_mem_t *temp_b = list_entry(b, module_mem_t, list); -#if WITH_MEM_STATS - static int bytes_total_allocated; - static int bytes_total_freed; - static int bytes_total_in_use; - static int bytes_max_allocated; - static int bytes_max_in_use; - static int iterations_allocated; - static int iterations_freed; - static int iterations_in_use; - static int iterations_max_in_use; -#endif + if (a == NULL || b == NULL) { + return 0; + } -#if defined(_PLATFORM_IS_LINUX_) && (WITH_MEM_STATS) + /* return true to swap if a < b */ + return (temp_a->mem_statis.bytes_max_in_use < temp_b->mem_statis.bytes_max_in_use); +} + +static void _mem_swap_module_pos(list_head_t *a, list_head_t *b) +{ + list_head_t temp = {NULL, NULL}; + + if (a == NULL || a == NULL) { + return; + } + + list_add(&temp, b); + list_del(b); + list_add(b, a); + list_del(a); + list_add(a, &temp); + list_del(&temp); +} + +static void _mem_sort_module_pos(list_head_t *head) +{ + list_head_t *start = NULL; + list_head_t *end = NULL; + + if (head == NULL) { + return; + } + + for (end = head->prev; end != head; end = end->prev) { /* list_for_each_prev */ + list_for_each(start, head) { + if (start == end) { + break; + } + + if (_mem_cmp_max_used(start, start->next)) { + _mem_swap_module_pos(start, start->next); + + start = start->prev; + if (start == end) { + end = end->next; + } + } + } + } +} + +static void *mutex_mem_stats = NULL; +static int bytes_total_allocated; +static int bytes_total_freed; +static int bytes_total_in_use; +static int bytes_max_allocated; +static int bytes_max_in_use; +static int iterations_allocated; +static int iterations_freed; +static int iterations_in_use; +static int iterations_max_in_use; + +#if defined(__UBUNTU_SDK_DEMO__) static int tracking_malloc_callstack = 1; +char *LITE_strdup(const char *src, ...) +{ + int len = 0; + char *dst = NULL; + + if (!src) { + return NULL; + } + len = strlen(src) + 1; + if (len > 1024) { + utils_err("Too long string to duplicate, abort! len = %d", len); + return NULL; + } + + dst = (char *)HAL_Malloc(sizeof(char) * len); + + if (!dst) { + return NULL; + } + strncpy(dst, src, len); + + return dst; +} + + static int record_backtrace(int *level, char *** trace) { #define MAX_BT_LEVEL 8 @@ -77,7 +171,7 @@ static int record_backtrace(int *level, char *** trace) *level = backtrace(buffer, MAX_BT_LEVEL); *trace = backtrace_symbols(buffer, *level); if (*trace == NULL) { - log_err("backtrace_symbols returns NULL!"); + utils_err("backtrace_symbols returns NULL!"); return -1; } @@ -95,35 +189,30 @@ void LITE_track_malloc_callstack(int state) } -#endif /* defined(_PLATFORM_IS_LINUX_) && (WITH_MEM_STATS) */ +#endif /* defined(__UBUNTU_SDK_DEMO__) */ void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ...) { -#if WITH_MEM_STATS - void *temp = NULL; int magic = 0; char *module_name = NULL; + va_list ap; if (size <= 0) { return NULL; } -#if WITH_MEM_STATS_PER_MODULE - - va_list ap; va_start(ap, size); magic = va_arg(ap, int); if (MEM_MAGIC == magic) { module_name = va_arg(ap, char *); } va_end(ap); -#endif temp = LITE_malloc_internal(f, l, size, magic, module_name); if (NULL == temp) { - log_err("allocate %d bytes from %s(%d) failed", size, f, l); + utils_err("allocate %d bytes from %s(%d) failed", size, f, l); return NULL; } @@ -135,27 +224,25 @@ void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ... } return temp; - -#else - return realloc(ptr, size); -#endif } -#if WITH_MEM_STATS_PER_MODULE void *_create_mem_table(char *module_name, struct list_head *list_head) { module_mem_t *pos = NULL; + int len = 0; if (!module_name || !list_head) { return NULL; } - pos = UTILS_malloc(sizeof(module_mem_t)); + pos = HAL_Malloc(sizeof(module_mem_t)); if (!pos) { return NULL; } memset(pos, 0, sizeof(module_mem_t)); - strncpy(pos->mem_statis.module_name, module_name, sizeof(pos->mem_statis.module_name)); + len = strlen(module_name); + memcpy(pos->mem_statis.module_name, module_name, + (len >= sizeof(pos->mem_statis.module_name)) ? (sizeof(pos->mem_statis.module_name) - 1) : len); INIT_LIST_HEAD(&pos->mem_statis.calling_stack.func_head); @@ -193,16 +280,16 @@ int _del_mem_table(char *module_name, struct list_head *list_head) if (calling_stack_pos) { list_del(&calling_stack_pos->func_head); if (calling_stack_pos->func_name) { - UTILS_free(calling_stack_pos->func_name); + HAL_Free(calling_stack_pos->func_name); calling_stack_pos->func_name = NULL; } - UTILS_free(calling_stack_pos); + HAL_Free(calling_stack_pos); calling_stack_pos = NULL; } } list_del(&table_pos->list); - UTILS_free(table_pos); + HAL_Free(table_pos); table_pos = NULL; ret = 0; } @@ -230,7 +317,7 @@ int _count_malloc_internal(const char *f, const int l, OS_malloc_record *os_mall pos = (module_mem_t *)_find_mem_table(module_name, &mem_module_statis); if (!pos) { if (NULL == (pos = (module_mem_t *)_create_mem_table(module_name, &mem_module_statis))) { - log_err("create_mem_table:[%s] failed!", module_name); + utils_err("create_mem_table:[%s] failed!", module_name); return ret; } } @@ -244,13 +331,13 @@ int _count_malloc_internal(const char *f, const int l, OS_malloc_record *os_mall } } if (!is_repeat) { - entry = UTILS_malloc(sizeof(calling_stack_t)); + entry = HAL_Malloc(sizeof(calling_stack_t)); if (!entry) { return ret; } memset(entry, 0, sizeof(calling_stack_t)); - entry->func_name = strdup(f); + entry->func_name = LITE_strdup(f); entry->line = l; list_add(&entry->func_head, &pos->mem_statis.calling_stack.func_head); } @@ -272,14 +359,14 @@ int _count_malloc_internal(const char *f, const int l, OS_malloc_record *os_mall return ret; } -void _count_free_internal(void *ptr, OS_malloc_record *os_malloc_pos) +void _count_free_internal(void *ptr, OS_malloc_record *os_malloc_pos) { module_mem_t *pos = NULL; pos = (module_mem_t *)(os_malloc_pos->mem_table); if (!pos) { - log_err("find mem_table faild"); + utils_err("find mem_table faild"); return; } @@ -288,26 +375,27 @@ void _count_free_internal(void *ptr, OS_malloc_record *os_malloc_pos) pos->mem_statis.bytes_total_freed += os_malloc_pos->buflen; pos->mem_statis.bytes_total_in_use -= os_malloc_pos->buflen; - } -#endif - void *LITE_malloc_internal(const char *f, const int l, int size, ...) { void *ptr = NULL; -#if WITH_MEM_STATS OS_malloc_record *pos; if (size <= 0) { return NULL; } - ptr = UTILS_malloc(size); + ptr = HAL_Malloc(size); if (!ptr) { return NULL; } + if (mutex_mem_stats == NULL) { + mutex_mem_stats = HAL_MutexCreate(); + } + HAL_MutexLock(mutex_mem_stats); + iterations_allocated += 1; bytes_total_allocated += size; bytes_total_in_use += size; @@ -316,8 +404,8 @@ void *LITE_malloc_internal(const char *f, const int l, int size, ...) #if defined(WITH_TOTAL_COST_WARNING) if (bytes_total_in_use > WITH_TOTAL_COST_WARNING) { - log_debug(" "); - log_debug("==== PRETTY HIGH TOTAL IN USE: %d BYTES ====", bytes_total_in_use); + utils_debug(" "); + utils_debug("==== PRETTY HIGH TOTAL IN USE: %d BYTES ====", bytes_total_in_use); LITE_dump_malloc_free_stats(LOG_DEBUG_LEVEL); } #endif @@ -325,9 +413,10 @@ void *LITE_malloc_internal(const char *f, const int l, int size, ...) iterations_in_use += 1; iterations_max_in_use = (iterations_in_use > iterations_max_in_use) ? iterations_in_use : iterations_max_in_use; - pos = UTILS_malloc(sizeof(OS_malloc_record)); + pos = HAL_Malloc(sizeof(OS_malloc_record)); if (NULL == pos) { - UTILS_free(ptr); + HAL_Free(ptr); + HAL_MutexUnlock(mutex_mem_stats); return NULL; } memset(pos, 0, sizeof(OS_malloc_record)); @@ -336,7 +425,7 @@ void *LITE_malloc_internal(const char *f, const int l, int size, ...) pos->buflen = size; pos->func = (char *)f; pos->line = (int)l; -#if defined(_PLATFORM_IS_LINUX_) +#if defined(__UBUNTU_SDK_DEMO__) if (tracking_malloc_callstack) { record_backtrace(&pos->bt_level, &pos->bt_symbols); } @@ -344,23 +433,23 @@ void *LITE_malloc_internal(const char *f, const int l, int size, ...) list_add_tail(&pos->list, &mem_recs); -#if WITH_MEM_STATS_PER_MODULE - va_list ap; - va_start(ap, size); - _count_malloc_internal(f, l, pos, ap); - va_end(ap); -#endif + { + va_list ap; + va_start(ap, size); + _count_malloc_internal(f, l, pos, ap); + va_end(ap); + } #if defined(WITH_ALLOC_WARNING_THRESHOLD) if (size > WITH_ALLOC_WARNING_THRESHOLD) { int k; - log_warning("large allocating @ %s(%d) for %04d bytes!", f, l, size); + log_warning("utils", "large allocating @ %s(%d) for %04d bytes!", f, l, size); LITE_printf("\r\n"); -#if defined(_PLATFORM_IS_LINUX_) +#if defined(__UBUNTU_SDK_DEMO__) for (k = 0; k < pos->bt_level; ++k) { int m; - const char *p = LITE_strchr(pos->bt_symbols[k], '('); + const char *p = strchr(pos->bt_symbols[k], '('); if (p[1] == ')') { continue; @@ -375,47 +464,47 @@ void *LITE_malloc_internal(const char *f, const int l, int size, ...) LITE_printf("\r\n"); } #endif - memset(ptr, 0, size); + HAL_MutexUnlock(mutex_mem_stats); return ptr; -#else - ptr = UTILS_malloc(size); - if (NULL == ptr) { - return NULL; - } - memset(ptr, 0, size); - return ptr; -#endif } void LITE_free_internal(void *ptr) { -#if WITH_MEM_STATS OS_malloc_record *pos; + OS_malloc_record *next; + int found = 0; if (!ptr) { return; } + HAL_MutexLock(mutex_mem_stats); + pos = NULL; - list_for_each_entry(pos, &mem_recs, list, OS_malloc_record) { + list_for_each_entry_safe(pos, next, &mem_recs, list, OS_malloc_record) { if (pos->buf == ptr) { + found = 1; break; } } + if (!found) { + pos = NULL; + } + if (NULL == pos) { - log_warning("Cannot find %p allocated! Skip stat ...", ptr); + log_warning("utils", "Cannot find %p allocated! Skip stat ...", ptr); + + HAL_MutexUnlock(mutex_mem_stats); + return; } else { iterations_freed += 1; iterations_in_use -= 1; bytes_total_freed += pos->buflen; bytes_total_in_use -= pos->buflen; - -#if WITH_MEM_STATS_PER_MODULE _count_free_internal(ptr, pos); -#endif if (pos->buf && pos->buflen > 0) { memset(pos->buf, 0xEE, pos->buflen); @@ -424,17 +513,17 @@ void LITE_free_internal(void *ptr) pos->buflen = 0; pos->func = ""; pos->line = 0; -#if defined(_PLATFORM_IS_LINUX_) +#if defined(__UBUNTU_SDK_DEMO__) pos->bt_level = 0; - UTILS_free(pos->bt_symbols); + HAL_Free(pos->bt_symbols); pos->bt_symbols = 0; #endif list_del(&pos->list); - UTILS_free(pos); + HAL_Free(pos); } -#endif - UTILS_free(ptr); + HAL_MutexUnlock(mutex_mem_stats); + HAL_Free(ptr); } void *LITE_malloc_routine(int size, ...) @@ -442,8 +531,6 @@ void *LITE_malloc_routine(int size, ...) int magic = 0; char *module_name = NULL; -#if WITH_MEM_STATS_PER_MODULE - va_list ap; va_start(ap, size); magic = va_arg(ap, int); @@ -451,7 +538,6 @@ void *LITE_malloc_routine(int size, ...) module_name = va_arg(ap, char *); } va_end(ap); -#endif return LITE_malloc(size, magic, module_name); } @@ -461,8 +547,6 @@ void *LITE_calloc_routine(size_t n, size_t s, ...) int magic = 0; char *module_name = NULL; -#if WITH_MEM_STATS_PER_MODULE - va_list ap; va_start(ap, s); magic = va_arg(ap, int); @@ -470,7 +554,6 @@ void *LITE_calloc_routine(size_t n, size_t s, ...) module_name = va_arg(ap, char *); } va_end(ap); -#endif return LITE_malloc(n * s, magic, module_name);; } @@ -482,48 +565,64 @@ void LITE_free_routine(void *ptr) void LITE_dump_malloc_free_stats(int level) { -#if WITH_MEM_STATS OS_malloc_record *pos; + module_mem_t *module_pos, *tmp; + module_mem_t *unknown_mod = NULL; - if (LITE_log_enabled() && level > LITE_get_loglevel()) { + if (level > LITE_get_loglevel()) { return; } - LITE_printf("\r\n"); - LITE_printf("---------------------------------------------------\r\n"); - LITE_printf(". bytes_total_allocated: %d\r\n", bytes_total_allocated); - LITE_printf(". bytes_total_freed: %d\r\n", bytes_total_freed); - LITE_printf(". bytes_total_in_use: %d\r\n", bytes_total_in_use); - LITE_printf(". bytes_max_allocated: %d\r\n", bytes_max_allocated); - LITE_printf(". bytes_max_in_use: %d\r\n", bytes_max_in_use); - LITE_printf(". iterations_allocated: %d\r\n", iterations_allocated); - LITE_printf(". iterations_freed: %d\r\n", iterations_freed); - LITE_printf(". iterations_in_use: %d\r\n", iterations_in_use); - LITE_printf(". iterations_max_in_use: %d\r\n", iterations_max_in_use); - LITE_printf("---------------------------------------------------\r\n"); - -#if WITH_MEM_STATS_PER_MODULE - - module_mem_t *module_pos, *tmp; - module_mem_t *unknown_mod = NULL; + utils_debug(""); + utils_debug("---------------------------------------------------"); + utils_debug(". bytes_total_allocated: %d", bytes_total_allocated); + utils_debug(". bytes_total_freed: %d", bytes_total_freed); + utils_debug(". bytes_total_in_use: %d", bytes_total_in_use); + utils_warning(". bytes_max_allocated: %d", bytes_max_allocated); + utils_info(". bytes_max_in_use: %d", bytes_max_in_use); + utils_debug(". iterations_allocated: %d", iterations_allocated); + utils_debug(". iterations_freed: %d", iterations_freed); + utils_debug(". iterations_in_use: %d", iterations_in_use); + utils_debug(". iterations_max_in_use: %d", iterations_max_in_use); + utils_debug("---------------------------------------------------"); + utils_debug(""); + + _mem_sort_module_pos(&mem_module_statis); + LITE_printf("\r\n"); + LITE_printf("| | max_in_use | max_allocated | total_allocated | total_free\r\n"); + LITE_printf("|---------------|----------------------|------------------|-----------------------|----------------------\r\n"); list_for_each_entry_safe(module_pos, tmp, &mem_module_statis, list, module_mem_t) { if (module_pos) { - LITE_printf("\x1B[1;32mMODULE_NAME: [%s]\x1B[0m\r\n", module_pos->mem_statis.module_name); - LITE_printf("---------------------------------------------------\r\n"); - LITE_printf(". bytes_total_allocated: %d\r\n", module_pos->mem_statis.bytes_total_allocated); - LITE_printf(". bytes_total_freed: %d\r\n", module_pos->mem_statis.bytes_total_freed); - LITE_printf(". bytes_total_in_use: %d\r\n", module_pos->mem_statis.bytes_total_in_use); - LITE_printf(". bytes_max_allocated: %d\r\n", module_pos->mem_statis.bytes_max_allocated); - LITE_printf(". bytes_max_in_use: %d\r\n", module_pos->mem_statis.bytes_max_in_use); - LITE_printf(". iterations_allocated: %d\r\n", module_pos->mem_statis.iterations_allocated); - LITE_printf(". iterations_freed: %d\r\n", module_pos->mem_statis.iterations_freed); - LITE_printf(". iterations_in_use: %d\r\n", module_pos->mem_statis.iterations_in_use); - LITE_printf(". iterations_max_in_use: %d\r\n", module_pos->mem_statis.iterations_max_in_use); - LITE_printf("---------------------------------------------------\r\n"); + LITE_printf("| %-13s | %6d bytes / %-5d | %6d bytes | %6d bytes / %-5d | %6d bytes / %-5d \r\n", + module_pos->mem_statis.module_name, + module_pos->mem_statis.bytes_max_in_use, + module_pos->mem_statis.iterations_max_in_use, + module_pos->mem_statis.bytes_max_allocated, + module_pos->mem_statis.bytes_total_allocated, + module_pos->mem_statis.iterations_allocated, + module_pos->mem_statis.bytes_total_freed, + module_pos->mem_statis.iterations_freed + ); + /* + LITE_printf("\x1B[1;32mMODULE_NAME: [%s]\x1B[0m\r\n", module_pos->mem_statis.module_name); + LITE_printf("---------------------------------------------------\r\n"); + LITE_printf(". bytes_total_allocated: %d\r\n", module_pos->mem_statis.bytes_total_allocated); + LITE_printf(". bytes_total_freed: %d\r\n", module_pos->mem_statis.bytes_total_freed); + LITE_printf(". bytes_total_in_use: %d\r\n", module_pos->mem_statis.bytes_total_in_use); + LITE_printf(". bytes_max_allocated: %d\r\n", module_pos->mem_statis.bytes_max_allocated); + LITE_printf(". bytes_max_in_use: %d\r\n", module_pos->mem_statis.bytes_max_in_use); + LITE_printf(". iterations_allocated: %d\r\n", module_pos->mem_statis.iterations_allocated); + LITE_printf(". iterations_freed: %d\r\n", module_pos->mem_statis.iterations_freed); + LITE_printf(". iterations_in_use: %d\r\n", module_pos->mem_statis.iterations_in_use); + LITE_printf(". iterations_max_in_use: %d\r\n", module_pos->mem_statis.iterations_max_in_use); + LITE_printf("---------------------------------------------------\r\n"); + */ if (!strcmp(module_pos->mem_statis.module_name, "unknown")) { unknown_mod = module_pos; + } else { + HAL_Free(module_pos->mem_statis.calling_stack.func_name); } } } @@ -537,14 +636,24 @@ void LITE_dump_malloc_free_stats(int level) list_for_each_entry_safe(call_pos, tmp, &unknown_mod->mem_statis.calling_stack.func_head, func_head, calling_stack_t) { if (call_pos->func_name) { LITE_printf(". \x1B[1;31m%s \x1B[0m Ln:%d\r\n", call_pos->func_name, call_pos->line); + + /* free memery of func_name and calling_stack */ + HAL_Free(call_pos->func_name); + list_del(&call_pos->func_head); + HAL_Free(call_pos); } } LITE_printf("\r\n"); } -#endif + list_for_each_entry_safe(module_pos, tmp, &mem_module_statis, list, module_mem_t) { + list_del(&module_pos->list); + HAL_Free(module_pos); + } + + LITE_printf("\r\n"); - if (!LITE_log_enabled() || LITE_get_loglevel() == level) { + if (LITE_get_loglevel() == level) { int j; int cnt = 0; @@ -567,33 +676,36 @@ void LITE_dump_malloc_free_stats(int level) } LITE_printf("]\r\n"); -#if defined(_PLATFORM_IS_LINUX_) - int k; - - LITE_printf("\r\n"); - for (k = 0; k < pos->bt_level; ++k) { - int m; - const char *p = strchr(pos->bt_symbols[k], '('); - - if (p[1] == ')') { - continue; +#if defined(__UBUNTU_SDK_DEMO__) + { + int k; + LITE_printf("\r\n"); + for (k = 0; k < pos->bt_level; ++k) { + int m; + const char *p = strchr(pos->bt_symbols[k], '('); + + if (p[1] == ')') { + continue; + } + LITE_printf(" "); + for (m = 0; m < k; ++m) { + LITE_printf(" "); + } + + LITE_printf("%s\r\n", p); } - LITE_printf(" "); - for (m = 0; m < k; ++m) { - LITE_printf(" "); - } - - LITE_printf("%s\r\n", p); } #endif LITE_printf("\r\n"); } } } -#else - log_err("WITH_MEM_STATS = %d", WITH_MEM_STATS); -#endif /* #if WITH_MEM_STATS */ return; } +void **LITE_get_mem_mutex(void) +{ + return &mutex_mem_stats; +} +#endif diff --git a/iotkit-embedded/src/infra/infra_mem_stats.h b/iotkit-embedded/src/infra/infra_mem_stats.h new file mode 100644 index 0000000..60adc1e --- /dev/null +++ b/iotkit-embedded/src/infra/infra_mem_stats.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __MEM_STATS_H__ +#define __MEM_STATS_H__ + +#include "infra_list.h" +#include "infra_log.h" + +#if defined(__UBUNTU_SDK_DEMO__) + #include +#endif + +typedef struct { + void *buf; + int buflen; + char *func; + int line; +#if defined(_PLATFORM_IS_LINUX_) + char **bt_symbols; + int bt_level; +#endif + list_head_t list; + void *mem_table; +} OS_malloc_record; + + +#define MEM_MAGIC (0x1234) + +#define LITE_calloc(num, size, ...) LITE_malloc_internal(__func__, __LINE__, (num * size), ##__VA_ARGS__) +#define LITE_malloc(size, ...) LITE_malloc_internal(__func__, __LINE__, size, ##__VA_ARGS__) +#define LITE_realloc(ptr, size, ...) LITE_realloc_internal(__func__, __LINE__, ptr, size, ##__VA_ARGS__) +#define LITE_free(ptr) \ + do { \ + if (!ptr) { \ + log_warning("utils", "%s == NULL! LITE_free(%s) aborted.", #ptr, #ptr); \ + break; \ + } \ + \ + LITE_free_internal((void *)ptr); \ + ptr = NULL; \ + } while(0) + +void *LITE_malloc_internal(const char *f, const int l, int size, ...); +void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ...); +void LITE_free_internal(void *ptr); +void LITE_dump_malloc_free_stats(int level); +void **LITE_get_mem_mutex(void); + +#endif /* __MEM_STATS_H__ */ + diff --git a/iotkit-embedded/src/infra/infra_net.c b/iotkit-embedded/src/infra/infra_net.c new file mode 100644 index 0000000..85556f0 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_net.c @@ -0,0 +1,328 @@ +/* + * 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) +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_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 ssl_hooks_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; + } + +#ifdef INFRA_MEM_STATS + memset(&ssl_hooks, 0, sizeof(ssl_hooks_t)); + ssl_hooks.malloc = ssl_malloc; + ssl_hooks.free = ssl_free; + + ssl_hooks_set(&ssl_hooks); +#else + (void)ssl_hooks; +#endif + + if (0 != (pNetwork->handle = (intptr_t)HAL_SSL_Establish( + pNetwork->pHostAddress, + pNetwork->port, + pNetwork->ca_crt, + pNetwork->ca_crt_len + 1))) { + return 0; + } + 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) { + ret = read_tcp(pNetwork, buffer, len, timeout_ms); + } +#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) { + ret = write_tcp(pNetwork, buffer, len, timeout_ms); + } +#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) { + ret = disconnect_tcp(pNetwork); + } +#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) { + ret = connect_tcp(pNetwork); + } +#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; +} +#endif + + diff --git a/iotkit-embedded/src/utils/misc/utils_net.h b/iotkit-embedded/src/infra/infra_net.h similarity index 63% rename from iotkit-embedded/src/utils/misc/utils_net.h rename to iotkit-embedded/src/infra/infra_net.h index 6223149..be83c51 100644 --- a/iotkit-embedded/src/utils/misc/utils_net.h +++ b/iotkit-embedded/src/infra/infra_net.h @@ -1,28 +1,11 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#ifndef _INFRA_NET_H_ +#define _INFRA_NET_H_ - -#ifndef _IOTX_COMMON_NET_H_ -#define _IOTX_COMMON_NET_H_ - -#include "iot_import.h" - +#include "infra_types.h" /** * @brief The structure of network connection(TCP or SSL). @@ -57,11 +40,12 @@ struct utils_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, char *product_key); +int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt); #endif /* IOTX_COMMON_NET_H */ + + diff --git a/iotkit-embedded/src/infra/infra_preauth.c b/iotkit-embedded/src/infra/infra_preauth.c new file mode 100644 index 0000000..e372452 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_preauth.c @@ -0,0 +1,231 @@ +/* + * 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" + +#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_pre_auth_output_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_pre_auth_output_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/iotkit-embedded/src/infra/infra_preauth.h b/iotkit-embedded/src/infra/infra_preauth.h new file mode 100644 index 0000000..e21b029 --- /dev/null +++ b/iotkit-embedded/src/infra/infra_preauth.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __INFRA_PREAUTH__ +#define __INFRA_PREAUTH__ + +#include "infra_defs.h" +#include "infra_types.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 + +#define PRE_AUTH_HOSTNAME_MAXLEN (64) +#define PRE_AUTH_CLIENT_ID_MAXLEN (200) +#define PRE_AUTH_USERNAME_MAXLEN (64) +#define PRE_AUTH_PASSWORD_MAXLEN (65) + +typedef struct { + char hostname[PRE_AUTH_HOSTNAME_MAXLEN]; + uint16_t port; + char clientid[PRE_AUTH_CLIENT_ID_MAXLEN]; + char username[PRE_AUTH_USERNAME_MAXLEN]; + char password[PRE_AUTH_PASSWORD_MAXLEN]; +} iotx_pre_auth_output_t; + +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_pre_auth_output_t *preauth_output); + +#endif /* #ifndef __INFRA_PREAUTH__ */ \ No newline at end of file diff --git a/iotkit-embedded/src/infra/infra_prt_nwk_payload.c b/iotkit-embedded/src/infra/infra_prt_nwk_payload.c new file mode 100644 index 0000000..97c0bf9 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_report.c b/iotkit-embedded/src/infra/infra_report.c new file mode 100644 index 0000000..a989ae9 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_report.h b/iotkit-embedded/src/infra/infra_report.h new file mode 100644 index 0000000..8947fea --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_sha1.c b/iotkit-embedded/src/infra/infra_sha1.c new file mode 100644 index 0000000..eecb1a8 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/utils/digest/utils_sha1.h b/iotkit-embedded/src/infra/infra_sha1.h similarity index 67% rename from iotkit-embedded/src/utils/digest/utils_sha1.h rename to iotkit-embedded/src/infra/infra_sha1.h index 5a319ac..c3fd35d 100644 --- a/iotkit-embedded/src/utils/digest/utils_sha1.h +++ b/iotkit-embedded/src/infra/infra_sha1.h @@ -1,27 +1,16 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ -#ifndef _IOTX_COMMON_SHA1_H_ -#define _IOTX_COMMON_SHA1_H_ -#include "iot_import.h" +#ifndef _INFRA_SHA1_H_ +#define _INFRA_SHA1_H_ + +#include "infra_types.h" + +#define SHA1_DIGEST_SIZE (20) /** * \brief SHA-1 context structure @@ -69,7 +58,7 @@ void utils_sha1_starts(iot_sha1_context *ctx); * \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, size_t ilen); +void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen); /** * \brief SHA-1 final digest @@ -89,6 +78,9 @@ void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]); * \param ilen length of the input data * \param output SHA-1 checksum result */ -void utils_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]); +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/iotkit-embedded/src/infra/infra_sha256.c b/iotkit-embedded/src/infra/infra_sha256.c new file mode 100644 index 0000000..f8cd83a --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/utils/digest/utils_sha256.h b/iotkit-embedded/src/infra/infra_sha256.h similarity index 55% rename from iotkit-embedded/src/utils/digest/utils_sha256.h rename to iotkit-embedded/src/infra/infra_sha256.h index e936fe9..7fc337d 100644 --- a/iotkit-embedded/src/utils/digest/utils_sha256.h +++ b/iotkit-embedded/src/infra/infra_sha256.h @@ -1,25 +1,27 @@ /* - * utils_sha256.h - * - * Created on: 2018��1��17�� - * Author: wb-jn347227 + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ #ifndef _IOTX_COMMON_SHA256_H_ #define _IOTX_COMMON_SHA256_H_ -#include "iot_import.h" +#include -#define SHA256_BLOCK_LENGTH 64 -#define SHA256_DIGEST_LENGTH 32 -#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#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) -#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +/** + * \brief SHA-256 context structure + */ typedef struct { - uint32_t state[8]; - uint64_t bitcount; - unsigned char buffer[SHA256_BLOCK_LENGTH]; + 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; @@ -39,14 +41,6 @@ void utils_sha256_init(iot_sha256_context *ctx); */ void utils_sha256_free(iot_sha256_context *ctx); -/** - * \brief Clone (the state of) a SHA-256 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void utils_sha256_clone(iot_sha256_context *dst, - const iot_sha256_context *src); /** * \brief SHA-256 context setup @@ -62,7 +56,7 @@ void utils_sha256_starts(iot_sha256_context *ctx); * \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, size_t ilen); +void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen); /** * \brief SHA-256 final digest @@ -70,10 +64,10 @@ void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, si * \param ctx SHA-256 context * \param output SHA-256 checksum result */ -void utils_sha256_finish(iot_sha256_context *ctx, unsigned char output[32]); +void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32]); /* Internal use */ -void utils_sha256_process(iot_sha256_context *ctx, const uint32_t *data); +void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64]); /** * \brief Output = SHA-256( input buffer ) @@ -82,6 +76,10 @@ void utils_sha256_process(iot_sha256_context *ctx, const uint32_t *data); * \param ilen length of the input data * \param output SHA-256 checksum result */ -void utils_sha256(const unsigned char *input, size_t ilen, unsigned char output[32]); +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/iotkit-embedded/src/infra/infra_string.c b/iotkit-embedded/src/infra/infra_string.c new file mode 100644 index 0000000..2b65d56 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_string.h b/iotkit-embedded/src/infra/infra_string.h new file mode 100644 index 0000000..5026b2d --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/utils/misc/utils_timer.c b/iotkit-embedded/src/infra/infra_timer.c similarity index 65% rename from iotkit-embedded/src/utils/misc/utils_timer.c rename to iotkit-embedded/src/infra/infra_timer.c index e75db8e..f1996cf 100644 --- a/iotkit-embedded/src/utils/misc/utils_timer.c +++ b/iotkit-embedded/src/infra/infra_timer.c @@ -1,26 +1,13 @@ +#include "infra_config.h" + +#ifdef INFRA_TIMER /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#include "infra_types.h" +#include "infra_timer.h" - - -#include "iot_import.h" -#include "utils_timer.h" - +uint64_t HAL_UptimeMs(void); void iotx_time_start(iotx_time_t *timer) { @@ -104,4 +91,5 @@ uint32_t utils_time_get_ms(void) { return HAL_UptimeMs(); } +#endif diff --git a/iotkit-embedded/src/infra/infra_timer.h b/iotkit-embedded/src/infra/infra_timer.h new file mode 100644 index 0000000..e018aab --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/infra_types.h b/iotkit-embedded/src/infra/infra_types.h new file mode 100644 index 0000000..7037296 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/infra/iot.mk b/iotkit-embedded/src/infra/iot.mk new file mode 100644 index 0000000..41e4cca --- /dev/null +++ b/iotkit-embedded/src/infra/iot.mk @@ -0,0 +1 @@ +LIBA_TARGET := libiot_infra.a diff --git a/iotkit-embedded/src/log/LITE-log/lite-log.h b/iotkit-embedded/src/log/LITE-log/lite-log.h deleted file mode 100644 index 35d229c..0000000 --- a/iotkit-embedded/src/log/LITE-log/lite-log.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __LITE_LOG_H__ -#define __LITE_LOG_H__ -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "lite-log_config.h" - -typedef enum _LOGLEVEL { - LOG_EMERG_LEVEL = 0, /* OS system is unavailable */ - LOG_CRIT_LEVEL, /* current application aborting */ - LOG_ERR_LEVEL, /* current app-module error */ - LOG_WARNING_LEVEL, /* using default parameters */ - LOG_INFO_LEVEL, /* running messages */ - LOG_DEBUG_LEVEL, /* debugging messages */ -} LOGLEVEL; - -void LITE_openlog(const char *ident); -void LITE_closelog(void); -int LITE_log_enabled(void); -char *LITE_get_logname(void); -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(const char *f, const int l, const int level, const char *fmt, va_list* params); -void LITE_syslog(const char *f, const int l, const int level, const char *fmt, ...); - -#define log_emerg(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_EMERG_LEVEL, __VA_ARGS__) -#define log_crit(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_CRIT_LEVEL, __VA_ARGS__) -#define log_err(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_ERR_LEVEL, __VA_ARGS__) -#define log_warning(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_WARNING_LEVEL, __VA_ARGS__) -#define log_info(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_INFO_LEVEL, __VA_ARGS__) -#define log_debug(...) LITE_syslog(__FUNCTION__, __LINE__, LOG_DEBUG_LEVEL, __VA_ARGS__) - -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 - ); - -#if defined(__GLIBC__) -#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) -#else -#define HEXDUMP_DEBUG(buf, len) \ - LITE_rich_hexdump(__func__, __LINE__, LOG_DEBUG_LEVEL, #buf, buf, len) - -#define HEXDUMP_INFO(buf, len) \ - LITE_rich_hexdump(__func__, __LINE__, LOG_INFO_LEVEL, #buf, buf, len) -#endif - -#if defined(__cplusplus) -} -#endif -#endif /* __LITE_LOG_H__ */ diff --git a/iotkit-embedded/src/log/LITE-log/lite-log_config.h b/iotkit-embedded/src/log/LITE-log/lite-log_config.h deleted file mode 100644 index b84cc67..0000000 --- a/iotkit-embedded/src/log/LITE-log/lite-log_config.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __LITE_LOG_CONFIG_H__ -#define __LITE_LOG_CONFIG_H__ - -#define LITE_printf printf -#define LITE_sprintf sprintf -#define LITE_snprintf snprintf -#define LITE_vsnprintf 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 - -#endif /* __LITE_LOG_CONFIG_H__ */ - diff --git a/iotkit-embedded/src/log/LITE-log/lite-log_internal.h b/iotkit-embedded/src/log/LITE-log/lite-log_internal.h deleted file mode 100644 index c159dfa..0000000 --- a/iotkit-embedded/src/log/LITE-log/lite-log_internal.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifndef __LITE_LOG_INTERNAL_H__ -#define __LITE_LOG_INTERNAL_H__ - -#include -#include -#include - -#include "lite-log.h" -#include "lite-log_config.h" - -typedef struct { - char name[LOG_MOD_NAME_LEN + 1]; - int priority; - char text_buf[LOG_MSG_MAXLEN + 1]; -} log_client; - -#endif /* __LITE_LOG_INTERNAL_H__ */ diff --git a/iotkit-embedded/src/log/iot.mk b/iotkit-embedded/src/log/iot.mk deleted file mode 100644 index 3de2bd7..0000000 --- a/iotkit-embedded/src/log/iot.mk +++ /dev/null @@ -1,6 +0,0 @@ -LIBA_TARGET := libiot_log.a -HDR_REFS := src/sdk-impl - -LIB_HEADERS := $(wildcard */*.h) -PKG_SOURCE := LITE-log.git -PKG_UPSTREAM := git@gitlab.alibaba-inc.com:iot-middleware/LITE-log.git diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTConnect.h b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTConnect.h deleted file mode 100644 index 0d8465d..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTConnect.h +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#ifndef MQTTCONNECT_H_ -#define MQTTCONNECT_H_ - -#if !defined(DLLImport) - #define DLLImport -#endif -#if !defined(DLLExport) - #define DLLExport -#endif - - -typedef union -{ - unsigned char all; /**< all connect flags */ -#if defined(REVERSED) - struct - { - unsigned int username : 1; /**< 3.1 user name */ - unsigned int password : 1; /**< 3.1 password */ - unsigned int willRetain : 1; /**< will retain setting */ - unsigned int willQoS : 2; /**< will QoS value */ - unsigned int will : 1; /**< will flag */ - unsigned int cleansession : 1; /**< clean session flag */ - unsigned int : 1; /**< unused */ - } bits; -#else - struct - { - unsigned int : 1; /**< unused */ - unsigned int cleansession : 1; /**< cleansession flag */ - unsigned int will : 1; /**< will flag */ - unsigned int willQoS : 2; /**< will QoS value */ - unsigned int willRetain : 1; /**< will retain setting */ - unsigned int password : 1; /**< 3.1 password */ - unsigned int username : 1; /**< 3.1 user name */ - } bits; -#endif -} 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 defined(REVERSED) - 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 KEEP_ALIVE_INTERVAL_DEFAULT_MIN 60 -#define KEEP_ALIVE_INTERVAL_DEFAULT_MAX 180 - - -#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, KEEP_ALIVE_INTERVAL_DEFAULT_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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTConnectClient.c b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTConnectClient.c deleted file mode 100644 index 371553e..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTConnectClient.c +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#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; - header.bits.type = 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.bits.cleansession = options->cleansession; - flags.bits.will = (options->willFlag) ? 1 : 0; - if (flags.bits.will) - { - flags.bits.willQoS = options->will.qos; - flags.bits.willRetain = options->will.retained; - } - - if (options->username.cstring || options->username.lenstring.data) - flags.bits.username = 1; - if (options->password.cstring || options->password.lenstring.data) - flags.bits.password = 1; - - 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.bits.username) - writeMQTTString(&ptr, options->username); - if (flags.bits.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 (header.bits.type != 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; - header.bits.type = 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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTDeserializePublish.c b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTDeserializePublish.c deleted file mode 100644 index 59aff4d..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTDeserializePublish.c +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#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 (header.bits.type != PUBLISH) - goto exit; - *dup = header.bits.dup; - *qos = header.bits.qos; - *retained = header.bits.retain; - - 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 = header.bits.dup; - *packettype = header.bits.type; - - 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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPacket.c b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPacket.c deleted file mode 100644 index 8ede736..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPacket.c +++ /dev/null @@ -1,401 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Sergio R. Caprile - non-blocking packet read functions for stream transport - *******************************************************************************/ - -#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 (a->cstring) - { - aptr = a->cstring; - alen = strlen(a->cstring); - } - else - { - aptr = a->lenstring.data; - alen = a->lenstring.len; - } - blen = strlen(bptr); - - return (alen == blen) && (strncmp(aptr, bptr, alen) == 0); -} - - -/** - * Helper function to read packet data from some source into a buffer - * @param buf the buffer into which the packet will be serialized - * @param buflen the length in bytes of the supplied buffer - * @param getfn pointer to a function which will read any number of bytes from the needed source - * @return integer MQTT packet type, or -1 on error - * @note the whole message must fit into the caller's buffer - */ -int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)) -{ - int rc = -1; - MQTTHeader header = {0}; - int len = 0; - int rem_len = 0; - - /* 1. read the header byte. This has the packet type in it */ - if ((*getfn)(buf, 1) != 1) - goto exit; - - len = 1; - /* 2. read the remaining length. This is variable in itself */ - MQTTPacket_decode(getfn, &rem_len); - len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */ - - /* 3. read the rest of the buffer using a callback to supply the rest of the data */ - if((rem_len + len) > buflen) - goto exit; - if ((*getfn)(buf + len, rem_len) != rem_len) - goto exit; - - header.byte = buf[0]; - rc = header.bits.type; -exit: - return rc; -} - -/** - * Decodes the message length according to the MQTT algorithm, non-blocking - * @param trp pointer to a transport structure holding what is needed to solve getting data from it - * @param value the decoded length returned - * @return integer the number of bytes read from the socket, 0 for call again, or -1 on error - */ -static int MQTTPacket_decodenb(MQTTTransport *trp) -{ - unsigned char c; - int rc = MQTTPACKET_READ_ERROR; - - if(trp->len == 0){ /* initialize on first call */ - trp->multiplier = 1; - trp->rem_len = 0; - } - do { - int frc; - if (++(trp->len) > MAX_NO_OF_REMAINING_LENGTH_BYTES) - goto exit; - if ((frc=(*trp->getfn)(trp->sck, &c, 1)) == -1) - goto exit; - if (frc == 0){ - rc = 0; - goto exit; - } - trp->rem_len += (c & 127) * trp->multiplier; - trp->multiplier *= 128; - } while ((c & 128) != 0); - rc = trp->len; -exit: - return rc; -} - -/** - * Helper function to read packet data from some source into a buffer, non-blocking - * @param buf the buffer into which the packet will be serialized - * @param buflen the length in bytes of the supplied buffer - * @param trp pointer to a transport structure holding what is needed to solve getting data from it - * @return integer MQTT packet type, 0 for call again, or -1 on error - * @note the whole message must fit into the caller's buffer - */ -int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp) -{ - int rc = -1, frc; - MQTTHeader header = {0}; - - switch(trp->state){ - default: - trp->state = 0; - /*FALLTHROUGH*/ - case 0: - /* read the header byte. This has the packet type in it */ - if ((frc=(*trp->getfn)(trp->sck, buf, 1)) == -1) - goto exit; - if (frc == 0) - return 0; - trp->len = 0; - ++trp->state; - /*FALLTHROUGH*/ - /* read the remaining length. This is variable in itself */ - case 1: - if((frc=MQTTPacket_decodenb(trp)) == MQTTPACKET_READ_ERROR) - goto exit; - if(frc == 0) - return 0; - trp->len = 1 + MQTTPacket_encode(buf + 1, trp->rem_len); /* put the original remaining length back into the buffer */ - if((trp->rem_len + trp->len) > buflen) - goto exit; - ++trp->state; - /*FALLTHROUGH*/ - case 2: - /* read the rest of the buffer using a callback to supply the rest of the data */ - if ((frc=(*trp->getfn)(trp->sck, buf + trp->len, trp->rem_len)) == -1) - goto exit; - if (frc == 0) - return 0; - trp->rem_len -= frc; - trp->len += frc; - if(trp->rem_len) - return 0; - - header.byte = buf[0]; - rc = header.bits.type; - break; - } - -exit: - trp->state = 0; - return rc; -} - diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPacket.h b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPacket.h deleted file mode 100644 index 1c7efbb..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPacket.h +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#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 -}; - -/** - * Bitfields for the MQTT header byte. - */ -typedef union -{ - unsigned char byte; /**< the whole byte */ -#if defined(REVERSED) - struct - { - unsigned int type : 4; /**< message type nibble */ - unsigned int dup : 1; /**< DUP flag bit */ - unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ - unsigned int retain : 1; /**< retained flag bit */ - } bits; -#else - struct - { - unsigned int retain : 1; /**< retained flag bit */ - unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ - unsigned int dup : 1; /**< DUP flag bit */ - unsigned int type : 4; /**< message type nibble */ - } bits; -#endif -} 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); - -DLLExport int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)); - -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; - -int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp); - -#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */ -} -#endif - - -#endif /* MQTTPACKET_H_ */ diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPublish.h b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPublish.h deleted file mode 100644 index ebe479d..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTPublish.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSerializePublish.c b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSerializePublish.c deleted file mode 100644 index 0764830..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSerializePublish.c +++ /dev/null @@ -1,164 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144 - *******************************************************************************/ - -#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; - } - - header.bits.type = PUBLISH; - header.bits.dup = dup; - header.bits.qos = qos; - header.bits.retain = 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; - } - header.bits.type = packettype; - header.bits.dup = dup; - header.bits.qos = (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); -} - - -/** - * 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); -} - - diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSubscribe.h b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSubscribe.h deleted file mode 100644 index aa91826..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSubscribe.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSubscribeClient.c b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSubscribeClient.c deleted file mode 100644 index e6e55c9..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTSubscribeClient.c +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#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; - header.bits.type = SUBSCRIBE; - header.bits.dup = dup; - header.bits.qos = 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 (header.bits.type != 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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTUnsubscribe.h b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTUnsubscribe.h deleted file mode 100644 index 355ca9a..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTUnsubscribe.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#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/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTUnsubscribeClient.c b/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTUnsubscribeClient.c deleted file mode 100644 index 6dfee7b..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/MQTTPacket/MQTTUnsubscribeClient.c +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#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; - header.bits.type = UNSUBSCRIBE; - header.bits.dup = dup; - header.bits.qos = 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/iotkit-embedded/src/mqtt/Link-MQTT/iot_export_mqtt.h b/iotkit-embedded/src/mqtt/Link-MQTT/iot_export_mqtt.h deleted file mode 100644 index 7721978..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/iot_export_mqtt.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _IOT_EXPORT_MQTT_H_ -#define _IOT_EXPORT_MQTT_H_ - -/* From mqtt_client.h */ -typedef enum { - IOTX_MQTT_QOS0 = 0, - IOTX_MQTT_QOS1, - IOTX_MQTT_QOS2 -} 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_RECVEIVED = 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; - uint16_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_RECVEIVED: - * Its data type is @iotx_mqtt_packet_info_t 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 */ - - char *pwrite_buf; /* Specify write-buffer */ - uint32_t write_buf_size; /* Specify size of write-buffer in byte */ - char *pread_buf; /* Specify read-buffer */ - 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; - -/** @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 Construct the MQTT client by ID2 - * This function initialize the data structures, establish MQTT connection. - * And set mqtt up/down process functions. - * - * @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_ConstructSecure(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 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); -/* From mqtt_client.h */ -/** @} */ /* end of api_mqtt */ - -/** @} */ /* end of api */ - -#endif diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_client.c b/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_client.c deleted file mode 100644 index 27f79a0..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_client.c +++ /dev/null @@ -1,2482 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include "iot_import.h" -#include "iot_export.h" -#include "lite-system.h" -#include "lite-log.h" -#include "lite-utils.h" -#include "utils_net.h" -#include "utils_hmac.h" -#include "utils_list.h" -#include "utils_timer.h" -#include "sdk-impl_internal.h" - -#include "MQTTPacket/MQTTPacket.h" -#include "mqtt_client.h" -#ifdef MQTT_ID2_AUTH - #ifdef MQTT_ID2_CRYPTO - #include "id2_crypto.h" - #endif -#endif - -static int iotx_mc_send_packet(iotx_mc_client_t *c, char *buf, int length, iotx_time_t *timer); -static iotx_mc_state_t iotx_mc_get_client_state(iotx_mc_client_t *pClient); -static void iotx_mc_set_client_state(iotx_mc_client_t *pClient, iotx_mc_state_t newState); -static int iotx_mc_keepalive_sub(iotx_mc_client_t *pClient); -static void iotx_mc_disconnect_callback(iotx_mc_client_t *pClient) ; -static int iotx_mc_check_state_normal(iotx_mc_client_t *c); -static int iotx_mc_handle_reconnect(iotx_mc_client_t *pClient); -static void iotx_mc_reconnect_callback(iotx_mc_client_t *pClient); -static int iotx_mc_push_pubInfo_to(iotx_mc_client_t *c, int len, unsigned short msgId, list_node_t **node); -static int iotx_mc_push_subInfo_to(iotx_mc_client_t *c, int len, unsigned short msgId, enum msgTypes type, - iotx_mc_topic_handle_t *handler, - list_node_t **node); -static int iotx_mc_check_handle_is_identical(iotx_mc_topic_handle_t *messageHandlers1, - iotx_mc_topic_handle_t *messageHandler2); - - -/* check rule whether is valid or not */ -static int iotx_mc_check_rule(char *iterm, iotx_mc_topic_type_t type) -{ - int i = 0; - int len = 0; - - if (NULL == iterm) { - log_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) { - log_err("the character # and + is error"); - return FAIL_RETURN; - } - } - } else { - if ('+' == iterm[i] || '#' == iterm[i]) { - log_err("has character # and + is error"); - return FAIL_RETURN; - } - } - - if (iterm[i] < 32 || iterm[i] >= 127) { - return FAIL_RETURN; - } - } - return SUCCESS_RETURN; -} - - -/* Check topic name */ -/* 0, topic name is valid; NOT 0, topic name is invalid */ -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[IOTX_MC_TOPIC_NAME_MAX_LEN]; - if (NULL == topicName || '/' != topicName[0]) { - return FAIL_RETURN; - } - - if (strlen(topicName) > IOTX_MC_TOPIC_NAME_MAX_LEN) { - log_err("len of topicName exceeds 64"); - return FAIL_RETURN; - } - - memset(topicString, 0x0, IOTX_MC_TOPIC_NAME_MAX_LEN); - strncpy(topicString, topicName, IOTX_MC_TOPIC_NAME_MAX_LEN - 1); - - iterm = strtok(topicString, delim); - - if (SUCCESS_RETURN != iotx_mc_check_rule(iterm, type)) { - log_err("run iotx_check_rule error"); - return FAIL_RETURN; - } - - for (;;) { - iterm = strtok(NULL, delim); - - if (iterm == NULL) { - break; - } - - /* The character '#' is not in the last */ - if (1 == mask) { - log_err("the character # is error"); - return FAIL_RETURN; - } - - if (SUCCESS_RETURN != iotx_mc_check_rule(iterm, type)) { - log_err("run iotx_check_rule error"); - return FAIL_RETURN; - } - - if (iterm[0] == '#') { - mask = 1; - } - } - - return SUCCESS_RETURN; -} - - -/* Send keepalive packet */ -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); - len = MQTTSerialize_pingreq((unsigned char *)pClient->buf_send, pClient->buf_size_send); - if (len <= 0) { - HAL_MutexUnlock(pClient->lock_write_buf); - log_err("Serialize ping request is error"); - return MQTT_PING_PACKET_ERROR; - } - - rc = iotx_mc_send_packet(pClient, pClient->buf_send, len, &timer); - if (SUCCESS_RETURN != rc) { - HAL_MutexUnlock(pClient->lock_write_buf); - /* ping outstanding, then close socket unsubscribe topic and handle callback function */ - log_err("ping outstanding is error,result = %d", rc); - return MQTT_NETWORK_ERROR; - } - HAL_MutexUnlock(pClient->lock_write_buf); - - return SUCCESS_RETURN; -} - - -/* MQTT send connect packet */ -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); - if ((len = MQTTSerialize_connect((unsigned char *)pClient->buf_send, pClient->buf_size_send, pConnectParams)) <= 0) { - HAL_MutexUnlock(pClient->lock_write_buf); - log_err("Serialize connect packet failed,len = %d", len); - 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) { - HAL_MutexUnlock(pClient->lock_write_buf); - log_err("send connect packet failed"); - return MQTT_NETWORK_ERROR; - } - HAL_MutexUnlock(pClient->lock_write_buf); - - return SUCCESS_RETURN; -} - - -/* MQTT send publish packet */ -int MQTTPublish(iotx_mc_client_t *c, const char *topicName, iotx_mqtt_topic_info_pt topic_msg) - -{ - list_node_t *node = NULL; - iotx_time_t timer; - MQTTString topic = MQTTString_initializer; - int len = 0; - - 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_write_buf); - 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) { - HAL_MutexUnlock(c->lock_write_buf); - log_err("MQTTSerialize_publish is error, len=%d, buf_size=%u, payloadlen=%u", - len, - c->buf_size_send, - topic_msg->payload_len); - return MQTT_PUBLISH_PACKET_ERROR; - } - - - /* 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)) { - log_err("push publish into to pubInfolist failed!"); - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_PUSH_TO_LIST_ERROR; - } - } - - /* send the publish packet */ - if (iotx_mc_send_packet(c, c->buf_send, len, &timer) != SUCCESS_RETURN) { - if (topic_msg->qos > IOTX_MQTT_QOS0) { - /* If failed, remove from list */ - HAL_MutexLock(c->lock_list_pub); - list_remove(c->list_pub_wait_ack, node); - HAL_MutexUnlock(c->lock_list_pub); - } - - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_NETWORK_ERROR; - } - - HAL_MutexUnlock(c->lock_write_buf); - return SUCCESS_RETURN; -} - - -/* MQTT send publish ACK */ -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) { - len = MQTTSerialize_ack((unsigned char *)c->buf_send, c->buf_size_send, PUBACK, 0, msgId); - } else if (type == PUBREC) { - len = MQTTSerialize_ack((unsigned char *)c->buf_send, c->buf_size_send, PUBREC, 0, msgId); - } else if (type == PUBREL) { - len = MQTTSerialize_ack((unsigned char *)c->buf_send, c->buf_size_send, PUBREL, 0, msgId); - } else { - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_PUBLISH_ACK_TYPE_ERROR; - } - - if (len <= 0) { - 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) { - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_NETWORK_ERROR; - } - - HAL_MutexUnlock(c->lock_write_buf); - return SUCCESS_RETURN; -} - - -/* MQTT send subscribe packet */ -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; - int qos_sub = (int)qos; - iotx_time_t timer; - MQTTString topic = MQTTString_initializer; - iotx_mc_topic_handle_t handler = {topicFilter, {messageHandler, pcontext}}; - - list_node_t *node = NULL; - - if (!c || !topicFilter || !messageHandler) { - return FAIL_RETURN; - } - - topic.cstring = (char *)topicFilter; - iotx_time_init(&timer); - utils_time_countdown_ms(&timer, c->request_timeout_ms); - - HAL_MutexLock(c->lock_write_buf); - - len = MQTTSerialize_subscribe((unsigned char *)c->buf_send, c->buf_size_send, 0, (unsigned short)msgId, 1, &topic, - (int *)&qos_sub); - if (len <= 0) { - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_SUBSCRIBE_PACKET_ERROR; - } - - - - /* - * NOTE: It prefer to push the element into list and then remove it when send failed, - * because some of extreme cases - * */ - - /* push the element to list of wait subscribe ACK */ - if (SUCCESS_RETURN != iotx_mc_push_subInfo_to(c, len, msgId, SUBSCRIBE, &handler, &node)) { - log_err("push publish into to pubInfolist failed!"); - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_PUSH_TO_LIST_ERROR; - } - - if ((iotx_mc_send_packet(c, c->buf_send, len, &timer)) != SUCCESS_RETURN) { /* send the subscribe packet */ - /* If send failed, remove it */ - HAL_MutexLock(c->lock_list_sub); - list_remove(c->list_sub_wait_ack, node); - HAL_MutexUnlock(c->lock_list_sub); - HAL_MutexUnlock(c->lock_write_buf); - log_err("run sendPacket error!"); - return MQTT_NETWORK_ERROR; - } - - HAL_MutexUnlock(c->lock_write_buf); - return SUCCESS_RETURN; -} - - -/* MQTT send unsubscribe packet */ -static int MQTTUnsubscribe(iotx_mc_client_t *c, const char *topicFilter, unsigned int msgId) -{ - iotx_time_t timer; - MQTTString topic = MQTTString_initializer; - int len = 0; - iotx_mc_topic_handle_t handler = {topicFilter, {NULL, NULL}}; - - /* push into list */ - list_node_t *node = NULL; - - if (!c || !topicFilter) { - return FAIL_RETURN; - } - - topic.cstring = (char *)topicFilter; - iotx_time_init(&timer); - utils_time_countdown_ms(&timer, c->request_timeout_ms); - - HAL_MutexLock(c->lock_write_buf); - - if ((len = MQTTSerialize_unsubscribe((unsigned char *)c->buf_send, c->buf_size_send, 0, (unsigned short)msgId, 1, - &topic)) <= 0) { - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_UNSUBSCRIBE_PACKET_ERROR; - } - - if (SUCCESS_RETURN != iotx_mc_push_subInfo_to(c, len, msgId, UNSUBSCRIBE, &handler, &node)) { - log_err("push publish into to pubInfolist failed!"); - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_PUSH_TO_LIST_ERROR; - } - - if ((iotx_mc_send_packet(c, c->buf_send, len, &timer)) != SUCCESS_RETURN) { /* send the subscribe packet */ - /* remove from list */ - HAL_MutexLock(c->lock_list_sub); - list_remove(c->list_sub_wait_ack, node); - HAL_MutexUnlock(c->lock_list_sub); - HAL_MutexUnlock(c->lock_write_buf); - return MQTT_NETWORK_ERROR; - } - - HAL_MutexUnlock(c->lock_write_buf); - - return SUCCESS_RETURN; -} - - -/* MQTT send disconnect packet */ -static int MQTTDisconnect(iotx_mc_client_t *c) -{ - int rc = FAIL_RETURN; - iotx_time_t timer; /* we might wait for incomplete incoming publishes to complete */ - - if (!c) { - return FAIL_RETURN; - } - - HAL_MutexLock(c->lock_write_buf); - int 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 */ - } - - HAL_MutexUnlock(c->lock_write_buf); - - return rc; -} - -/* remove the list element specified by @msgId from list of wait publish ACK */ -/* return: 0, success; NOT 0, fail; */ -static int iotx_mc_mask_pubInfo_from(iotx_mc_client_t *c, uint16_t msgId) -{ - if (!c) { - return FAIL_RETURN; - } - - HAL_MutexLock(c->lock_list_pub); - if (c->list_pub_wait_ack->len) { - list_iterator_t *iter; - list_node_t *node = NULL; - iotx_mc_pub_info_t *repubInfo = NULL; - - if (NULL == (iter = list_iterator_new(c->list_pub_wait_ack, LIST_TAIL))) { - HAL_MutexUnlock(c->lock_list_pub); - return SUCCESS_RETURN; - } - - - for (;;) { - node = list_iterator_next(iter); - - if (NULL == node) { - break; - } - - repubInfo = (iotx_mc_pub_info_t *) node->val; - if (NULL == repubInfo) { - log_err("node's value is invalid!"); - continue; - } - - if (repubInfo->msg_id == msgId) { - repubInfo->node_state = IOTX_MC_NODE_STATE_INVALID; /* mark as invalid node */ - } - } - - list_iterator_destroy(iter); - } - HAL_MutexUnlock(c->lock_list_pub); - - return SUCCESS_RETURN; -} - - -/* push the wait element into list of wait publish ACK */ -/* return: 0, success; NOT 0, fail; */ -static int iotx_mc_push_pubInfo_to(iotx_mc_client_t *c, int len, unsigned short msgId, list_node_t **node) -{ - if (!c || !node) { - log_err("the param of c is error!"); - return FAIL_RETURN; - } - - if ((len < 0) || (len > c->buf_size_send)) { - log_err("the param of len is error!"); - return FAIL_RETURN; - } - - HAL_MutexLock(c->lock_list_pub); - - if (c->list_pub_wait_ack->len >= IOTX_MC_REPUB_NUM_MAX) { - HAL_MutexUnlock(c->lock_list_pub); - log_err("more than %u elements in republish list. List overflow!", c->list_pub_wait_ack->len); - return FAIL_RETURN; - } - - iotx_mc_pub_info_t *repubInfo = (iotx_mc_pub_info_t *)LITE_malloc(sizeof(iotx_mc_pub_info_t) + len); - if (NULL == repubInfo) { - HAL_MutexUnlock(c->lock_list_pub); - log_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); - - *node = list_node_new(repubInfo); - if (NULL == *node) { - HAL_MutexUnlock(c->lock_list_pub); - log_err("run list_node_new is error!"); - return FAIL_RETURN; - } - - list_rpush(c->list_pub_wait_ack, *node); - - HAL_MutexUnlock(c->lock_list_pub); - - return SUCCESS_RETURN; -} - - -/* push the wait element into list of wait subscribe(unsubscribe) ACK */ -/* return: 0, success; NOT 0, fail; */ -static int iotx_mc_push_subInfo_to(iotx_mc_client_t *c, int len, unsigned short msgId, enum msgTypes type, - iotx_mc_topic_handle_t *handler, - list_node_t **node) -{ - if (!c || !handler || !node) { - return FAIL_RETURN; - } - - HAL_MutexLock(c->lock_list_sub); - - if (c->list_sub_wait_ack->len >= IOTX_MC_SUB_REQUEST_NUM_MAX) { - HAL_MutexUnlock(c->lock_list_sub); - log_err("number of subInfo more than max!,size = %d", c->list_sub_wait_ack->len); - return FAIL_RETURN; - } - - iotx_mc_subsribe_info_t *subInfo = (iotx_mc_subsribe_info_t *)LITE_malloc(sizeof( - iotx_mc_subsribe_info_t) + len); - if (NULL == subInfo) { - HAL_MutexUnlock(c->lock_list_sub); - log_err("run iotx_memory_malloc is error!"); - return FAIL_RETURN; - } - - subInfo->node_state = IOTX_MC_NODE_STATE_NORMANL; - subInfo->msg_id = msgId; - subInfo->len = len; - iotx_time_start(&subInfo->sub_start_time); - subInfo->type = type; - subInfo->handler = *handler; - subInfo->buf = (unsigned char *)subInfo + sizeof(iotx_mc_subsribe_info_t); - - memcpy(subInfo->buf, c->buf_send, len); - - *node = list_node_new(subInfo); - if (NULL == *node) { - HAL_MutexUnlock(c->lock_list_sub); - log_err("run list_node_new is error!"); - return FAIL_RETURN; - } - - list_rpush(c->list_sub_wait_ack, *node); - - HAL_MutexUnlock(c->lock_list_sub); - - return SUCCESS_RETURN; -} - - -/* remove the list element specified by @msgId from list of wait subscribe(unsubscribe) ACK */ -/* and return message handle by @messageHandler */ -/* return: 0, success; NOT 0, fail; */ -static int iotx_mc_mask_subInfo_from(iotx_mc_client_t *c, unsigned int msgId, iotx_mc_topic_handle_t *messageHandler) -{ - if (!c || !messageHandler) { - return FAIL_RETURN; - } - - HAL_MutexLock(c->lock_list_sub); - if (c->list_sub_wait_ack->len) { - list_iterator_t *iter; - list_node_t *node = NULL; - iotx_mc_subsribe_info_t *subInfo = NULL; - - if (NULL == (iter = list_iterator_new(c->list_sub_wait_ack, LIST_TAIL))) { - HAL_MutexUnlock(c->lock_list_sub); - return SUCCESS_RETURN; - } - - for (;;) { - node = list_iterator_next(iter); - if (NULL == node) { - break; - } - - subInfo = (iotx_mc_subsribe_info_t *) node->val; - if (NULL == subInfo) { - log_err("node's value is invalid!"); - continue; - } - - if (subInfo->msg_id == msgId) { - *messageHandler = subInfo->handler; /* return handle */ - subInfo->node_state = IOTX_MC_NODE_STATE_INVALID; /* mark as invalid node */ - } - } - - list_iterator_destroy(iter); - } - HAL_MutexUnlock(c->lock_list_sub); - - return SUCCESS_RETURN; -} - - -/* get next packet-id */ -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; -} - - -/* send packet */ -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; - - if (!c || !buf || !time) { - return rc; - } - - while (sent < length && !utils_time_is_expired(time)) { - rc = c->ipstack->write(c->ipstack, &buf[sent], length, iotx_time_left(time)); - 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; -} - - -/* decode packet */ -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 != 1) { - return MQTT_NETWORK_ERROR; - } - - *value += (i & 127) * multiplier; - multiplier *= 128; - } while ((i & 128) != 0); - - return len; -} - - -/* read packet */ -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; - - if (!c || !timer || !packet_type) { - return FAIL_RETURN; - } - - /* 1. read the header byte. This has the packet type in it */ - rc = c->ipstack->read(c->ipstack, c->buf_read, 1, iotx_time_left(timer) == 0 ? 1 : iotx_time_left(timer)); - if (0 == rc) { /* timeout */ - *packet_type = 0; - return SUCCESS_RETURN; - } else if (1 != rc) { - log_debug("mqtt read error, rc=%d", rc); - return FAIL_RETURN; - } - - len = 1; - - /* 2. read the remaining length. This is variable in itself */ - if ((rc = iotx_mc_decode_packet(c, &rem_len, iotx_time_left(timer))) < 0) { - log_err("decodePacket error,rc = %d", rc); - return rc; - } - - len += MQTTPacket_encode((unsigned char *)c->buf_read + 1, - rem_len); /* put the original remaining length back into the buffer */ - - /* Check if the received data length exceeds mqtt read buffer length */ - if ((rem_len > 0) && ((rem_len + len) > c->buf_size_read)) { - log_err("mqtt read buffer is too short, mqttReadBufLen : %u, remainDataLen : %d", c->buf_size_read, rem_len); - int needReadLen = c->buf_size_read - len; - if (c->ipstack->read(c->ipstack, c->buf_read + len, needReadLen, iotx_time_left(timer) == 0 ? 1 : iotx_time_left(timer)) != needReadLen) { - log_err("mqtt read error"); - return FAIL_RETURN; - } - - /* drop data whitch over the length of mqtt buffer */ - int remainDataLen = rem_len - needReadLen; - char *remainDataBuf = LITE_malloc(remainDataLen + 1); - if (!remainDataBuf) { - log_err("allocate remain buffer failed"); - return FAIL_RETURN; - } - - if (c->ipstack->read(c->ipstack, remainDataBuf, remainDataLen, iotx_time_left(timer) == 0 ? 1 : iotx_time_left(timer)) != remainDataLen) { - log_err("mqtt read error"); - LITE_free(remainDataBuf); - remainDataBuf = NULL; - return FAIL_RETURN; - } - - LITE_free(remainDataBuf); - remainDataBuf = NULL; - - 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"; - - c->handle_event.h_fp(c->handle_event.pcontext, c, &msg); - } - - return SUCCESS_RETURN; - - } - - /* 3. read the rest of the buffer using a callback to supply the rest of the data */ - if (rem_len > 0 && (c->ipstack->read(c->ipstack, c->buf_read + len, rem_len, iotx_time_left(timer) == 0 ? 1 : iotx_time_left(timer)) != rem_len)) { - log_err("mqtt read error"); - return FAIL_RETURN; - } - - header.byte = c->buf_read[0]; - *packet_type = header.bits.type; - return SUCCESS_RETURN; -} - - -/* check whether the topic is matched or not */ -static char iotx_mc_is_topic_matched(char *topicFilter, MQTTString *topicName) -{ - if (!topicFilter || !topicName) { - return 0; - } - char *curf = topicFilter; - char *curn = topicName->lenstring.data; - char *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'); -} - - -/* deliver message */ -static void iotx_mc_deliver_message(iotx_mc_client_t *c, MQTTString *topicName, iotx_mqtt_topic_info_pt topic_msg) -{ - int i, flag_matched = 0; - - if (!c || !topicName || !topic_msg) { - return; - } - - topic_msg->ptopic = topicName->lenstring.data; - topic_msg->topic_len = topicName->lenstring.len; - - /* we have to find the right message handler - indexed by topic */ - HAL_MutexLock(c->lock_generic); - for (i = 0; i < IOTX_MC_SUB_NUM_MAX; ++i) { - - if ((c->sub_handle[i].topic_filter != 0) - && (MQTTPacket_equals(topicName, (char *)c->sub_handle[i].topic_filter) - || iotx_mc_is_topic_matched((char *)c->sub_handle[i].topic_filter, topicName))) { - log_debug("topic be matched"); - - iotx_mc_topic_handle_t msg_handle = c->sub_handle[i]; - HAL_MutexUnlock(c->lock_generic); - - if (NULL != msg_handle.handle.h_fp) { - iotx_mqtt_event_msg_t msg; - msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECVEIVED; - msg.msg = (void *)topic_msg; - - msg_handle.handle.h_fp(msg_handle.handle.pcontext, c, &msg); - flag_matched = 1; - } - - HAL_MutexLock(c->lock_generic); - } - } - - HAL_MutexUnlock(c->lock_generic); - - if (0 == flag_matched) { - log_debug("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_RECVEIVED; - msg.msg = topic_msg; - - c->handle_event.h_fp(c->handle_event.pcontext, c, &msg); - } - } -} - - -/* handle CONNACK packet received from remote MQTT broker */ -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) { - log_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; -} - - -/* 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; - c->handle_event.h_fp(c->handle_event.pcontext, c, &msg); - } - - return SUCCESS_RETURN; -} - - -/* handle SUBACK packet received from remote MQTT broker */ -static int iotx_mc_handle_recv_SUBACK(iotx_mc_client_t *c) -{ - unsigned short mypacketid; - int i, count = 0, grantedQoS = -1; - int i_free = -1, flag_dup = 0; - - if (!c) { - return FAIL_RETURN; - } - - if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, (unsigned char *)c->buf_read, c->buf_size_read) != 1) { - log_err("Sub ack packet error"); - return MQTT_SUBSCRIBE_ACK_PACKET_ERROR; - } - - iotx_mc_topic_handle_t messagehandler; - memset(&messagehandler, 0, sizeof(iotx_mc_topic_handle_t)); - (void)iotx_mc_mask_subInfo_from(c, mypacketid, &messagehandler); - - /* In negative case, grantedQoS will be 0xFFFF FF80, which means -128 */ - if ((uint8_t)grantedQoS == 0x80) { - log_err("MQTT SUBSCRIBE failed, ack code is 0x80"); - if (NULL != c->handle_event.h_fp) { - iotx_mqtt_event_msg_t msg; - - msg.event_type = IOTX_MQTT_EVENT_SUBCRIBE_NACK; - msg.msg = (void *)(uintptr_t)mypacketid; - c->handle_event.h_fp(c->handle_event.pcontext, c, &msg); - } - return MQTT_SUBSCRIBE_ACK_FAILURE; - } - - if ((NULL == messagehandler.handle.h_fp) || (NULL == messagehandler.topic_filter)) { - return MQTT_SUB_INFO_NOT_FOUND_ERROR; - } - - HAL_MutexLock(c->lock_generic); - - for (i = 0; i < IOTX_MC_SUB_NUM_MAX; ++i) { - /* If subscribe the same topic and callback function, then ignore */ - if ((NULL != c->sub_handle[i].topic_filter)) { - if (0 == iotx_mc_check_handle_is_identical(&c->sub_handle[i], &messagehandler)) { - /* if subscribe a identical topic and relate callback function, then ignore this subscribe */ - flag_dup = 1; - log_err("There is a identical topic and related handle in list!"); - break; - } - } else { - if (-1 == i_free) { - i_free = i; /* record available element */ - } - } - } - - if (0 == flag_dup) { - if (-1 == i_free) { - log_err("NOT more @sub_handle space!"); - HAL_MutexUnlock(c->lock_generic); - return FAIL_RETURN; - } else { - c->sub_handle[i_free].topic_filter = messagehandler.topic_filter; - c->sub_handle[i_free].handle.h_fp = messagehandler.handle.h_fp; - c->sub_handle[i_free].handle.pcontext = messagehandler.handle.pcontext; - } - } - - HAL_MutexUnlock(c->lock_generic); - - /* call callback function to notify that SUBSCRIBE is successful */ - if (NULL != c->handle_event.h_fp) { - iotx_mqtt_event_msg_t msg; - msg.event_type = IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS; - msg.msg = (void *)(uintptr_t)mypacketid; - c->handle_event.h_fp(c->handle_event.pcontext, c, &msg); - } - - return SUCCESS_RETURN; -} - - -/* handle PUBLISH packet received from remote MQTT broker */ -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; - int payload_len = 0; - - 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 = (unsigned short)payload_len; - - /* payload decrypt by id2_aes */ - if (c->mqtt_down_process) { - c->mqtt_down_process(&topic_msg); - } - - log_debug("%20s : %08d", "Packet Ident", topic_msg.packet_id); - log_debug("%20s : %d", "Topic Length", topicName.lenstring.len); - log_debug("%20s : %.*s", - "Topic Name", - topicName.lenstring.len, - topicName.lenstring.data); - log_debug("%20s : %d / %d", "Payload Len/Room", - topic_msg.payload_len, - c->buf_read + c->buf_size_read - topic_msg.payload); - log_debug("%20s : %d", "Receive Buflen", c->buf_size_read); - -#if defined(INSPECT_MQTT_FLOW) - log_debug("%20s : %p", "Payload Buffer", topic_msg.payload); - log_debug("%20s : %p", "Receive Buffer", c->buf_read); - HEXDUMP_DEBUG(topic_msg.payload, topic_msg.payload_len); -#endif - - topic_msg.ptopic = NULL; - topic_msg.topic_len = 0; - - log_debug("delivering msg ..."); - - 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 { - log_err("Invalid QOS, QOSvalue = %d", topic_msg.qos); - return MQTT_PUBLISH_QOS_ERROR; - } - - return result; -} - - -/* handle UNSUBACK packet received from remote MQTT broker */ -static int iotx_mc_handle_recv_UNSUBACK(iotx_mc_client_t *c) -{ - unsigned short i, 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; - } - - iotx_mc_topic_handle_t messageHandler; - (void)iotx_mc_mask_subInfo_from(c, mypacketid, &messageHandler); - - /* Remove from message handler array */ - HAL_MutexLock(c->lock_generic); - for (i = 0; i < IOTX_MC_SUB_NUM_MAX; ++i) { - if ((c->sub_handle[i].topic_filter != NULL) - && (0 == iotx_mc_check_handle_is_identical(&c->sub_handle[i], &messageHandler))) { - memset(&c->sub_handle[i], 0, sizeof(iotx_mc_topic_handle_t)); - - /* NOTE: in case of more than one register(subscribe) with different callback function, - * so we must keep continuously searching related message handle */ - } - } - - 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; - - c->handle_event.h_fp(c->handle_event.pcontext, c, &msg); - } - - HAL_MutexUnlock(c->lock_generic); - return SUCCESS_RETURN; -} - - -/* wait CONNACK packet from remote MQTT broker */ -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) { - log_err("readPacket error,result = %d", rc); - return MQTT_NETWORK_ERROR; - } - - if (++wait_connack > WAIT_CONNACK_MAX) { - log_err("wait connack timeout"); - return MQTT_NETWORK_ERROR; - } - - } while (packetType != CONNACK); - - rc = iotx_mc_handle_recv_CONNACK(c); - if (SUCCESS_RETURN != rc) { - log_err("recvConnackProc error,result = %d", rc); - } - - return rc; -} - - -/* MQTT cycle to handle packet from remote broker */ -static int iotx_mc_cycle(iotx_mc_client_t *c, iotx_time_t *timer) -{ - unsigned int packetType; - int rc = SUCCESS_RETURN; - - if (!c) { - return FAIL_RETURN; - } - - iotx_mc_state_t state = iotx_mc_get_client_state(c); - if (state != IOTX_MC_STATE_CONNECTED) { - log_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; - log_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) { - iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); - log_debug("readPacket error,result = %d", rc); - return MQTT_NETWORK_ERROR; - } - - if (MQTT_CPT_RESERVED == packetType) { - /* log_debug("wait data timeout"); */ - 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); - - switch (packetType) { - case CONNACK: { - log_debug("CONNACK"); - break; - } - case PUBACK: { - log_debug("PUBACK"); - rc = iotx_mc_handle_recv_PUBACK(c); - if (SUCCESS_RETURN != rc) { - log_err("recvPubackProc error,result = %d", rc); - } - - break; - } - case SUBACK: { - log_debug("SUBACK"); - rc = iotx_mc_handle_recv_SUBACK(c); - if (SUCCESS_RETURN != rc) { - log_err("recvSubAckProc error,result = %d", rc); - } - break; - } - case PUBLISH: { - log_debug("PUBLISH"); - /* HEXDUMP_DEBUG(c->buf_read, 32); */ - - rc = iotx_mc_handle_recv_PUBLISH(c); - if (SUCCESS_RETURN != rc) { - log_err("recvPublishProc error,result = %d", rc); - } - break; - } - case UNSUBACK: { - rc = iotx_mc_handle_recv_UNSUBACK(c); - if (SUCCESS_RETURN != rc) { - log_err("recvUnsubAckProc error,result = %d", rc); - } - break; - } - case PINGRESP: { - rc = SUCCESS_RETURN; - log_info("receive ping response!"); - break; - } - default: - log_err("INVALID TYPE"); - return FAIL_RETURN; - } - - return rc; -} - - -/* check MQTT client is in normal state */ -/* 0, in abnormal state; 1, in normal state */ -static int iotx_mc_check_state_normal(iotx_mc_client_t *c) -{ - if (!c) { - return 0; - } - - if (iotx_mc_get_client_state(c) == IOTX_MC_STATE_CONNECTED) { - return 1; - } - - return 0; -} - - -/* return: 0, identical; NOT 0, different */ -static int iotx_mc_check_handle_is_identical(iotx_mc_topic_handle_t *messageHandlers1, - iotx_mc_topic_handle_t *messageHandler2) -{ - if (!messageHandlers1 || !messageHandler2) { - return 1; - } - - int 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; - } - - 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; -} - - -/* subscribe */ -static int iotx_mc_subscribe(iotx_mc_client_t *c, - const char *topicFilter, - iotx_mqtt_qos_t qos, - iotx_mqtt_event_handle_func_fpt topic_handle_func, - void *pcontext) -{ - if (NULL == c || NULL == topicFilter || !topic_handle_func) { - return NULL_VALUE_ERROR; - } - - int rc = FAIL_RETURN; - - if (!iotx_mc_check_state_normal(c)) { - log_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)) { - log_err("topic format is error,topicFilter = %s", topicFilter); - return MQTT_TOPIC_FORMAT_ERROR; - } - - unsigned int msgId = iotx_mc_get_next_packetid(c); - 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); - } - - log_err("run MQTTSubscribe error"); - return rc; - } - - log_info("mqtt subscribe success,topic = %s!", topicFilter); - return msgId; -} - - -/* unsubscribe */ -static int iotx_mc_unsubscribe(iotx_mc_client_t *c, const char *topicFilter) -{ - int rc = FAIL_RETURN; - unsigned int msgId = iotx_mc_get_next_packetid(c); - - if (NULL == c || NULL == topicFilter) { - return NULL_VALUE_ERROR; - } - - if (0 != iotx_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) { - log_err("topic format is error,topicFilter = %s", topicFilter); - return MQTT_TOPIC_FORMAT_ERROR; - } - - if (!iotx_mc_check_state_normal(c)) { - log_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); - } - - log_err("run MQTTUnsubscribe error!"); - return rc; - } - - log_info("mqtt unsubscribe success,topic = %s!", topicFilter); - return (int)msgId; -} - -/* publish */ -static int iotx_mc_publish(iotx_mc_client_t *c, const char *topicName, iotx_mqtt_topic_info_pt topic_msg) -{ - uint16_t msg_id = 0; - int rc = FAIL_RETURN; - - if (NULL == c || NULL == topicName || NULL == topic_msg) { - return NULL_VALUE_ERROR; - } - - if (0 != iotx_mc_check_topic(topicName, TOPIC_NAME_TYPE)) { - log_err("topic format is error,topicFilter = %s", topicName); - return MQTT_TOPIC_FORMAT_ERROR; - } - - if (!iotx_mc_check_state_normal(c)) { - log_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c)); - return MQTT_STATE_ERROR; - } - - 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) { - log_err("MQTTPublish return error,MQTT_QOS2 is now not supported."); - return MQTT_PUBLISH_QOS_ERROR; - } - /* payload encrypt by id2_aes */ - if (c->mqtt_up_process) { - rc = c->mqtt_up_process((char *)topicName, topic_msg); - } - -#if defined(INSPECT_MQTT_FLOW) - 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); - } - log_err("MQTTPublish is error, rc = %d", rc); - return rc; - } - - return (int)msg_id; -} - - -/* get state of MQTT client */ -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; -} - - -/* 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); -} - - -/* 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 < KEEP_ALIVE_INTERVAL_DEFAULT_MIN) { - log_warning("Input heartbeat interval(%d ms) < Allowed minimum(%d ms)", - (pConnectParams->keepAliveInterval * 1000), - (KEEP_ALIVE_INTERVAL_DEFAULT_MIN * 1000) - ); - log_warning("Reset heartbeat interval => %d Millisecond", - (KEEP_ALIVE_INTERVAL_DEFAULT_MIN * 1000) - ); - pClient->connect_data.keepAliveInterval = KEEP_ALIVE_INTERVAL_DEFAULT_MIN; - } else if (pConnectParams->keepAliveInterval > KEEP_ALIVE_INTERVAL_DEFAULT_MAX) { - log_warning("Input heartbeat interval(%d ms) > Allowed maximum(%d ms)", - (pConnectParams->keepAliveInterval * 1000), - (KEEP_ALIVE_INTERVAL_DEFAULT_MAX * 1000) - ); - log_warning("Reset heartbeat interval => %d Millisecond", - (KEEP_ALIVE_INTERVAL_DEFAULT_MAX * 1000) - ); - pClient->connect_data.keepAliveInterval = KEEP_ALIVE_INTERVAL_DEFAULT_MAX; - } else { - pClient->connect_data.keepAliveInterval = pConnectParams->keepAliveInterval; - } - - return SUCCESS_RETURN; -} - -static int32_t iotx_mc_calc_seed(uint32_t *p_seed) -{ - char *device_secret; - iotx_device_info_pt pdev = iotx_device_info_get(); - uint32_t seed = 0; - - POINTER_SANITY_CHECK(p_seed, NULL_VALUE_ERROR); - POINTER_SANITY_CHECK(pdev, NULL_VALUE_ERROR); - - device_secret = pdev->device_secret; - STRING_PTR_SANITY_CHECK(device_secret, NULL_VALUE_ERROR); - - while ('\0' != *device_secret) { - seed += *device_secret; - device_secret++; - } - seed += (HAL_UptimeMs() / 1000); - seed %= UINT32_MAX; - *p_seed = seed; - return SUCCESS_RETURN; -} - -static int32_t iotx_mc_calc_random_init() -{ - uint32_t seed; - - if (SUCCESS_RETURN != iotx_mc_calc_seed(&seed)) { - return FAIL_RETURN; - } - - HAL_Srandom(seed); - return SUCCESS_RETURN; -} - -/* 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; - - if ((NULL == pClient) || (NULL == pInitParams)) { - return NULL_VALUE_ERROR; - } - - memset(pClient, 0x0, sizeof(iotx_mc_client_t)); - - MQTTPacket_connectData connectdata = MQTTPacket_connectData_initializer; - - 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; - - - memset(pClient->sub_handle, 0, IOTX_MC_SUB_NUM_MAX * sizeof(iotx_mc_topic_handle_t)); - - pClient->packet_id = 0; - pClient->lock_generic = HAL_MutexCreate(); - if (!pClient->lock_generic) { - return FAIL_RETURN; - } - - pClient->lock_list_sub = HAL_MutexCreate(); - if (!pClient->lock_list_sub) { - HAL_MutexDestroy(pClient->lock_generic); - pClient->lock_generic = NULL; - return FAIL_RETURN; - } - - pClient->lock_list_pub = HAL_MutexCreate(); - if (!pClient->lock_list_pub) { - HAL_MutexDestroy(pClient->lock_generic); - pClient->lock_generic = NULL; - HAL_MutexDestroy(pClient->lock_list_sub); - pClient->lock_list_sub = NULL; - return FAIL_RETURN; - } - - if (pInitParams->request_timeout_ms < IOTX_MC_REQUEST_TIMEOUT_MIN_MS - || pInitParams->request_timeout_ms > IOTX_MC_REQUEST_TIMEOUT_MAX_MS) { - - pClient->request_timeout_ms = IOTX_MC_REQUEST_TIMEOUT_DEFAULT_MS; - } else { - pClient->request_timeout_ms = pInitParams->request_timeout_ms; - } - - pClient->buf_send = pInitParams->pwrite_buf; - pClient->buf_size_send = pInitParams->write_buf_size; - pClient->buf_read = pInitParams->pread_buf; - pClient->buf_size_read = pInitParams->read_buf_size; - - 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; - - pClient->list_pub_wait_ack = list_new(); - if (pClient->list_pub_wait_ack) { - pClient->list_pub_wait_ack->free = LITE_free_routine; - } - pClient->list_sub_wait_ack = list_new(); - if (pClient->list_sub_wait_ack) { - pClient->list_sub_wait_ack->free = LITE_free_routine; - } - - pClient->lock_write_buf = HAL_MutexCreate(); - - - /* 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); - - pClient->ipstack = (utils_network_pt)LITE_malloc(sizeof(utils_network_t)); - if (NULL == pClient->ipstack) { - log_err("allocate Network struct failed"); - rc = FAIL_RETURN; - goto RETURN; - } - memset(pClient->ipstack, 0x0, sizeof(utils_network_t)); -#ifndef IOTX_NET_INIT_WITH_PK_EXT - rc = iotx_net_init(pClient->ipstack, pInitParams->host, pInitParams->port, pInitParams->pub_key); -#else - rc = iotx_net_init(pClient->ipstack, pInitParams->host, pInitParams->port, pInitParams->pub_key, - iotx_device_info_get()->product_key); -#endif - if (SUCCESS_RETURN != rc) { - mc_state = IOTX_MC_STATE_INVALID; - goto RETURN; - } -#if defined(MQTT_ID2_CRYPTO) - pClient->ipstack->ca_crt = NULL; - pClient->ipstack->ca_crt_len = 0; -#endif - if (SUCCESS_RETURN != iotx_mc_calc_random_init()) { - log_err("iotx_mc_calc_random_init failed"); - rc = FAIL_RETURN; - goto RETURN; - } - - mc_state = IOTX_MC_STATE_INITIALIZED; - rc = SUCCESS_RETURN; - log_info("MQTT init success!"); - -RETURN : - iotx_mc_set_client_state(pClient, mc_state); - if (rc != SUCCESS_RETURN) { - if (pClient->list_pub_wait_ack) { - pClient->list_pub_wait_ack->free(pClient->list_pub_wait_ack); - pClient->list_pub_wait_ack = NULL; - } - if (pClient->list_sub_wait_ack) { - pClient->list_sub_wait_ack->free(pClient->list_sub_wait_ack); - pClient->list_sub_wait_ack = NULL; - } - if (pClient->ipstack) { - LITE_free(pClient->ipstack); - pClient->ipstack = NULL; - } - if (pClient->lock_generic) { - HAL_MutexDestroy(pClient->lock_generic); - pClient->lock_generic = NULL; - } - if (pClient->lock_list_sub) { - HAL_MutexDestroy(pClient->lock_list_sub); - pClient->lock_list_sub = NULL; - } - 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; - } - } - - return rc; -} - - -/* remove node of list of wait subscribe ACK, which is in invalid state or timeout */ -static int MQTTSubInfoProc(iotx_mc_client_t *pClient) -{ - int rc = SUCCESS_RETURN; - - if (!pClient) { - return FAIL_RETURN; - } - - HAL_MutexLock(pClient->lock_list_sub); - do { - if (0 == pClient->list_sub_wait_ack->len) { - break; - } - - list_iterator_t *iter; - list_node_t *node = NULL; - list_node_t *tempNode = NULL; - uint16_t packet_id = 0; - enum msgTypes msg_type; - - if (NULL == (iter = list_iterator_new(pClient->list_sub_wait_ack, LIST_TAIL))) { - log_err("new list failed"); - HAL_MutexUnlock(pClient->lock_list_sub); - return SUCCESS_RETURN; - } - - for (;;) { - node = list_iterator_next(iter); - - if (NULL != tempNode) { - list_remove(pClient->list_sub_wait_ack, tempNode); - tempNode = NULL; - } - - if (NULL == node) { - break; /* end of list */ - } - - iotx_mc_subsribe_info_t *subInfo = (iotx_mc_subsribe_info_t *) node->val; - if (NULL == subInfo) { - log_err("node's value is invalid!"); - tempNode = node; - continue; - } - - /* remove invalid node */ - if (IOTX_MC_NODE_STATE_INVALID == subInfo->node_state) { - tempNode = node; - continue; - } - - if (iotx_mc_get_client_state(pClient) != IOTX_MC_STATE_CONNECTED) { - continue; - } - - /* check the request if timeout or not */ - if (utils_time_spend(&subInfo->sub_start_time) <= (pClient->request_timeout_ms * 2)) { - /* continue to check the next node */ - continue; - } - - /* When arrive here, it means timeout to wait ACK */ - packet_id = subInfo->msg_id; - msg_type = subInfo->type; - - /* Wait MQTT SUBSCRIBE ACK timeout */ - if (NULL != pClient->handle_event.h_fp) { - iotx_mqtt_event_msg_t msg; - - if (SUBSCRIBE == msg_type) { - /* subscribe timeout */ - msg.event_type = IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT; - msg.msg = (void *)(uintptr_t)packet_id; - } else { /* if (UNSUBSCRIBE == msg_type) */ - /* unsubscribe timeout */ - msg.event_type = IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT; - msg.msg = (void *)(uintptr_t)packet_id; - } - - pClient->handle_event.h_fp(pClient->handle_event.pcontext, pClient, &msg); - } - - tempNode = node; - } - - list_iterator_destroy(iter); - - } while (0); - - HAL_MutexUnlock(pClient->lock_list_sub); - - return rc; -} - - -static void iotx_mc_keepalive(iotx_mc_client_t *pClient) -{ - int rc = 0; - - if (!pClient) { - return; - } - - /* Periodic sending ping packet to detect whether the network is connected */ - iotx_mc_keepalive_sub(pClient); - - iotx_mc_state_t 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) { - /* 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) { - log_debug("reconnect network fail, rc = %d", rc); - } else { - log_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) { - log_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); -} - - -/* republish */ -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; -} - - -/* remove node of list of wait publish ACK, which is in invalid state or timeout */ -static int MQTTPubInfoProc(iotx_mc_client_t *pClient) -{ - int rc = 0; - iotx_mc_state_t state = IOTX_MC_STATE_INVALID; - - if (!pClient) { - return FAIL_RETURN; - } - - HAL_MutexLock(pClient->lock_list_pub); - do { - if (0 == pClient->list_pub_wait_ack->len) { - break; - } - - list_iterator_t *iter; - list_node_t *node = NULL; - list_node_t *tempNode = NULL; - - if (NULL == (iter = list_iterator_new(pClient->list_pub_wait_ack, LIST_TAIL))) { - log_err("new list failed"); - break; - } - - for (;;) { - node = list_iterator_next(iter); - - if (NULL != tempNode) { - list_remove(pClient->list_pub_wait_ack, tempNode); - tempNode = NULL; - } - - if (NULL == node) { - break; /* end of list */ - } - - iotx_mc_pub_info_t *repubInfo = (iotx_mc_pub_info_t *) node->val; - if (NULL == repubInfo) { - log_err("node's value is invalid!"); - tempNode = node; - continue; - } - - /* remove invalid node */ - if (IOTX_MC_NODE_STATE_INVALID == repubInfo->node_state) { - tempNode = 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(&repubInfo->pub_start_time) <= (pClient->request_timeout_ms * 2)) { - continue; - } - - /* If wait ACK timeout, republish */ - HAL_MutexUnlock(pClient->lock_list_pub); - rc = MQTTRePublish(pClient, (char *)repubInfo->buf, repubInfo->len); - iotx_time_start(&repubInfo->pub_start_time); - HAL_MutexLock(pClient->lock_list_pub); - - if (MQTT_NETWORK_ERROR == rc) { - iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED); - break; - } - } - - list_iterator_destroy(iter); - - } while (0); - - HAL_MutexUnlock(pClient->lock_list_pub); - - return SUCCESS_RETURN; -} - - -/* connect */ -static int iotx_mc_connect(iotx_mc_client_t *pClient) -{ - int rc = FAIL_RETURN; - - if (NULL == pClient) { - return NULL_VALUE_ERROR; - } - - /* Establish TCP or TLS connection */ - rc = pClient->ipstack->connect(pClient->ipstack); - if (SUCCESS_RETURN != rc) { - pClient->ipstack->disconnect(pClient->ipstack); - log_err("TCP or TLS Connection failed"); - - if (ERROR_CERTIFICATE_EXPIRED == rc) { - log_err("certificate is expired!"); - return ERROR_CERT_VERIFY_FAIL; - } else { - return MQTT_NETWORK_CONNECT_ERROR; - } - } - - /* remove */ - /*log_debug("start MQTT connection with parameters: clientid=%s, username=%s, password=%s", - pClient->connect_data.clientID.cstring, - pClient->connect_data.username.cstring, - pClient->connect_data.password.cstring);*/ - - rc = MQTTConnect(pClient); - if (rc != SUCCESS_RETURN) { - pClient->ipstack->disconnect(pClient->ipstack); - log_err("send connect packet failed"); - return rc; - } - - if (SUCCESS_RETURN != iotx_mc_wait_CONNACK(pClient)) { - (void)MQTTDisconnect(pClient); - pClient->ipstack->disconnect(pClient->ipstack); - log_err("wait connect ACK timeout, or receive a ACK indicating error!"); - 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); - - log_info("mqtt connect success!"); - return SUCCESS_RETURN; -} - - -static int iotx_mc_attempt_reconnect(iotx_mc_client_t *pClient) -{ - - int rc; - - log_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 = iotx_mc_connect(pClient); - - if (SUCCESS_RETURN != rc) { - log_err("run iotx_mqtt_connect() error!"); - return rc; - } - - return SUCCESS_RETURN; -} - - -/* reconnect */ -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; - } - log_info("Waiting to reconnect..."); - while (!utils_time_is_expired(&(pClient->reconnect_param.reconnect_next_time))) { - /* Timer has not expired. Not time to attempt reconnect yet. */ - HAL_SleepMs(20); - } - - log_info("start to reconnect"); - /* REDO AUTH before each reconnection */ - if (NULL != pClient->mqtt_auth && SUCCESS_RETURN != pClient->mqtt_auth()) { - log_err("redo authentication error!"); - return -1; - } - - rc = iotx_mc_attempt_reconnect(pClient); - if (SUCCESS_RETURN == rc) { - iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECTED); - return SUCCESS_RETURN; - } 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; - } - } - - interval_ms = pClient->reconnect_param.reconnect_time_interval_ms; - interval_ms += HAL_Random(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); - - log_err("mqtt reconnect failed rc = %d", rc); - - return rc; -} - -static int iotx_mc_disconnect(iotx_mc_client_t *pClient) -{ - int rc = -1; - - if (NULL == pClient) { - return NULL_VALUE_ERROR; - } - - if (iotx_mc_check_state_normal(pClient)) { - rc = MQTTDisconnect(pClient); - log_debug("rc = MQTTDisconnect() = %d", rc); - } - - /* close tcp/ip socket or free tls resources */ - pClient->ipstack->disconnect(pClient->ipstack); - - iotx_mc_set_client_state(pClient, IOTX_MC_STATE_INITIALIZED); - - log_info("mqtt disconnect!"); - return SUCCESS_RETURN; -} - -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); - } -} - - -/* release MQTT resource */ -static int iotx_mc_release(iotx_mc_client_t *pClient) -{ - - 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); - - HAL_MutexDestroy(pClient->lock_generic); - HAL_MutexDestroy(pClient->lock_list_sub); - HAL_MutexDestroy(pClient->lock_list_pub); - HAL_MutexDestroy(pClient->lock_write_buf); - - list_destroy(pClient->list_pub_wait_ack); - list_destroy(pClient->list_sub_wait_ack); - - if (NULL != pClient->ipstack) { - LITE_free(pClient->ipstack); - } - - log_info("mqtt release!"); - return SUCCESS_RETURN; -} - - -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 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 (!iotx_mc_check_state_normal(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); - } - log_err("ping outstanding is error,result = %d", rc); - return rc; - } - - log_info("send MQTT ping..."); - - HAL_MutexLock(pClient->lock_generic); - pClient->ping_mark = 1; - pClient->keepalive_probes++; - HAL_MutexUnlock(pClient->lock_generic); - - return SUCCESS_RETURN; -} - -/* report ModuleID */ -static int iotx_mc_report_mid(iotx_mc_client_t *pclient) -{ - int ret; - char topic_name[IOTX_URI_MAX_LEN + 1]; - iotx_mqtt_topic_info_t topic_info; - char requestId[MIDREPORT_REQID_LEN + 1] = {0}; - iotx_device_info_pt dev = iotx_device_info_get(); - char pid[PID_STRLEN_MAX + 1] = {0}; - char mid[MID_STRLEN_MAX + 1] = {0}; - - memset(pid, 0, sizeof(pid)); - memset(mid, 0, sizeof(mid)); - - if (0 == HAL_GetPartnerID(pid)) { - log_debug("PartnerID is Null"); - return SUCCESS_RETURN; - } - if (0 == HAL_GetModuleID(mid)) { - log_debug("ModuleID is Null"); - return SUCCESS_RETURN; - } - - log_debug("MID Report: started in MQTT"); - - iotx_midreport_reqid(requestId, - dev->product_key, - dev->device_name); - /* 1,generate json data */ - char *msg = HAL_Malloc(MIDREPORT_PAYLOAD_LEN); - if (NULL == msg) { - log_err("allocate mem failed"); - return FAIL_RETURN; - } - - iotx_midreport_payload(msg, - requestId, - mid, - pid); - - log_debug("MID Report: json data = '%s'", msg); - - memset(&topic_info, 0, sizeof(iotx_mqtt_topic_info_t)); - - topic_info.qos = IOTX_MQTT_QOS0; - topic_info.payload = (void *)msg; - topic_info.payload_len = strlen(msg); - topic_info.retain = 0; - topic_info.dup = 0; - - /* 2,generate topic name */ - ret = iotx_midreport_topic(topic_name, - "", - dev->product_key, - dev->device_name); - - log_debug("MID Report: topic name = '%s'", topic_name); - - if (ret < 0) { - log_err("generate topic name of info failed"); - HAL_Free(msg); - return FAIL_RETURN; - } - - ret = IOT_MQTT_Publish(pclient, topic_name, &topic_info); - if (ret < 0) { - log_err("publish failed"); - HAL_Free(msg); - return FAIL_RETURN; - } - - HAL_Free(msg); - - log_debug("MID Report: finished, IOT_MQTT_Publish() = %d", ret); - return SUCCESS_RETURN; -} - -/************************ Public Interface ************************/ -void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams) -{ - int err; - iotx_mc_client_t *pclient; - - POINTER_SANITY_CHECK(pInitParams, NULL); - POINTER_SANITY_CHECK(pInitParams->pwrite_buf, NULL); - POINTER_SANITY_CHECK(pInitParams->pread_buf, NULL); - - STRING_PTR_SANITY_CHECK(pInitParams->host, NULL); - STRING_PTR_SANITY_CHECK(pInitParams->client_id, NULL); - STRING_PTR_SANITY_CHECK(pInitParams->username, NULL); - STRING_PTR_SANITY_CHECK(pInitParams->password, NULL); - - pclient = (iotx_mc_client_t *)LITE_malloc(sizeof(iotx_mc_client_t)); - if (NULL == pclient) { - log_err("not enough memory."); - return NULL; - } - - err = iotx_mc_init(pclient, pInitParams); - if (SUCCESS_RETURN != err) { - LITE_free(pclient); - return NULL; - } - - err = iotx_mc_connect(pclient); - if (SUCCESS_RETURN != err) { - iotx_mc_release(pclient); - LITE_free(pclient); - return NULL; - } -#ifndef MQTT_ID2_AUTH - pclient->mqtt_auth = iotx_guider_authenticate; -#else - pclient->mqtt_auth = iotx_guider_id2_authenticate; -#endif - - /* report module id */ - err = iotx_mc_report_mid(pclient); - if (SUCCESS_RETURN != err) { - iotx_mc_release(pclient); - LITE_free(pclient); - return NULL; - } - - return pclient; -} - -#ifdef MQTT_ID2_AUTH -void *IOT_MQTT_ConstructSecure(iotx_mqtt_param_t *pInitParams) -{ - iotx_mc_client_t *pclient; - - pclient = IOT_MQTT_Construct(pInitParams); - if (NULL == pclient) { - return NULL; - } - - pclient->mqtt_auth = iotx_guider_id2_authenticate; -#ifdef MQTT_ID2_CRYPTO - pclient->mqtt_up_process = iotx_mqtt_id2_payload_encrypt; - pclient->mqtt_down_process = iotx_mqtt_id2_payload_decrypt; -#endif - return pclient; -} -#endif - -int IOT_MQTT_Destroy(void **phandler) -{ - POINTER_SANITY_CHECK(phandler, NULL_VALUE_ERROR); - POINTER_SANITY_CHECK(*phandler, NULL_VALUE_ERROR); - - iotx_mc_release((iotx_mc_client_t *)(*phandler)); - LITE_free(*phandler); - *phandler = NULL; - - return SUCCESS_RETURN; -} - -int IOT_MQTT_Yield(void *handle, int timeout_ms) -{ - int rc = SUCCESS_RETURN; - iotx_mc_client_t *pClient = (iotx_mc_client_t *)handle; - iotx_time_t time; - - POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR); - if (timeout_ms < 0) { - log_err("Invalid argument, timeout_ms = %d", timeout_ms); - return -1; - } - if (timeout_ms == 0) { - timeout_ms = 10; - } - - iotx_time_init(&time); - utils_time_countdown_ms(&time, timeout_ms); - - do { - if (SUCCESS_RETURN != rc) { - unsigned int left_t = iotx_time_left(&time); - log_info("error occur "); - if (left_t < 20) - HAL_SleepMs(left_t); - else - HAL_SleepMs(20); - } - - /* Keep MQTT alive or reconnect if connection abort */ - iotx_mc_keepalive(pClient); - - /* acquire package in cycle, such as PINGRESP or PUBLISH */ - rc = iotx_mc_cycle(pClient, &time); - if (SUCCESS_RETURN == rc) { - /* check list of wait publish ACK to remove node that is ACKED or timeout */ - MQTTPubInfoProc(pClient); - - /* check list of wait subscribe(or unsubscribe) ACK to remove node that is ACKED or timeout */ - MQTTSubInfoProc(pClient); - } - - } while (!utils_time_is_expired(&time)); - - return 0; -} - -/* check whether MQTT connection is established or not */ -int IOT_MQTT_CheckStateNormal(void *handle) -{ - POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR); - return iotx_mc_check_state_normal((iotx_mc_client_t *)handle); -} - -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) -{ - POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR); - POINTER_SANITY_CHECK(topic_handle_func, NULL_VALUE_ERROR); - STRING_PTR_SANITY_CHECK(topic_filter, NULL_VALUE_ERROR); - - if (qos > IOTX_MQTT_QOS2) { - log_warning("Invalid qos(%d) out of [%d, %d], using %d", - qos, - IOTX_MQTT_QOS0, IOTX_MQTT_QOS2, IOTX_MQTT_QOS0); - qos = IOTX_MQTT_QOS0; - } - - return iotx_mc_subscribe((iotx_mc_client_t *)handle, topic_filter, qos, topic_handle_func, pcontext); -} - -int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter) -{ - POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR); - STRING_PTR_SANITY_CHECK(topic_filter, NULL_VALUE_ERROR); - - return iotx_mc_unsubscribe((iotx_mc_client_t *)handle, topic_filter); -} - -int IOT_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg) -{ - POINTER_SANITY_CHECK(handle, NULL_VALUE_ERROR); - STRING_PTR_SANITY_CHECK(topic_name, NULL_VALUE_ERROR); - - return iotx_mc_publish((iotx_mc_client_t *)handle, topic_name, topic_msg); -} diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_client.h b/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_client.h deleted file mode 100644 index a895b8b..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_client.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _IOTX_MQTT_CLIENT_H_ -#define _IOTX_MQTT_CLIENT_H_ -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include - -#include "iot_import.h" -#include "iot_export_mqtt.h" - -/* maximum number of successful subscribe */ -#define IOTX_MC_SUB_NUM_MAX (30) - -/* maximum republish elements in list */ -#define IOTX_MC_REPUB_NUM_MAX (20) - -/* MQTT client version number */ -#define IOTX_MC_MQTT_VERSION (4) - -/* maximum length of topic name in byte */ -#define IOTX_MC_TOPIC_NAME_MAX_LEN (128) - -/* 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 (30) - -/* 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 (60000) - -/* Minimum timeout interval of MQTT request in millisecond */ -#define IOTX_MC_REQUEST_TIMEOUT_MIN_MS (500) - -/* Maximum timeout interval of MQTT request in millisecond */ -#define IOTX_MC_REQUEST_TIMEOUT_MAX_MS (5000) - -/* Default timeout interval of MQTT request in millisecond */ -#define IOTX_MC_REQUEST_TIMEOUT_DEFAULT_MS (2000) - -/* Max times of keepalive which has been send and did not received response package */ -#define IOTX_MC_KEEPALIVE_PROBE_MAX (3) - - -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_t; - - -typedef enum MQTT_NODE_STATE { - IOTX_MC_NODE_STATE_NORMANL = 0, - IOTX_MC_NODE_STATE_INVALID, -} iotx_mc_node_t; - - -/* Handle structure of subscribed topic */ -typedef struct { - const char *topic_filter; - iotx_mqtt_event_handle_t handle; -} iotx_mc_topic_handle_t; - - -/* Information structure of subscribed topic */ -typedef struct SUBSCRIBE_INFO { - enum msgTypes type; /* type, (sub or unsub) */ - uint16_t msg_id; /* packet id of subscribe(unsubcribe) */ - iotx_time_t sub_start_time; /* start time of subscribe request */ - iotx_mc_node_t node_state; /* state of this node */ - iotx_mc_topic_handle_t handler; /* handle of topic subscribed(unsubcribed) */ - uint16_t len; /* length of subscribe message */ - unsigned char *buf; /* subscribe message */ -} iotx_mc_subsribe_info_t, *iotx_mc_subsribe_info_pt; - - -/* 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 */ - unsigned char *buf; /* publish message */ -} iotx_mc_pub_info_t, *iotx_mc_pub_info_pt; - - -/* 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; - -/* 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 buf_size_send; /* send buffer size in byte */ - uint32_t buf_size_read; /* read buffer size in byte */ - uint8_t keepalive_probes; /* keepalive probes */ - char *buf_send; /* pointer of send buffer */ - char *buf_read; /* pointer of read buffer */ - iotx_mc_topic_handle_t sub_handle[IOTX_MC_SUB_NUM_MAX]; /* array of subscribe handle */ - utils_network_pt 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 */ - list_t *list_pub_wait_ack; /* list of wait publish ack */ - list_t *list_sub_wait_ack; /* list of subscribe or unsubscribe ack */ - void *lock_list_pub; /* lock of list of wait publish ack */ - void *lock_list_sub; /* lock of list of subscribe or unsubscribe ack */ - void *lock_write_buf; /* lock of write */ - iotx_mqtt_event_handle_t handle_event; /* event handle */ - int (*mqtt_auth)(void); - int (*mqtt_up_process)(char *topic, iotx_mqtt_topic_info_pt topic_msg); /* process function before mqtt publish */ - int (*mqtt_down_process)(iotx_mqtt_topic_info_pt topic_msg); /* process function while received mqtt publish */ -} iotx_mc_client_t, *iotx_mc_client_pt; - -typedef enum { - TOPIC_NAME_TYPE = 0, - TOPIC_FILTER_TYPE -} iotx_mc_topic_type_t; - - -#if defined(__cplusplus) -} -#endif -#endif /* #ifndef _IOTX_MQTT_CLIENT_H_ */ diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_instance.c b/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_instance.c deleted file mode 100644 index 4aad6d9..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_instance.c +++ /dev/null @@ -1,332 +0,0 @@ -#include -#include -#include -#include -#include - -#include "lite-utils.h" -#include "iot_import.h" -#include "iot_export.h" -#include "iot_export_mqtt.h" - -#include "mqtt_instance.h" - -#define DPRINT(...) \ -do { \ - printf("\033[1;31;40m%s.%d: ", __func__, __LINE__); \ - printf(__VA_ARGS__); \ - printf("\033[0m"); \ -} while (0) - -static void *mqtt_client = NULL; - -static void *mqtt_rbuf = NULL; -static void *mqtt_wbuf = NULL; - -static int abort_request = 0; - -typedef struct mqtt_instance_event_s { - void (*event_cb)(int event, void *ctx); - void *ctx; - - struct mqtt_instance_event_s *next; -} mqtt_instance_event_t; - -static mqtt_instance_event_t *first_event = NULL; - -static void event_list_add(mqtt_instance_event_t *ev) -{ - ev->next = first_event; - first_event = ev; -} - -static void event_list_remove(mqtt_instance_event_t *ev) -{ - mqtt_instance_event_t **ep, *e1; - - /* remove connection from list */ - ep = &first_event; - while ((*ep) != NULL) { - e1 = *ep; - if (e1 == ev) - *ep = ev->next; - else - ep = &e1->next; - } -} - -static void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - int event = 0; - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_RECONNECT: - event = MQTT_INSTANCE_EVENT_CONNECTED; - break; - case IOTX_MQTT_EVENT_DISCONNECT: - event = MQTT_INSTANCE_EVENT_DISCONNECTED; - break; - default: - return; - } - - mqtt_instance_event_t *ev; - for (ev = first_event; ev; ev = ev->next) { - if (ev->event_cb) - ev->event_cb(event, ev->ctx); - } -} - - -void *mqtt_get_instance(void) -{ - return mqtt_client; -} - -void mqtt_remove_instance(void) -{ - mqtt_client = NULL; -} - -int mqtt_set_instance(void* mqtt_t) -{ - if (mqtt_client || mqtt_t == NULL) - return FAIL_RETURN; - - mqtt_client = mqtt_t; - return SUCCESS_RETURN; -} - -/* -* 1: mqtt instance have been init -* 0: mqtt instance init success -* IOT_MQTT_Construct success, MQTT connected. -* -1: mqtt instance init fail -*/ -int mqtt_init_instance(char *productKey, char *deviceName, char *deviceSecret, int maxMsgSize) -{ - if (mqtt_client) - return 1; - - IOT_OpenLog("masterslave"); - IOT_SetLogLevel(IOT_LOG_DEBUG); - - iotx_conn_info_pt pconn_info; - iotx_mqtt_param_t mqtt_params; - - int ret = IOT_SetupConnInfo(productKey, deviceName, deviceSecret, (void **)&pconn_info); - if (ret != SUCCESS_RETURN) - return -1; - - mqtt_rbuf = LITE_malloc(maxMsgSize); - if (!mqtt_rbuf) - return -1; - - mqtt_wbuf = LITE_malloc(maxMsgSize); - if (!mqtt_wbuf) - goto fail; - - /* Initialize MQTT parameter */ - memset(&mqtt_params, 0x0, sizeof(mqtt_params)); - - mqtt_params.port = pconn_info->port; - mqtt_params.host = pconn_info->host_name; - mqtt_params.client_id = pconn_info->client_id; - mqtt_params.username = pconn_info->username; - mqtt_params.password = pconn_info->password; - mqtt_params.pub_key = pconn_info->pub_key; - - mqtt_params.request_timeout_ms = 2000; - mqtt_params.clean_session = 0; - mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = mqtt_rbuf; - mqtt_params.read_buf_size = maxMsgSize; - mqtt_params.pwrite_buf = mqtt_wbuf; - mqtt_params.write_buf_size = maxMsgSize; - - mqtt_params.handle_event.h_fp = event_handle; - mqtt_params.handle_event.pcontext = NULL; - - /* Construct a MQTT client with specify parameter */ - mqtt_client = IOT_MQTT_Construct(&mqtt_params); - if (!mqtt_client) - goto fail; - - return 0; - -fail: - mqtt_deinit_instance(); - return -1; -} - -int mqtt_deinit_instance(void) -{ - abort_request = 1; - - if (mqtt_rbuf) { - LITE_free(mqtt_rbuf); - mqtt_rbuf = NULL; - } - - if (mqtt_wbuf) { - LITE_free(mqtt_wbuf); - mqtt_wbuf = NULL; - } - - if (mqtt_client) { - IOT_MQTT_Destroy(&mqtt_client); - mqtt_client = NULL; - } - - mqtt_instance_event_t *ev, *ev_next; - for (ev = first_event; ev; ev = ev_next) { - ev_next = ev->next; - event_list_remove(ev); - LITE_free(ev); - } - - first_event = NULL; - - abort_request = 0; - - return 0; -} - -int mqtt_set_event_cb(void (*event_cb)(int event, void *ctx), void *ctx) -{ - if (!event_cb) - return -1; - - if (!mqtt_client) - return -1; - - mqtt_instance_event_t *ev = LITE_malloc(sizeof(mqtt_instance_event_t)); - if (!ev) - return -1; - memset(ev, 0, sizeof(mqtt_instance_event_t)); - - ev->event_cb = event_cb; - ev->ctx = ctx; - - event_list_add(ev); - - return 0; -} - -typedef struct mqtt_instance_topic_s { - char *topic; - - void (*cb)(char *topic, int topic_len, void *payload, int payload_len, void *ctx); - void *ctx; - - struct mqtt_instance_topic_s *next; -} mqtt_instance_topic_t; - -static mqtt_instance_topic_t *first_topic = NULL; - -static void topic_list_add(mqtt_instance_topic_t *t) -{ - t->next = first_topic; - first_topic = t; -} - -static void topic_list_remove(mqtt_instance_topic_t *t) -{ - mqtt_instance_topic_t **tp, *t1; - - /* remove connection from list */ - tp = &first_topic; - while ((*tp) != NULL) { - t1 = *tp; - if (t1 == t) - *tp = t->next; - else - tp = &t1->next; - } -} - -static void subscriber_cb(void *ctx, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - mqtt_instance_topic_t *t = ctx; - iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg; - - if (t->cb) { - t->cb((char *)ptopic_info->ptopic, ptopic_info->topic_len, - (void *)ptopic_info->payload , ptopic_info->payload_len, t->ctx); - } -} - -int mqtt_subscribe(char *topic, void (*cb)(char *topic, int topic_len, void *payload, int len, void *ctx), void *ctx) -{ - if (!topic || !cb) - return -1; - - if (!mqtt_client) - return -1; - - mqtt_instance_topic_t *t = LITE_malloc(sizeof(mqtt_instance_topic_t)); - if (!t) - return -1; - memset(t, 0, sizeof(mqtt_instance_topic_t)); - - t->topic = LITE_malloc(strlen(topic) + 1); - if (!t->topic) { - LITE_free(t); - return -1; - } - strcpy(t->topic, topic); - - t->cb = cb; - t->ctx = ctx; - - int ret = IOT_MQTT_Subscribe(mqtt_client, t->topic, IOTX_MQTT_QOS1, subscriber_cb, t); - if (ret < 0) { - LITE_free(t->topic); - LITE_free(t); - return -1; - } - - topic_list_add(t); - - return 0; -} - -int mqtt_unsubscribe(char *topic) -{ - mqtt_instance_topic_t *t, *t_next; - - for (t = first_topic; t; t = t_next) { - t_next = t->next; - - if (strcmp(t->topic, topic) == 0) { - if (mqtt_client) IOT_MQTT_Unsubscribe(mqtt_client, topic); - topic_list_remove(t); - LITE_free(t->topic); - LITE_free(t); - } - } - - return 0; -} - -int mqtt_publish(char *topic, int qos, void *data, int len) -{ - iotx_mqtt_topic_info_t mqtt_msg; - - if (!mqtt_client) - return -1; - 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; - - if (IOT_MQTT_Publish(mqtt_client, topic, &mqtt_msg) < 0) { - DPRINT("IOT_MQTT_Publish failed\n"); - return -1; - } - - return 0; -} diff --git a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_instance.h b/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_instance.h deleted file mode 100644 index 2f2ac81..0000000 --- a/iotkit-embedded/src/mqtt/Link-MQTT/mqtt_instance.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef __MQTT_INSTANCE_H__ -#define __MQTT_INSTANCE_H__ - -enum { - MQTT_INSTANCE_EVENT_DISCONNECTED = 0, - MQTT_INSTANCE_EVENT_CONNECTED = 1, -}; - - -/** - * @brief Get the mqtt singleton instance. - * - * @param None - * - * @retval NULL : failed - * @retval NOT_NULL : The singleton instance of mqtt client. - * @see None. - */ -void *mqtt_get_instance(void); - - -/** - * @brief Remove the mqtt singleton instance. - * - * @param None - * - * @retval None - * @see None. - */ -void mqtt_remove_instance(void); - - -/** - * @brief Set the mqtt singleton instance. - * - * @param None - * - * @retval -1: - * @retval 0: - * @see None. - */ -int mqtt_set_instance(void* mqtt_t); - - - -/** - * @brief Initialize the mqtt singleton instance. - * - * @param [in] productKey - * @param [in] deviceName - * @param [in] deviceSecret - * @param [in] maxMsgSize: mqtt read/send buffer size - * - * @retval 1: mqtt instance have been init - * @retval 0: mqtt instance init success - * IOT_MQTT_Construct success, MQTT connected. - * @retval -1: mqtt instance init fail - * @see None. - */ -int mqtt_init_instance(char *productKey, char *deviceName, char *deviceSecret, int maxMsgSize); - - -/** - * @brief Deinitialize the mqtt singleton instance. - * - * - * @retval 0: success - * @retval -1: fail - * @see None. - */ -int mqtt_deinit_instance(void); - - -/** - * @brief Set mqtt event callback. - * - * @param [in] event callback - * @param [in] user data - * - * @retval 0: success - * @retval -1: fail - * @see None. - */ -int mqtt_set_event_cb(void (*event)(int event, void *ctx), void *ctx); - - -/** - * @brief Subscribe topic. - * - * @param [in] topic - * @param [in] callback - * @param [in] user data - * - * @retval 0: success - * @retval -1: fail - * @see None. - */ -int mqtt_subscribe(char *topic, void (*cb)(char *topic, int topic_len, void *payload, int payload_len, void *ctx), void *ctx); - - -/** - * @brief Unsubscribe topic. - * - * @param [in] topic - * - * @retval 0: success - * @retval -1: fail - * @see None. - */ -int mqtt_unsubscribe(char *topic); - - -/** - * @brief Publish packet. - * - * @param [in] topic - * @param [in] qos - * @param [in] payload data - * @param [in] payload data length - * - * @retval 0: success - * @retval -1: fail - * @see None. - */ -int mqtt_publish(char *topic, int qos, void *data, int len); - -#endif /* __MQTT_INSTANCE_H__ */ diff --git a/iotkit-embedded/src/mqtt/examples/mqtt_example.c b/iotkit-embedded/src/mqtt/examples/mqtt_example.c new file mode 100644 index 0000000..2aa24ba --- /dev/null +++ b/iotkit-embedded/src/mqtt/examples/mqtt_example.c @@ -0,0 +1,250 @@ +#include "dev_sign_api.h" +#include "mqtt_api.h" + +char DEMO_PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0}; +char DEMO_DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0}; +char DEMO_DEVICE_SECRET[IOTX_DEVICE_SECRET_LEN + 1] = {0}; + +void *HAL_Malloc(uint32_t size); +void HAL_Free(void *ptr); +void HAL_Printf(const char *fmt, ...); +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]); +uint64_t HAL_UptimeMs(void); +int HAL_Snprintf(char *str, const int len, const char *fmt, ...); + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while(0) + +void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) +{ + iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt) msg->msg; + + switch (msg->event_type) { + case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: + /* print topic name and topic message */ + EXAMPLE_TRACE("Message Arrived:"); + EXAMPLE_TRACE("Topic : %.*s", topic_info->topic_len, topic_info->ptopic); + EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload); + EXAMPLE_TRACE("\n"); + break; + default: + break; + } +} + +int example_subscribe(void *handle) +{ + int res = 0; + const char *fmt = "/%s/%s/user/get"; + char *topic = NULL; + int topic_len = 0; + + topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1; + topic = HAL_Malloc(topic_len); + if (topic == NULL) { + EXAMPLE_TRACE("memory not enough"); + return -1; + } + memset(topic, 0, topic_len); + HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME); + + res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL); + if (res < 0) { + EXAMPLE_TRACE("subscribe failed"); + HAL_Free(topic); + return -1; + } + + HAL_Free(topic); + return 0; +} + +int example_publish(void *handle) +{ + int res = 0; + const char *fmt = "/%s/%s/user/get"; + char *topic = NULL; + int topic_len = 0; + char *payload = "{\"message\":\"hello!\"}"; + + topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1; + topic = HAL_Malloc(topic_len); + if (topic == NULL) { + EXAMPLE_TRACE("memory not enough"); + return -1; + } + memset(topic, 0, topic_len); + HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME); + + res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, payload, strlen(payload)); + if (res < 0) { + EXAMPLE_TRACE("publish failed, res = %d", res); + HAL_Free(topic); + return -1; + } + + HAL_Free(topic); + return 0; +} + +void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) +{ + EXAMPLE_TRACE("msg->event_type : %d", msg->event_type); +} + +/* + * NOTE: About demo topic of /${productKey}/${deviceName}/user/get + * + * The demo device has been configured in IoT console (https://iot.console.aliyun.com) + * so that its /${productKey}/${deviceName}/user/get can both be subscribed and published + * + * We design this to completely demonstrate publish & subscribe process, in this way + * MQTT client can receive original packet sent by itself + * + * For new devices created by yourself, pub/sub privilege also requires being granted + * to its /${productKey}/${deviceName}/user/get for successfully running whole example + */ + +int main(int argc, char *argv[]) +{ + void *pclient = NULL; + int res = 0; + int loop_cnt = 0; + iotx_mqtt_param_t mqtt_params; + + HAL_GetProductKey(DEMO_PRODUCT_KEY); + HAL_GetDeviceName(DEMO_DEVICE_NAME); + HAL_GetDeviceSecret(DEMO_DEVICE_SECRET); + + EXAMPLE_TRACE("mqtt example"); + + /* Initialize MQTT parameter */ + /* + * Note: + * + * If you did NOT set value for members of mqtt_params, SDK will use their default values + * If you wish to customize some parameter, just un-comment value assigning expressions below + * + **/ + memset(&mqtt_params, 0x0, sizeof(mqtt_params)); + + /** + * + * MQTT connect hostname string + * + * MQTT server's hostname can be customized here + * + * default value is ${productKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com + */ + /* mqtt_params.host = "something.iot-as-mqtt.cn-shanghai.aliyuncs.com"; */ + + /** + * + * MQTT connect port number + * + * TCP/TLS port which can be 443 or 1883 or 80 or etc, you can customize it here + * + * default value is 1883 in TCP case, and 443 in TLS case + */ + /* mqtt_params.port = 1883; */ + + /** + * + * MQTT request timeout interval + * + * MQTT message request timeout for waiting ACK in MQTT Protocol + * + * default value is 2000ms. + */ + /* mqtt_params.request_timeout_ms = 2000; */ + + /** + * + * MQTT clean session flag + * + * If CleanSession is set to 0, the Server MUST resume communications with the Client based on state from + * the current Session (as identified by the Client identifier). + * + * If CleanSession is set to 1, the Client and Server MUST discard any previous Session and Start a new one. + * + * default value is 0. + */ + /* mqtt_params.clean_session = 0; */ + + /** + * + * MQTT keepAlive interval + * + * KeepAlive is the maximum time interval that is permitted to elapse between the point at which + * the Client finishes transmitting one Control Packet and the point it starts sending the next. + * + * default value is 60000. + */ + /* mqtt_params.keepalive_interval_ms = 60000; */ + + /** + * + * MQTT write buffer size + * + * Write buffer is allocated to place upstream MQTT messages, MQTT client will be limitted + * to send packet no longer than this to Cloud + * + * default value is 1024. + * + */ + /* mqtt_params.write_buf_size = 1024; */ + + /** + * + * MQTT read buffer size + * + * Write buffer is allocated to place downstream MQTT messages, MQTT client will be limitted + * to recv packet no longer than this from Cloud + * + * default value is 1024. + * + */ + /* mqtt_params.read_buf_size = 1024; */ + + /** + * + * MQTT event callback function + * + * Event callback function will be called by SDK when it want to notify user what is happening inside itself + * + * default value is NULL, which means PUB/SUB event won't be exposed. + * + */ + mqtt_params.handle_event.h_fp = example_event_handle; + + pclient = IOT_MQTT_Construct(&mqtt_params); + if (NULL == pclient) { + EXAMPLE_TRACE("MQTT construct failed"); + return -1; + } + + res = example_subscribe(pclient); + if (res < 0) { + IOT_MQTT_Destroy(&pclient); + return -1; + } + + while (1) { + if (0 == loop_cnt % 20) { + example_publish(pclient); + } + + IOT_MQTT_Yield(pclient, 200); + + loop_cnt += 1; + } + + return 0; +} + diff --git a/iotkit-embedded/src/mqtt/examples/mqtt_example_at.c b/iotkit-embedded/src/mqtt/examples/mqtt_example_at.c new file mode 100644 index 0000000..3e2085b --- /dev/null +++ b/iotkit-embedded/src/mqtt/examples/mqtt_example_at.c @@ -0,0 +1,212 @@ +#include +#include + +#include "dev_sign_api.h" +#include "mqtt_api.h" + +#ifdef ATM_ENABLED + #include "at_api.h" +#endif + +static char g_topic_name[CONFIG_MQTT_TOPIC_MAXLEN]; + +void HAL_Printf(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]); +uint64_t HAL_UptimeMs(void); +int HAL_Snprintf(char *str, const int len, const char *fmt, ...); + +#define EXAMPLE_TRACE(fmt, ...) \ + do { \ + HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ + HAL_Printf(fmt, ##__VA_ARGS__); \ + HAL_Printf("%s", "\r\n"); \ + } while(0) + +void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) +{ + iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt) msg->msg; + + switch (msg->event_type) { + case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: + /* print topic name and topic message */ + HAL_Printf("Message Arrived: \n"); + HAL_Printf("Topic : %.*s\n", topic_info->topic_len, topic_info->ptopic); + HAL_Printf("Payload: %.*s\n", topic_info->payload_len, topic_info->payload); + HAL_Printf("\n"); + break; + default: + break; + } +} + +int example_subscribe(void *handle) +{ + int res = 0; + char product_key[IOTX_PRODUCT_KEY_LEN] = {0}; + char device_name[IOTX_DEVICE_NAME_LEN] = {0}; + const char *fmt = "/%s/%s/user/get"; + char *topic = NULL; + int topic_len = 0; + + HAL_GetProductKey(product_key); + HAL_GetDeviceName(device_name); + + topic_len = strlen(fmt) + strlen(product_key) + strlen(device_name) + 1; + if (topic_len > CONFIG_MQTT_TOPIC_MAXLEN) { + HAL_Printf("topic too long\n"); + return -1; + } + topic = g_topic_name; + memset(topic, 0, CONFIG_MQTT_TOPIC_MAXLEN); + HAL_Snprintf(topic, topic_len, fmt, product_key, device_name); + + res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL); + if (res < 0) { + HAL_Printf("subscribe failed\n"); + return -1; + } + + return 0; +} + +int example_publish(void *handle) +{ + int res = 0; + iotx_mqtt_topic_info_t topic_msg; + char product_key[IOTX_PRODUCT_KEY_LEN] = {0}; + char device_name[IOTX_DEVICE_NAME_LEN] = {0}; + const char *fmt = "/%s/%s/user/get"; + char *topic = NULL; + int topic_len = 0; + char *payload = "hello,world"; + + HAL_GetProductKey(product_key); + HAL_GetDeviceName(device_name); + + topic_len = strlen(fmt) + strlen(product_key) + strlen(device_name) + 1; + if (topic_len > CONFIG_MQTT_TOPIC_MAXLEN) { + HAL_Printf("topic too long\n"); + return -1; + } + topic = g_topic_name; + memset(topic, 0, CONFIG_MQTT_TOPIC_MAXLEN); + HAL_Snprintf(topic, topic_len, fmt, product_key, device_name); + + + memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); + topic_msg.qos = IOTX_MQTT_QOS0; + topic_msg.retain = 0; + topic_msg.dup = 0; + topic_msg.payload = (void *)payload; + topic_msg.payload_len = strlen(payload); + + res = IOT_MQTT_Publish(handle, topic, &topic_msg); + if (res < 0) { + HAL_Printf("publish failed\n"); + return -1; + } + + return 0; +} + +void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) +{ + HAL_Printf("msg->event_type : %d\n", msg->event_type); +} + +/* + * NOTE: About demo topic of /${productKey}/${deviceName}/user/get + * + * The demo device has been configured in IoT console (https://iot.console.aliyun.com) + * so that its /${productKey}/${deviceName}/user/get can both be subscribed and published + * + * We design this to completely demostrate publish & subscribe process, in this way + * MQTT client can receive original packet sent by itself + * + * For new devices created by yourself, pub/sub privilege also required to be granted + * to its /${productKey}/${deviceName}/user/get to run whole example + */ + +int main(int argc, char *argv[]) +{ + void *pclient = NULL; + int res = 0; + int loop_cnt = 0; + + iotx_mqtt_region_types_t region = IOTX_CLOUD_REGION_SHANGHAI; + iotx_sign_mqtt_t sign_mqtt; + iotx_dev_meta_info_t meta; + iotx_mqtt_param_t mqtt_params; + +#ifdef ATM_ENABLED + if (IOT_ATM_Init() < 0) { + HAL_Printf("IOT ATM init failed!\n"); + return -1; + } +#endif + HAL_Printf("mqtt example\n"); + + memset(&meta, 0, sizeof(iotx_dev_meta_info_t)); + HAL_GetProductKey(meta.product_key); + HAL_GetDeviceName(meta.device_name); + HAL_GetDeviceSecret(meta.device_secret); + + memset(&sign_mqtt, 0x0, sizeof(iotx_sign_mqtt_t)); + + if (IOT_Sign_MQTT(region, &meta, &sign_mqtt) < 0) { + return -1; + } + +#if 0 /* Uncomment this to show more information */ + HAL_Printf("sign_mqtt.hostname: %s\n", sign_mqtt.hostname); + HAL_Printf("sign_mqtt.port : %d\n", sign_mqtt.port); + HAL_Printf("sign_mqtt.username: %s\n", sign_mqtt.username); + HAL_Printf("sign_mqtt.password: %s\n", sign_mqtt.password); + HAL_Printf("sign_mqtt.clientid: %s\n", sign_mqtt.clientid); +#endif + + /* Initialize MQTT parameter */ + memset(&mqtt_params, 0x0, sizeof(mqtt_params)); + + mqtt_params.port = sign_mqtt.port; + mqtt_params.host = sign_mqtt.hostname; + mqtt_params.client_id = sign_mqtt.clientid; + mqtt_params.username = sign_mqtt.username; + mqtt_params.password = sign_mqtt.password; + + mqtt_params.request_timeout_ms = 2000; + mqtt_params.clean_session = 0; + mqtt_params.keepalive_interval_ms = 60000; + mqtt_params.read_buf_size = 1024; + mqtt_params.write_buf_size = 1024; + + mqtt_params.handle_event.h_fp = example_event_handle; + mqtt_params.handle_event.pcontext = NULL; + + pclient = IOT_MQTT_Construct(&mqtt_params); + if (NULL == pclient) { + EXAMPLE_TRACE("MQTT construct failed"); + return -1; + } + + res = example_subscribe(pclient); + if (res < 0) { + IOT_MQTT_Destroy(&pclient); + return -1; + } + + while (1) { + if (0 == loop_cnt % 20) { + example_publish(pclient); + } + + IOT_MQTT_Yield(pclient, 200); + + loop_cnt += 1; + } + + return 0; +} + diff --git a/iotkit-embedded/src/mqtt/impl/MQTTConnect.h b/iotkit-embedded/src/mqtt/impl/MQTTConnect.h new file mode 100644 index 0000000..20ec833 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTConnectClient.c b/iotkit-embedded/src/mqtt/impl/MQTTConnectClient.c new file mode 100644 index 0000000..71cb8ac --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTDeserializePublish.c b/iotkit-embedded/src/mqtt/impl/MQTTDeserializePublish.c new file mode 100644 index 0000000..9713db3 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTPacket.c b/iotkit-embedded/src/mqtt/impl/MQTTPacket.c new file mode 100644 index 0000000..931a930 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTPacket.h b/iotkit-embedded/src/mqtt/impl/MQTTPacket.h new file mode 100644 index 0000000..e93dfc5 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTPublish.h b/iotkit-embedded/src/mqtt/impl/MQTTPublish.h new file mode 100644 index 0000000..4cb4e6a --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTSerializePublish.c b/iotkit-embedded/src/mqtt/impl/MQTTSerializePublish.c new file mode 100644 index 0000000..4c068b7 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTSubscribe.h b/iotkit-embedded/src/mqtt/impl/MQTTSubscribe.h new file mode 100644 index 0000000..ecd04d6 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTSubscribeClient.c b/iotkit-embedded/src/mqtt/impl/MQTTSubscribeClient.c new file mode 100644 index 0000000..4a26ca2 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTUnsubscribe.h b/iotkit-embedded/src/mqtt/impl/MQTTUnsubscribe.h new file mode 100644 index 0000000..ab44911 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/MQTTUnsubscribeClient.c b/iotkit-embedded/src/mqtt/impl/MQTTUnsubscribeClient.c new file mode 100644 index 0000000..2463a4d --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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/iotkit-embedded/src/mqtt/impl/iotx_mqtt_client.c b/iotkit-embedded/src/mqtt/impl/iotx_mqtt_client.c new file mode 100644 index 0000000..0576da2 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/iotx_mqtt_client.c @@ -0,0 +1,3179 @@ +/* + * 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 = MQTT_CPT_RESERVED; + 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); + *packet_type = MQTT_CPT_RESERVED; + 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; + int userKeepAliveInterval = 0; + + if (NULL == pClient) { + return NULL_VALUE_ERROR; + } + userKeepAliveInterval = pClient->connect_data.keepAliveInterval; + pClient->connect_data.keepAliveInterval = CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX; + 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); + pClient->connect_data.keepAliveInterval = userKeepAliveInterval; + + 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; + } + pClient->keepalive_probes = 0; + 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; + + if (topicName.lenstring.len == 0 || topicName.lenstring.data == NULL) { + mqtt_err("Null topicName"); + return MQTT_PUBLISH_PACKET_ERROR; + } + +#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->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->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 */ + 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; + int qos_sub = (int)qos; + 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_sub); + 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/iotkit-embedded/src/mqtt/impl/iotx_mqtt_client.h b/iotkit-embedded/src/mqtt/impl/iotx_mqtt_client.h new file mode 100644 index 0000000..3a31373 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/iotx_mqtt_client.h @@ -0,0 +1,170 @@ +/* + * 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 */ + 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/iotkit-embedded/src/mqtt/impl/iotx_mqtt_config.h b/iotkit-embedded/src/mqtt/impl/iotx_mqtt_config.h new file mode 100644 index 0000000..c135d7e --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/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 (60000) + +/* Max times of keepalive which has been send and did not received response package */ +#define IOTX_MC_KEEPALIVE_PROBE_MAX (2) + + +/* 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/iotkit-embedded/src/mqtt/impl/mqtt_internal.h b/iotkit-embedded/src/mqtt/impl/mqtt_internal.h new file mode 100644 index 0000000..1dd3507 --- /dev/null +++ b/iotkit-embedded/src/mqtt/impl/mqtt_internal.h @@ -0,0 +1,46 @@ +/* + * 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_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/iotkit-embedded/src/mqtt/iot.mk b/iotkit-embedded/src/mqtt/iot.mk index 787ec17..c5f26e2 100644 --- a/iotkit-embedded/src/mqtt/iot.mk +++ b/iotkit-embedded/src/mqtt/iot.mk @@ -1,5 +1,13 @@ -LIBA_TARGET := libiot_mqtt.a -HDR_REFS := src +LIBA_TARGET := libiot_mqtt.a +HDR_REFS := src/infra +LIB_SRCS_PATTERN := *.c -PKG_SOURCE := Link-MQTT.git -PKG_UPSTREAM := git@gitlab.alibaba-inc.com:iot-middleware/Link-MQTT.git +SRCS_mqtt-example := examples/mqtt_example.c +SRCS_mqtt-example-at := examples/mqtt_example_at.c + +$(call Append_Conditional, LIB_SRCS_PATTERN, impl/*.c, MQTT_DEFAULT_IMPL) +$(call Append_Conditional, TARGET, mqtt-example, MQTT_COMM_ENABLED, ATM_ENABLED BUILD_AOS NO_EXECUTABLES) +$(call Append_Conditional, TARGET, mqtt-example-at, ATM_ENABLED BUILD_AOS NO_EXECUTABLES) + +DEPENDS += external_libs/mbedtls +LDFLAGS += -liot_sdk -liot_hal -liot_tls diff --git a/iotkit-embedded/src/mqtt/mqtt_api.c b/iotkit-embedded/src/mqtt/mqtt_api.c new file mode 100644 index 0000000..aaa8930 --- /dev/null +++ b/iotkit-embedded/src/mqtt/mqtt_api.c @@ -0,0 +1,831 @@ +#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" + +#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; +static char iotx_ca_crt_itls[IOTX_PRODUCT_KEY_LEN + IOTX_PRODUCT_SECRET_LEN + 2] = {0}; + +/* 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 _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_pre_auth_output_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_pre_auth_output_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 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 */ + +extern int _sign_get_clientid(char *clientid_string, const char *device_id, const char *custom_kv, uint8_t enable_itls); + +/************************ 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; + char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = {0}; + int region = 0; + int dynamic = 0; + uint8_t enalbe_itls = 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_pre_auth_output_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 */ + + /* setup device_id */ + memcpy(device_id, meta_info.product_key, strlen(meta_info.product_key)); + memcpy(device_id + strlen(device_id), ".", strlen(".")); + memcpy(device_id + strlen(device_id), meta_info.device_name, strlen(meta_info.device_name)); + + /* reconfig clientid, append custome clientKV and itls switch flag */ + if (pInitParams != NULL && pInitParams->customize_info != NULL) { + if (strstr(pInitParams->customize_info, "authtype=id2") != NULL) { + enalbe_itls = 1; + } + else { + enalbe_itls = 0; + } + } + + if (_sign_get_clientid(g_default_sign.clientid, device_id, + (pInitParams != NULL) ? pInitParams->customize_info : NULL, enalbe_itls) != SUCCESS_RETURN) { + return NULL; + } + + /* Initialize MQTT parameter */ + memset(&mqtt_params, 0x0, sizeof(iotx_mqtt_param_t)); + +#ifdef SUPPORT_TLS + { + extern const char *iotx_ca_crt; + if (enalbe_itls == 0) { + mqtt_params.pub_key = iotx_ca_crt; + } + else { + memset(iotx_ca_crt_itls, 0, sizeof(iotx_ca_crt_itls)); + HAL_GetProductKey(iotx_ca_crt_itls); + iotx_ca_crt_itls[strlen(iotx_ca_crt_itls)] = '.'; + HAL_GetProductSecret(iotx_ca_crt_itls + strlen(iotx_ca_crt_itls)); + mqtt_params.pub_key = iotx_ca_crt_itls; + } + } +#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)(); + } + + 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/iotkit-embedded/src/sdk-impl/exports/iot_export_mqtt.h b/iotkit-embedded/src/mqtt/mqtt_api.h similarity index 67% rename from iotkit-embedded/src/sdk-impl/exports/iot_export_mqtt.h rename to iotkit-embedded/src/mqtt/mqtt_api.h index eeff864..54e8a3b 100644 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_mqtt.h +++ b/iotkit-embedded/src/mqtt/mqtt_api.h @@ -1,30 +1,25 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * 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_QOS2, + IOTX_MQTT_QOS3_SUB_LOCAL } iotx_mqtt_qos_t; typedef enum { @@ -66,7 +61,7 @@ typedef enum { IOTX_MQTT_EVENT_PUBLISH_NACK = 11, /* MQTT packet published from MQTT remote broker be received */ - IOTX_MQTT_EVENT_PUBLISH_RECVEIVED = 12, + 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, @@ -79,11 +74,12 @@ typedef struct { uint8_t dup; uint8_t retain; uint16_t topic_len; - uint16_t payload_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 */ @@ -108,8 +104,8 @@ typedef struct { * IOTX_MQTT_EVENT_PUBLISH_NACK : * Its data type is @uint32_t and the value is MQTT packet identifier. * - * 3) IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - * Its data type is @iotx_mqtt_packet_info_t and see detail at the declare of this type. + * 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; @@ -144,26 +140,36 @@ typedef struct { const char *client_id; /* Specify MQTT connection client id*/ const char *username; /* Specify MQTT user name */ const char *password; /* Specify MQTT password */ - + const char *customize_info; /* Specify User custom information */ /* 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 */ - - char *pwrite_buf; /* Specify write-buffer */ uint32_t write_buf_size; /* Specify size of write-buffer in byte */ - char *pread_buf; /* Specify read-buffer */ 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 * @{ */ @@ -184,18 +190,6 @@ typedef struct { */ void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams); -/** - * @brief Construct the MQTT client by ID2 - * This function initialize the data structures, establish MQTT connection. - * And set mqtt up/down process functions. - * - * @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_ConstructSecure(iotx_mqtt_param_t *pInitParams); /** * @brief Deconstruct the MQTT client @@ -222,7 +216,6 @@ int IOT_MQTT_Destroy(void **phandle); */ int IOT_MQTT_Yield(void *handle, int timeout_ms); - /** * @brief check whether MQTT connection is established or not. * @@ -236,25 +229,35 @@ int IOT_MQTT_CheckStateNormal(void *handle); /** - * @brief disable MQTT auto-reconnect. + * @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 0 : Success. - * @retval -1 : Failed. + * @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_Disable_Reconnect(void *handle); - +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. + * @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. @@ -262,11 +265,12 @@ int IOT_MQTT_Disable_Reconnect(void *handle); 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); +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); /** @@ -299,9 +303,84 @@ int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter); * @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 (1200) + +#if defined(__cplusplus) +} +#endif +#endif + + diff --git a/iotkit-embedded/src/mqtt/mqtt_wrapper.h b/iotkit-embedded/src/mqtt/mqtt_wrapper.h new file mode 100644 index 0000000..0f228d2 --- /dev/null +++ b/iotkit-embedded/src/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_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]); +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 + 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/iotkit-embedded/src/ota/Link-OTA/ota_internal.h b/iotkit-embedded/src/ota/Link-OTA/ota_internal.h deleted file mode 100644 index 140fce9..0000000 --- a/iotkit-embedded/src/ota/Link-OTA/ota_internal.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef _OTA_INTERNAL_H_ -#define _OTA_INTERNAL_H_ - -typedef void (*ota_cb_fpt)(void *pcontext, const char *msg, uint32_t msg_len); - -#endif /* _OTA_INTERNAL_H_ */ diff --git a/iotkit-embedded/src/ota/Link-OTA/src/ota.c b/iotkit-embedded/src/ota/Link-OTA/src/ota.c deleted file mode 100644 index b94b8a5..0000000 --- a/iotkit-embedded/src/ota/Link-OTA/src/ota.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -#include "iot_import_ota.h" -#include "iot_export_ota.h" -#include "ota_internal.h" - - -#include "ota_lib.c" - -#if (OTA_SIGNAL_CHANNEL) == 1 - #include "ota_mqtt.c" -#elif (OTA_SIGNAL_CHANNEL) == 2 - #include "ota_coap.c" -#else - #error "NOT support yet!" -#endif - -#include "ota_fetch.c" - -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 */ - 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 *ch_signal; /* channel handle of signal exchanged with OTA server */ - void *ch_fetch; /* channel handle of download */ - - int err; /* last error code */ - -} 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)); -} - - -static void ota_callback(void *pcontext, const char *msg, uint32_t msg_len) -{ - 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 or downloaded state"); - return; - } - - pvalue = otalib_JsonValueOf(msg, msg_len, "message", &val_len); - if (NULL == pvalue) { - OTA_LOG_ERROR("invalid json doc of OTA "); - return; - } - - /* 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 ; - } - - /* 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; - } - - if (0 != otalib_GetParams(pvalue, val_len, &h_ota->purl, &h_ota->version, h_ota->md5sum, &h_ota->size_file)) { - OTA_LOG_ERROR("Get firmware parameter failed"); - return; - } - - if (NULL == (h_ota->ch_fetch = ofc_Init(h_ota->purl))) { - OTA_LOG_ERROR("Initialize fetch module failed"); - return ; - } - - h_ota->state = IOT_OTAS_FETCHING; -} - - -/* 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 ((NULL == product_key) || (NULL == device_name) || (NULL == ch_signal)) { - 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->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->product_key = product_key; - h_ota->device_name = device_name; - h_ota->state = IOT_OTAS_INITED; - 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) { - 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; - } - - osc_Deinit(h_ota->ch_signal); - ofc_Deinit(h_ota->ch_fetch); - otalib_MD5Deinit(h_ota->md5); - - if (NULL != h_ota->purl) { - OTA_FREE(h_ota->purl); - } - - if (NULL != h_ota->version) { - OTA_FREE(h_ota->version); - } - - 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 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 -} - - -/* 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_ms) -{ - 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_ms); - if (ret < 0) { - OTA_LOG_ERROR("Fetch firmware failed"); - h_ota->state = IOT_OTAS_FETCHED; - h_ota->err = IOT_OTAE_FETCH_FAILED; - 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"); - } - - h_ota->size_last_fetched = ret; - h_ota->size_fetched += ret; - - if (h_ota->size_fetched >= h_ota->size_file) { - h_ota->state = IOT_OTAS_FETCHED; - } - - otalib_MD5Update(h_ota->md5, buf, ret); - - return ret; -} - - -int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, size_t 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_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; - } - 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/iotkit-embedded/src/ota/Link-OTA/src/ota_mqtt.c b/iotkit-embedded/src/ota/Link-OTA/src/ota_mqtt.c deleted file mode 100644 index c199eb4..0000000 --- a/iotkit-embedded/src/ota/Link-OTA/src/ota_mqtt.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __OTA_MQTT_C_H__ -#define __OTA_MQTT_C_H__ - - -#include "iot_export_ota.h" -#include "iot_import_ota.h" -#include "ota_internal.h" - -/* OSC, OTA signal channel */ - -/* Specify the maximum characters of version */ -#define OTA_MQTT_TOPIC_LEN (64) - -typedef struct { - void *mqtt; - const char *product_key; - const char *device_name; - char topic_upgrade[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); - - OTA_ASSERT(ret < buf_len); - - 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; -} - - -/* 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); - - OTA_ASSERT(IOTX_MQTT_EVENT_PUBLISH_RECVEIVED == msg->event_type); - - if (NULL != handle->cb) { - handle->cb(handle->context, topic_info->payload, topic_info->payload_len); - } -} - - -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/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; - } - - 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); -} - -#endif diff --git a/iotkit-embedded/sample/ota/ota_mqtt-example.c b/iotkit-embedded/src/ota/examples/ota_example_mqtt.c similarity index 73% rename from iotkit-embedded/sample/ota/ota_mqtt-example.c rename to iotkit-embedded/src/ota/examples/ota_example_mqtt.c index 8003348..d6f820f 100644 --- a/iotkit-embedded/sample/ota/ota_mqtt-example.c +++ b/iotkit-embedded/src/ota/examples/ota_example_mqtt.c @@ -1,58 +1,29 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ - #include #include #include #include -#include "iot_import.h" -#include "iot_export.h" - -#if defined(MQTT_ID2_AUTH) && defined(TEST_ID2_DAILY) - #define PRODUCT_KEY "OvNmiEYRDSY" - #define DEVICE_NAME "sh_online_sample_mqtt" - #define DEVICE_SECRET "v9mqGzepKEphLhXmAoiaUIR2HZ7XwTky" -#elif defined(TEST_OTA_PRE) - #define PRODUCT_KEY "6RcIOUafDOm" - #define DEVICE_NAME "sh_pre_sample_mqtt" - #define DEVICE_SECRET "R0OTtD46DSalSpGW7SFzFDIA6fksTC2c" -#elif defined(TEST_MQTT_DAILY) - #define PRODUCT_KEY "fR9zCD4oT72" - #define DEVICE_NAME "ota_test" - #define DEVICE_SECRET "67szT5tQNMIu3sbrd3UwLhs7M73wTHXQ" -#else - #define PRODUCT_KEY "yfTuLfBJTiL" - #define DEVICE_NAME "TestDeviceForDemo" - #define DEVICE_SECRET "fSCl9Ns5YPnYN8Ocg0VEel1kXFnRlV6c" -#endif - -char g_product_key[PRODUCT_KEY_LEN + 1]; -char g_product_secret[PRODUCT_SECRET_LEN + 1]; -char g_device_name[DEVICE_NAME_LEN + 1]; -char g_device_secret[DEVICE_SECRET_LEN + 1]; - -/* These are pre-defined topics */ -#define TOPIC_UPDATE "/"PRODUCT_KEY"/"DEVICE_NAME"/update" -#define TOPIC_ERROR "/"PRODUCT_KEY"/"DEVICE_NAME"/update/error" -#define TOPIC_GET "/"PRODUCT_KEY"/"DEVICE_NAME"/get" -#define TOPIC_DATA "/"PRODUCT_KEY"/"DEVICE_NAME"/data" +#include "infra_compat.h" +#include "mqtt_api.h" +#include "ota_api.h" + +void *HAL_Malloc(uint32_t size); +void HAL_Free(void *ptr); + +void HAL_Printf(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]); +void HAL_SleepMs(uint32_t ms); + +char g_product_key[IOTX_PRODUCT_KEY_LEN + 1]; +char g_product_secret[IOTX_PRODUCT_SECRET_LEN + 1]; +char g_device_name[IOTX_DEVICE_NAME_LEN + 1]; +char g_device_secret[IOTX_DEVICE_SECRET_LEN + 1]; #define OTA_MQTT_MSGLEN (2048) @@ -120,7 +91,7 @@ void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) EXAMPLE_TRACE("publish nack, packet-id=%u", (unsigned int)packet_id); break; - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: + case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: EXAMPLE_TRACE("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", topic_info->topic_len, topic_info->ptopic, @@ -134,7 +105,7 @@ void event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) } } -int mqtt_client(void) +static int _ota_mqtt_client(void) { #define OTA_BUF_LEN (5000) @@ -190,9 +161,7 @@ int mqtt_client(void) mqtt_params.request_timeout_ms = 2000; mqtt_params.clean_session = 0; mqtt_params.keepalive_interval_ms = 60000; - mqtt_params.pread_buf = msg_readbuf; mqtt_params.read_buf_size = OTA_MQTT_MSGLEN; - mqtt_params.pwrite_buf = msg_buf; mqtt_params.write_buf_size = OTA_MQTT_MSGLEN; mqtt_params.handle_event.h_fp = event_handle; @@ -206,18 +175,18 @@ int mqtt_client(void) rc = -1; goto do_exit; } - h_ota = IOT_OTA_Init(PRODUCT_KEY, DEVICE_NAME, pclient); + h_ota = IOT_OTA_Init(g_product_key, g_device_name, pclient); if (NULL == h_ota) { rc = -1; EXAMPLE_TRACE("initialize OTA failed"); goto do_exit; } - if (0 != IOT_OTA_ReportVersion(h_ota, "iotx_ver_1.0.0")) { - rc = -1; - EXAMPLE_TRACE("report OTA version failed"); - goto do_exit; - } + /* if (0 != IOT_OTA_ReportVersion(h_ota, "iotx_ver_1.1.0")) { */ + /* rc = -1; */ + /* EXAMPLE_TRACE("report OTA version failed"); */ + /* goto do_exit; */ + /* } */ HAL_SleepMs(1000); @@ -231,7 +200,8 @@ int mqtt_client(void) if (IOT_OTA_IsFetching(h_ota)) { uint32_t last_percent = 0, percent = 0; - char version[128], md5sum[33]; + char md5sum[33]; + char version[128] = {0}; uint32_t len, size_downloaded, size_file; do { @@ -303,23 +273,17 @@ int mqtt_client(void) return rc; } -int main(int argc, char **argv) +int main(int argc, char *argv[]) { - IOT_OpenLog("mqtt"); + EXAMPLE_TRACE("hello main func"); IOT_SetLogLevel(IOT_LOG_DEBUG); user_argc = argc; user_argv = argv; - /**< set device info*/ - HAL_SetProductKey(PRODUCT_KEY); - HAL_SetDeviceName(DEVICE_NAME); - HAL_SetDeviceSecret(DEVICE_SECRET); - /**< end*/ - mqtt_client(); + _ota_mqtt_client(); IOT_DumpMemoryStats(IOT_LOG_DEBUG); - IOT_CloseLog(); EXAMPLE_TRACE("out of sample!"); return 0; diff --git a/iotkit-embedded/src/ota/iot.mk b/iotkit-embedded/src/ota/iot.mk index a126777..479fe34 100644 --- a/iotkit-embedded/src/ota/iot.mk +++ b/iotkit-embedded/src/ota/iot.mk @@ -1,6 +1,13 @@ -LIBA_TARGET := libiot_ota.a -LIB_SRCS_PATTERN := Link-OTA/src/ota.c -HDR_REFS := src +LIBA_TARGET := libiot_ota.a -PKG_SOURCE := Link-OTA.git -PKG_UPSTREAM := git@gitlab.alibaba-inc.com:iot-middleware/Link-OTA.git +HDR_REFS := src/infra + +DEPENDS += wrappers +LDFLAGS += -liot_sdk -liot_hal -liot_tls + +LIB_SRCS_PATTERN := *.c + +LIB_SRCS_EXCLUDE += examples/ota_example_mqtt.c +SRCS_ota-example-mqtt := examples/ota_example_mqtt.c + +$(call Append_Conditional, TARGET, ota-example-mqtt, OTA_ENABLED, BUILD_AOS NO_EXECUTABLES) diff --git a/iotkit-embedded/src/ota/iotx_ota.c b/iotkit-embedded/src/ota/iotx_ota.c new file mode 100644 index 0000000..49d8bc5 --- /dev/null +++ b/iotkit-embedded/src/ota/iotx_ota.c @@ -0,0 +1,984 @@ +/* + * 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; + + 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; +} + + +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 (0 != otalib_GetParams(pvalue, val_len, &h_ota->purl, &h_ota->version, h_ota->md5sum, &h_ota->size_file)) { + OTA_LOG_ERROR("Get config parameter failed"); + return -1; + } + + 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); + } + + 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); + 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); + 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/iotkit-embedded/src/ota/iotx_ota.h b/iotkit-embedded/src/ota/iotx_ota.h new file mode 100644 index 0000000..816e31e --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/ota/iotx_ota_config.h b/iotkit-embedded/src/ota/iotx_ota_config.h new file mode 100644 index 0000000..3536a43 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/ota/iotx_ota_internal.h b/iotkit-embedded/src/ota/iotx_ota_internal.h new file mode 100644 index 0000000..8bb6c58 --- /dev/null +++ b/iotkit-embedded/src/ota/iotx_ota_internal.h @@ -0,0 +1,102 @@ +/* + * 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_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); + +#endif /* _IOTX_OTA_INTERNAL_H_ */ + + diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_ota.h b/iotkit-embedded/src/ota/ota_api.h similarity index 79% rename from iotkit-embedded/src/sdk-impl/exports/iot_export_ota.h rename to iotkit-embedded/src/ota/ota_api.h index 73c3287..26d8837 100644 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_ota.h +++ b/iotkit-embedded/src/ota/ota_api.h @@ -1,27 +1,16 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ - - #ifndef __OTA_EXPORT_H__ #define __OTA_EXPORT_H__ -#include "iot_import.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) @@ -50,6 +39,11 @@ typedef enum { 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 { @@ -79,13 +73,20 @@ typedef enum { 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_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 @@ -137,21 +138,6 @@ int IOT_OTA_Deinit(void *handle); */ int IOT_OTA_ReportVersion(void *handle, const char *version); - -/** - * @brief Request firmware image from cloud. - * - * - * @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. - */ -int IOT_OTA_RequestImage(void *handle, const char *version); - - /** * @brief Report detail progress to OTA server (optional). * NOTE: please @@ -167,23 +153,6 @@ int IOT_OTA_RequestImage(void *handle, const char *version); int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg); - -/** - * @brief Report detail progress to OTA server (optional). - * NOTE: please - * - * @param [in] handle: specify the OTA module. - * @param [in] configScope: product or device. - * @param [in] getType: file or other. - * @param [in] attributeKeys: attribute key. - * - * @retval 0 : Successful. - * @retval < 0 : Failed, the value is error code. - * @see None. - */ -int IOT_OTA_GetConfig(void *handle, const char* configScope, const char* getType, const char* attributeKeys); - - /** * @brief Check whether is on fetching state * @@ -248,7 +217,7 @@ int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeo * @retval < 0 : Failed, the value is error code. * @see None. */ -int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, size_t buf_len); +int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len); /** @@ -264,4 +233,10 @@ int IOT_OTA_GetLastError(void *handle); /** @} */ /* end of api_ota */ /** @} */ /* end of api */ +#if defined(__cplusplus) +} +#endif + #endif /* __OTA_EXPORT_H__ */ + + diff --git a/iotkit-embedded/src/ota/Link-OTA/src/ota_coap.c b/iotkit-embedded/src/ota/ota_coap.c similarity index 74% rename from iotkit-embedded/src/ota/Link-OTA/src/ota_coap.c rename to iotkit-embedded/src/ota/ota_coap.c index c2f396c..70ce80a 100644 --- a/iotkit-embedded/src/ota/Link-OTA/src/ota_coap.c +++ b/iotkit-embedded/src/ota/ota_coap.c @@ -1,29 +1,12 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ - - #ifndef __OTA_COAP_C_H__ #define __OTA_COAP_C_H__ +#if (OTA_SIGNAL_CHANNEL) == 2 -#include "iot_export_ota.h" -#include "iot_import_ota.h" -#include "ota_internal.h" +#include "iotx_ota_internal.h" /* OSC, OTA signal channel */ @@ -37,7 +20,7 @@ typedef struct { const char *device_name; ota_cb_fpt cb; void *context; -}otacoap_Struct_t, *otacoap_Struct_pt; +} otacoap_Struct_t, *otacoap_Struct_pt; static otacoap_Struct_pt h_osc_coap = NULL; @@ -61,18 +44,21 @@ static void otacoap_response_handler(void *arg, void *p_response) /* 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) +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); + buf_len, + "/topic/ota/device/%s/%s/%s", + ota_topic_type, + product_key, + device_name); - OTA_ASSERT(ret < buf_len); + if (ret >= buf_len) { + return -1; + } if (ret < 0) { OTA_LOG_ERROR("snprintf failed"); @@ -86,7 +72,7 @@ static int otacoap_GenTopicName(char *buf, size_t buf_len, const char *ota_topic 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}; + 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); @@ -97,12 +83,11 @@ static int otacoap_Publish(otacoap_Struct_pt handle, const char *topic_type, con /* 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; + OTA_LOG_ERROR("generate topic name failed"); + return -1; } - if (IOTX_SUCCESS != (ret = IOT_CoAP_SendMessage(handle->coap, (char *)uri, &message))) - { + if (IOTX_SUCCESS != (ret = IOT_CoAP_SendMessage(handle->coap, (char *)uri, &message))) { OTA_LOG_ERROR("send CoAP msg failed%d", ret); return -1; } @@ -168,5 +153,8 @@ int osc_ReportVersion(void *handle, const char *msg) return otacoap_Publish(handle, "request", msg); } +#endif /* #if (OTA_SIGNAL_CHANNEL) == 2 */ #endif + + diff --git a/iotkit-embedded/src/ota/Link-OTA/src/ota_fetch.c b/iotkit-embedded/src/ota/ota_fetch.c similarity index 64% rename from iotkit-embedded/src/ota/Link-OTA/src/ota_fetch.c rename to iotkit-embedded/src/ota/ota_fetch.c index ea250ec..b80a5f5 100644 --- a/iotkit-embedded/src/ota/Link-OTA/src/ota_fetch.c +++ b/iotkit-embedded/src/ota/ota_fetch.c @@ -1,26 +1,8 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ -#ifndef __OTA_FETCH_C_H__ -#define __OTA_FETCH_C_H__ - -#include -#include "iot_import_ota.h" +#include "iotx_ota_internal.h" /* ofc, OTA fetch channel */ @@ -40,10 +22,7 @@ extern int httpclient_common(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data); -extern const char *iotx_ca_get(void); - - -void *ofc_Init(const char *url) +void *ofc_Init(char *url) { otahttp_Struct_pt h_odc; @@ -57,24 +36,37 @@ void *ofc_Init(const char *url) /* 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; + 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;; + diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len; - if (0 != httpclient_common(&h_odc->http, h_odc->url, 443, iotx_ca_get(), HTTPCLIENT_GET, timeout_s * 1000, +#if !defined(SUPPORT_TLS) + 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; } @@ -92,4 +84,5 @@ int ofc_Deinit(void *handle) return 0; } -#endif + + diff --git a/iotkit-embedded/src/ota/Link-OTA/src/ota_lib.c b/iotkit-embedded/src/ota/ota_lib.c similarity index 54% rename from iotkit-embedded/src/ota/Link-OTA/src/ota_lib.c rename to iotkit-embedded/src/ota/ota_lib.c index 3faa613..0bd8c46 100644 --- a/iotkit-embedded/src/ota/Link-OTA/src/ota_lib.c +++ b/iotkit-embedded/src/ota/ota_lib.c @@ -1,33 +1,10 @@ /* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * + * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ +#include "iotx_ota_internal.h" - -#ifndef _OTA_LIB_C_ -#define _OTA_LIB_C_ - -#include -#include "iot_export_ota.h" -#include "iot_import_ota.h" -#include "ota_internal.h" - - -static const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len) +const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len) { int length; const char *val; @@ -38,7 +15,7 @@ static const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const return val; } -static void *otalib_MD5Init(void) +void *otalib_MD5Init(void) { iot_md5_context *ctx = OTA_MALLOC(sizeof(iot_md5_context)); if (NULL == ctx) { @@ -51,38 +28,76 @@ static void *otalib_MD5Init(void) return ctx; } -static void otalib_MD5Update(void *md5, const char *buf, size_t buf_len) +void otalib_MD5Update(void *md5, const char *buf, size_t buf_len) { utils_md5_update(md5, (unsigned char *)buf, buf_len); } -static void otalib_MD5Finalize(void *md5, char *output_str) +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] = utils_hb2hex(buf_out[i] >> 4); - output_str[i * 2 + 1] = utils_hb2hex(buf_out[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'; } -static void otalib_MD5Deinit(void *md5) +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 */ -static int otalib_GetFirmwareFixlenPara(const char *json_doc, - size_t json_doc_len, - const char *key, - char *dest, - size_t dest_len) +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; @@ -105,10 +120,10 @@ static int otalib_GetFirmwareFixlenPara(const char *json_doc, /* Get variant length parameter of firmware, and copy to @dest */ /* 0, successful; -1, failed */ -static int otalib_GetFirmwareVarlenPara(const char *json_doc, - size_t json_doc_len, - const char *key, - char **dest) +int otalib_GetFirmwareVarlenPara(const char *json_doc, + size_t json_doc_len, + const char *key, + char **dest) { const char *pvalue; uint32_t val_len; @@ -129,12 +144,11 @@ static int otalib_GetFirmwareVarlenPara(const char *json_doc, 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]; + char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0}; /* get version */ if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "version", version)) { @@ -167,6 +181,53 @@ int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char * #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 +} /* Generate firmware information according to @id, @version */ /* and then copy to @buf. */ @@ -188,7 +249,6 @@ int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *versio return 0; } - /* Generate report information according to @id, @msg */ /* and then copy to @buf. */ /* 0, successful; -1, failed */ @@ -198,13 +258,13 @@ int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, co if (NULL == msg_detail) { ret = HAL_Snprintf(buf, buf_len, - "{\"id\":%d,\"params\": {\"step\": \"%d\"}}", + "{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"\"}}", id, progress); } else { ret = HAL_Snprintf(buf, buf_len, - "{\"id\":%d,\"params\": {\"step\": \"%d\",\"desc\":\"%s\"}}", + "{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"%s\"}}", id, progress, msg_detail); @@ -223,4 +283,3 @@ int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, co } -#endif /* _OTA_LIB_C_ */ diff --git a/iotkit-embedded/src/ota/ota_mqtt.c b/iotkit-embedded/src/ota/ota_mqtt.c new file mode 100644 index 0000000..ceea75c --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/ota/ota_wrapper.h b/iotkit-embedded/src/ota/ota_wrapper.h new file mode 100644 index 0000000..d5a0794 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/packages/LITE-utils/CMakeLists.txt b/iotkit-embedded/src/packages/LITE-utils/CMakeLists.txt deleted file mode 100644 index f6841bc..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(utils_lite_utils OBJECT ${C_SOURCES}) - diff --git a/iotkit-embedded/src/packages/LITE-utils/json_parser.c b/iotkit-embedded/src/packages/LITE-utils/json_parser.c deleted file mode 100644 index b11d7bf..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/json_parser.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include - -#include "lite-utils_internal.h" -#include "json_parser.h" - -#define json_debug log_debug - -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) { - json_debug("Name:"); - for (i = 0; i < iNameLen; i++) { - json_debug("%c", *(p_cName + i)); - } - } - - if (p_cValue) { - json_debug("Value:"); - for (i = 0; i < iValueLen; i++) { - json_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; -} diff --git a/iotkit-embedded/src/packages/LITE-utils/lite-list.h b/iotkit-embedded/src/packages/LITE-utils/lite-list.h deleted file mode 100644 index 83cbc7c..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/lite-list.h +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -//#define inline __inline - -typedef struct list_head list_head_t; - -struct list_head { - struct list_head *next, *prev; -}; - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void INIT_LIST_HEAD(struct list_head *list) -{ - list->next = list; - list->prev = list; -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty() on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void __list_del_entry(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_replace - replace old entry by new one - * @old : the element to be replaced - * @new : the new element to insert - * - * If @old was empty, it will be overwritten. - */ -static inline void list_replace(struct list_head *old, - struct list_head *new) -{ - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; -} - -static inline void list_replace_init(struct list_head *old, - struct list_head *new) -{ - list_replace(old, new); - INIT_LIST_HEAD(old); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del_entry(entry); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del_entry(list); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del_entry(list); - list_add_tail(list, head); -} - -/** - * list_is_last - tests whether @list is the last entry in list @head - * @list: the entry to test - * @head: the head of the list - */ -static inline int list_is_last(const struct list_head *list, - const struct list_head *head) -{ - return list->next == head; -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - -/** - * list_empty_careful - tests whether a list is empty and not being modified - * @head: the list to test - * - * Description: - * tests whether a list is empty _and_ checks that no other CPU might be - * in the process of modifying either member (next or prev) - * - * NOTE: using list_empty_careful() without synchronization - * can only be safe if the only activity that can happen - * to the list entry is list_del_init(). Eg. it cannot be used - * if another CPU could re-list_add() it. - */ -static inline int list_empty_careful(const struct list_head *head) -{ - struct list_head *next = head->next; - return (next == head) && (next == head->prev); -} - -/** - * list_rotate_left - rotate the list to the left - * @head: the head of the list - */ -static inline void list_rotate_left(struct list_head *head) -{ - struct list_head *first; - - if (!list_empty(head)) { - first = head->next; - list_move_tail(first, head); - } -} - -/** - * list_is_singular - tests whether a list has just one entry. - * @head: the list to test. - */ -static inline int list_is_singular(const struct list_head *head) -{ - return !list_empty(head) && (head->next == head->prev); -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/** - * list_last_entry - get the last element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - * - * Note, that list is expected to be not empty. - */ -#define list_last_entry(ptr, type, member) \ - list_entry((ptr)->prev, type, member) - -/** - * list_first_entry_or_null - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - * - * Note that if the list is empty, it returns NULL. - */ -#define list_first_entry_or_null(ptr, type, member) \ - (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) - -/** - * list_next_entry - get the next element in list - * @pos: the type * to cursor - * @member: the name of the list_struct within the struct. - */ -#define list_next_entry(pos, member, type) \ - list_entry((pos)->member.next, type, member) - -/** - * list_prev_entry - get the prev element in list - * @pos: the type * to cursor - * @member: the name of the list_struct within the struct. - */ -#define list_prev_entry(pos, member, type) \ - list_entry((pos)->member.prev, type, member) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This variant doesn't differ from list_for_each() any more. - * We don't do prefetching in either case. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry - * @pos: the &struct list_head to use as a loop cursor. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_prev_safe(pos, n, head) \ - for (pos = (head)->prev, n = pos->prev; \ - pos != (head); \ - pos = n, n = pos->prev) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) - -/** - * list_for_each_entry_reverse - iterate backwards over list of given type. - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_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)) - -/** - * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() - * @pos: the type * to use as a start point - * @head: the head of the list - * @member: the name of the list_struct within the struct. - * - * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). - */ -#define list_prepare_entry(pos, head, member, type) \ - ((pos) ? : list_entry(head, type, member)) - -/** - * list_for_each_entry_continue - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Continue to iterate over list of given type, continuing after - * the current position. - */ -#define list_for_each_entry_continue(pos, head, member, type) \ - for (pos = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) - -/** - * list_for_each_entry_continue_reverse - iterate backwards from the given point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Start to iterate over list of given type backwards, continuing after - * the current position. - */ -#define list_for_each_entry_continue_reverse(pos, head, member, type) \ - for (pos = list_entry(pos->member.prev, type, member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, type, member)) - -/** - * list_for_each_entry_from - iterate over list of given type from the current point - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing from current position. - */ -#define list_for_each_entry_from(pos, head, member, type) \ - for (; &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#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)) - -/** - * list_for_each_entry_safe_continue - continue list iteration safe against removal - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type, continuing after current point, - * safe against removal of list entry. - */ -#define list_for_each_entry_safe_continue(pos, n, head, member, type) \ - for (pos = list_entry(pos->member.next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) - -/** - * list_for_each_entry_safe_from - iterate over list from current point safe against removal - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate over list of given type from current point, safe against - * removal of list entry. - */ -#define list_for_each_entry_safe_from(pos, n, head, member, type) \ - for (n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) - -/** - * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal - * @pos: the type * to use as a loop cursor. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - * - * Iterate backwards over list of given type, safe against removal - * of list entry. - */ -#define list_for_each_entry_safe_reverse(pos, n, head, member, type) \ - for (pos = list_entry((head)->prev, type, member), \ - n = list_entry(pos->member.prev, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, type, member)) - -/** - * list_safe_reset_next - reset a stale list_for_each_entry_safe loop - * @pos: the loop cursor used in the list_for_each_entry_safe loop - * @n: temporary storage used in list_for_each_entry_safe - * @member: the name of the list_struct within the struct. - * - * list_safe_reset_next is not safe to use in general if the list may be - * modified concurrently (eg. the lock is dropped in the loop body). An - * exception to this is if the cursor element (pos) is pinned in the list, - * and list_safe_reset_next is called after re-taking the lock and before - * completing the current iteration of the loop body. - */ -#define list_safe_reset_next(pos, n, member, type) \ - n = list_entry(pos->member.next, type, member) - -#endif diff --git a/iotkit-embedded/src/packages/LITE-utils/lite-utils.h b/iotkit-embedded/src/packages/LITE-utils/lite-utils.h deleted file mode 100644 index 47a78b6..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/lite-utils.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __LITE_UTILS_H__ -#define __LITE_UTILS_H__ - -#include -#include -#include -#include -#include -#include -#if defined(_PLATFORM_IS_LINUX_) -#include -#endif - -#include "lite-list.h" -#include "lite-log.h" -#include "iot_import.h" - - -#define UTILS_printf HAL_Printf -#define UTILS_malloc HAL_Malloc -#define UTILS_vsnprintf HAL_Vsnprintf -#define UTILS_free HAL_Free - -#define LITE_TRUE (1) -#define LITE_FALSE (0) - -#ifndef container_of -#define container_of(ptr, type, member) \ - ((type *) ((char *) (ptr) - offsetof(type, member))) -#endif - -#define LITE_MINIMUM(a, b) (((a) <= (b)) ? (a) : (b)) -#define LITE_MAXIMUM(a, b) (((a) >= (b)) ? (a) : (b)) -#define LITE_isdigit(c) (((c) <= '9' && (c) >= '0') ? (LITE_TRUE) : (LITE_FALSE)) - -#if defined(_PLATFORM_IS_LINUX_) -#define LITE_ASSERT(expr) assert(expr) -#else -#define LITE_ASSERT(expr) \ - do { \ - if (!(expr)) { \ - UTILS_printf("### %s | %s(%d): ASSERT FAILED ###: %s is FALSE\r\n", \ - __FILE__, __func__, __LINE__, #expr); \ - } \ - } while(0) -#endif - -#define MEM_MAGIC (0x1234) - -#define LITE_calloc(num, size, ...) LITE_malloc_internal(__func__, __LINE__, (num * size), ##__VA_ARGS__) -#define LITE_malloc(size, ...) LITE_malloc_internal(__func__, __LINE__, size, ##__VA_ARGS__) -#define LITE_realloc(ptr, size, ...) LITE_realloc_internal(__func__, __LINE__, ptr, size, ##__VA_ARGS__) -#define LITE_free(ptr) \ - do { \ - if(!ptr) { \ - log_err("%s == NULL! LITE_free(%s) aborted.", #ptr, #ptr); \ - break; \ - } \ - \ - LITE_free_internal((void *)ptr); \ - ptr = NULL; \ - } while(0) - -void *LITE_malloc_internal(const char *f, const int l, int size, ...); -void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ...); -void LITE_free_internal(void *ptr); -void *LITE_malloc_routine(int size, ...); -void LITE_free_routine(void *ptr); -void *LITE_calloc_routine(size_t n, size_t s, ...); - -char *LITE_strdup(const char *src, ...); -char *LITE_format_string(const char *fmt, ...); -char *LITE_format_nstring(const int len, const char *fmt, ...); -void LITE_hexbuf_convert(unsigned char *digest, char *out, int buflen, int uppercase); -void LITE_hexstr_convert(char *hexstr, uint8_t *out_buf, int len); -void LITE_replace_substr(char orig[], char key[], char swap[]); - -void LITE_dump_malloc_free_stats(int level); -void LITE_track_malloc_callstack(int state); - -char *LITE_json_value_of(char *key, char *src, ...); -list_head_t *LITE_json_keys_of(char *src, char *prefix, ...); - -char *LITE_json_value_of_ext(char *key, char *src, ...); -char *LITE_json_value_of_ext2(char *key, char *src, int src_len, int *value_len); - -list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...); - -int get_json_item_size(char *src, int src_len); - -void LITE_json_keys_release(list_head_t *keylist); - -typedef struct _json_key_t { - char *key; - list_head_t list; -} json_key_t; - -#define foreach_json_keys_in(src, iter_key, keylist, pos) \ - for(keylist = (void *)LITE_json_keys_of((char *)src, ""), \ - pos = (void *)list_first_entry((list_head_t *)keylist, json_key_t, list), \ - iter_key = ((json_key_t *)pos)->key; \ - (iter_key = ((json_key_t *)pos)->key); \ - pos = list_next_entry((json_key_t *)pos, list, json_key_t)) - -int unittest_string_utils(void); -int unittest_json_parser(void); -int unittest_json_token(void); - -#endif /* __LITE_UTILS_H__ */ diff --git a/iotkit-embedded/src/packages/LITE-utils/lite-utils_config.h b/iotkit-embedded/src/packages/LITE-utils/lite-utils_config.h deleted file mode 100644 index e014b6d..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/lite-utils_config.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __LITE_UTILS_CONFIG_H__ -#define __LITE_UTILS_CONFIG_H__ - -#ifndef WITH_MEM_STATS -#ifdef _PLATFORM_IS_LINUX_ -#define WITH_MEM_STATS 1 -#define WITH_MEM_STATS_PER_MODULE 1 -#else -#define WITH_MEM_STATS 0 -#define WITH_MEM_STATS_PER_MODULE 0 -#endif -#endif - -#endif /* __LITE_UTILS_CONFIG_H__ */ diff --git a/iotkit-embedded/src/packages/LITE-utils/lite-utils_internal.h b/iotkit-embedded/src/packages/LITE-utils/lite-utils_internal.h deleted file mode 100644 index ac94abf..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/lite-utils_internal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __LITE_UTILS_INTERNAL_H__ -#define __LITE_UTILS_INTERNAL_H__ - -#define _GNU_SOURCE - -#include -#include -#include -#include - -#include "lite-log.h" - -#include "lite-utils_config.h" -#include "lite-utils.h" - -#endif /* __LITE_UTILS_INTERNAL_H__ */ diff --git a/iotkit-embedded/src/packages/LITE-utils/lite-utils_prog.c b/iotkit-embedded/src/packages/LITE-utils/lite-utils_prog.c deleted file mode 100644 index 67bc9c8..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/lite-utils_prog.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "lite-utils_internal.h" - -int main(void) -{ - unittest_string_utils(); - unittest_json_token(); - unittest_json_parser(); - - return 0; -} diff --git a/iotkit-embedded/src/packages/LITE-utils/lite-utils_testsuites.c b/iotkit-embedded/src/packages/LITE-utils/lite-utils_testsuites.c deleted file mode 100644 index d576d00..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/lite-utils_testsuites.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "lite-utils_internal.h" - -int unittest_string_utils(void) -{ - unsigned char hexbuf[] = { 0x12, 0x34, 0x56, 0x78, 0xcd, 0xef, 0xab, 0x90 }; - char hexstr[20] = { 0 }; - unsigned char outbuf[10] = { 0x0 }; - - LITE_hexbuf_convert(hexbuf, hexstr, sizeof(hexbuf), 0); - log_info("hexstr = '%s'", hexstr); - LITE_hexbuf_convert(hexbuf, hexstr, sizeof(hexbuf), 1); - log_info("hexstr = '%s'", hexstr); - - LITE_hexstr_convert(hexstr, outbuf, strlen(hexstr)); - HEXDUMP_INFO(outbuf, sizeof(outbuf)); - -#define UNITTEST_STRING_FORMAT "Integer: %d, String: '%s', Char: %c, Hex: %04x" - - char *str = NULL; - - str = LITE_format_string(UNITTEST_STRING_FORMAT, 100, "Hello", 'A', 640); - log_info("(Length: %02d) '%s'", (int)strlen(str), str); - LITE_free(str); - - str = LITE_format_nstring(10, UNITTEST_STRING_FORMAT, 100, "Hello", 'A', 640); - log_info("(Length: %02d) '%s'", (int)strlen(str), str); - LITE_free(str); - - str = LITE_format_nstring(20, UNITTEST_STRING_FORMAT, 100, "Hello", 'A', 640); - log_info("(Length: %02d) '%s'", (int)strlen(str), str); - LITE_free(str); - - str = LITE_format_nstring(40, UNITTEST_STRING_FORMAT, 100, "Hello", 'A', 640); - log_info("(Length: %02d) '%s'", (int)strlen(str), str); - LITE_free(str); - -#define UNITTEST_JSON_FORMAT \ - "{" \ - "\"KeyFlt\": \"Float\", " \ - "\"KeyInt\": \"Integer\", " \ - "\"KeyStr\": \"String\", " \ - "\"KeyBool\": \"Boolean\"" \ - "}" - - char source[128]; - - LITE_snprintf(source, sizeof(source), "%s", "Hello, World!"); - log_info("ORIG: '%s'", source); - LITE_replace_substr(source, "Worl", "Clou"); - log_info("REPL: '%s'", source); - - LITE_snprintf(source, sizeof(source), "%s", UNITTEST_JSON_FORMAT); - log_info("ORIG: '%s'", source); - LITE_replace_substr(source, "Float", "%f"); - LITE_replace_substr(source, "Integer", "%d"); - LITE_replace_substr(source, "String", "%s"); - LITE_replace_substr(source, "Boolean", "%s"); - log_info("REPL: '%s'", source); - - return 0; -} - -#define UNITTEST_JSON_SAMPLE \ -\ -" " \ -"{" \ - "\"code\":200," \ - "\"ArrayList\":[ 1, 4, 16 ]," \ - "\"KeyTrue\": true," \ - "\"KeyFalse\": false," \ - "\"data\":{ " \ - "\"iotId\":\"42Ze0mk3556498a1AlTP\"," \ - "\"iotToken\":\"0d7fdeb9dc1f4344a2cc0d45edcb0bcb\"," \ - "\"resources\":{" \ - "\"mqtt\":{" \ - "\"host\":\"10.10.10.10\"," \ - "\"port\":9999" \ - "}," \ - "\"codec\":{" \ - "\"name\":\"AES_CBC_NOPADDING\"," \ - "\"key\":\"12321321\"" \ - "}" \ - "}" \ - "}," \ - "\"message\":\"success\"" \ -"}" -#define UNITTEST_JSON_SUBKEY "data.resources" - -int unittest_json_token(void) -{ - list_head_t *key_list = NULL; - json_key_t *pos; - - key_list = LITE_json_keys_of(UNITTEST_JSON_SAMPLE, ""); - - list_for_each_entry(pos, key_list, list, json_key_t) { - if (pos->key) { - char *val = NULL; - - val = LITE_json_value_of(pos->key, UNITTEST_JSON_SAMPLE); - log_info("%-28s: %.48s", pos->key, val); - LITE_free(val); - } - } - LITE_json_keys_release(key_list); - -#if defined(__GLIBC__) - /* Demo usage without awareness of json_key_t{} and returned list */ - - char *sub_objc; - void *ret_list; - void *temp; - char *token; - - sub_objc = LITE_json_value_of(UNITTEST_JSON_SUBKEY, UNITTEST_JSON_SAMPLE); - - foreach_json_keys_in(sub_objc, token, ret_list, temp) { - char *val; - - val = LITE_json_value_of(token, sub_objc); - log_info("%s|%-18s: %.48s", UNITTEST_JSON_SUBKEY, token, val); - LITE_free(val); - } - LITE_json_keys_release(ret_list); - LITE_free(sub_objc); -#endif /* #if defined(__GLIBC__) */ - - return 0; -} - -int unittest_json_parser(void) -{ - char *val; - char **pkey; - char *keys[] = { - "data.iotToken", - "data.iotId", - "data.resources.mqtt", - "data.resources.mqtt.host", - "data.resources.mqtt.port", - "data.resources.codec", - "data.resources.codec.name", - "data.resources.codec.key", - "message", - 0 - }; - - for (pkey = keys; *pkey; ++ pkey) { - val = LITE_json_value_of(*pkey, UNITTEST_JSON_SAMPLE); - if (val == NULL) { - log_err("failed to get value of key: '%s'", *pkey); - return -1; - } - - log_info("%-28s: %s", *pkey, val); - LITE_free(val); - } - - return 0; -} - diff --git a/iotkit-embedded/src/packages/LITE-utils/mem_stats.h b/iotkit-embedded/src/packages/LITE-utils/mem_stats.h deleted file mode 100644 index 5c35fce..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/mem_stats.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __MEM_STATS_H__ -#define __MEM_STATS_H__ - -#include "lite-utils_internal.h" - -#if defined(_PLATFORM_IS_LINUX_) && WITH_MEM_STATS - #include -#endif - -typedef struct { - void *buf; - int buflen; - char *func; - int line; -#if defined(_PLATFORM_IS_LINUX_) - char **bt_symbols; - int bt_level; -#endif - list_head_t list; - -#if WITH_MEM_STATS_PER_MODULE - void *mem_table; -#endif -} OS_malloc_record; - -#endif /* __MEM_STATS_H__ */ - diff --git a/iotkit-embedded/src/packages/LITE-utils/string_utils.c b/iotkit-embedded/src/packages/LITE-utils/string_utils.c deleted file mode 100644 index 57415b4..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/string_utils.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "lite-utils_internal.h" -#include "string_utils.h" - -char *LITE_format_string(const char *fmt, ...) -{ -#define TEMP_STRING_MAXLEN (512) - - va_list ap; - char *tmp = NULL; - char *dst; - int rc = -1; - - va_start(ap, fmt); - tmp = HAL_Malloc(TEMP_STRING_MAXLEN); - LITE_ASSERT(tmp); - memset(tmp, 0, TEMP_STRING_MAXLEN); - rc = HAL_Vsnprintf(tmp, TEMP_STRING_MAXLEN, fmt, ap); - va_end(ap); - LITE_ASSERT(rc < 1024); - - dst = LITE_strdup(tmp); - HAL_Free(tmp); - - return dst; - -#undef TEMP_STRING_MAXLEN -} - -char *LITE_format_nstring(const int len, const char *fmt, ...) -{ - char *tmp = NULL; - char *dst; - char *module_name = NULL; - int magic = 0; - va_list ap; - - va_start(ap, fmt); - magic = va_arg(ap, int); - if (MEM_MAGIC == magic) { - module_name = va_arg(ap, char *); - } - if (!module_name) { - va_start(ap, fmt); - } - - tmp = LITE_malloc(len + 2, magic, module_name); - LITE_ASSERT(tmp); - - if (NULL == tmp) { - return NULL; - } - memset(tmp, 0, len + 2); - UTILS_vsnprintf(tmp, len + 1, fmt, ap); - va_end(ap); - - dst = LITE_malloc(len + 1, magic, module_name); - LITE_snprintf(dst, (len + 1), "%s", tmp); - LITE_free(tmp); - return dst; - -} - -char *LITE_strdup(const char *src, ...) -{ - int len = 0; - char *dst = NULL; - int magic = 0; - char *module_name = NULL; - - if (!src) { - return NULL; - } - len = strlen(src) + 1; - if (len > 1024) { - log_err("Too long string to duplicate, abort! len = %d", len); - return NULL; - } - -#if WITH_MEM_STATS_PER_MODULE - - 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 - - dst = (char *)LITE_malloc(sizeof(char) * len, magic, module_name); - - if (!dst) { - return NULL; - } - strncpy(dst, src, len); - - return dst; -} - -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]; - } -} - -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 *hexstr, uint8_t *out_buf, int in_len) -{ - int i = 0; - uint8_t ch0, ch1; - - if (in_len % 2 != 0) { - log_err("hexstr length (%d) is not even", in_len); - return; - } - - while (i < in_len / 2) { - ch0 = _hexval_of_char((char)hexstr[2 * i]); - ch1 = _hexval_of_char((char)hexstr[2 * i + 1]); - out_buf[i] = (ch0 << 4 | ch1); - i++; - } -} - -void LITE_replace_substr(char originalString[], char key[], char swap[]) -{ - int lengthOfOriginalString, lengthOfKey, lengthOfSwap, i, j, flag; - char tmp[512]; - - lengthOfOriginalString = strlen(originalString); - lengthOfKey = strlen(key); - lengthOfSwap = strlen(swap); - - for (i = 0; i <= lengthOfOriginalString - lengthOfKey; i++) { - flag = 1; - for (j = 0; j < lengthOfKey; j++) { - if (originalString[i + j] != key[j]) { - flag = 0; - break; - } - } - - if (flag) { - strcpy(tmp, originalString); - strcpy(&tmp[i], swap); - strcpy(&tmp[i + lengthOfSwap], &originalString[i + lengthOfKey]); - strcpy(originalString, tmp); - i += lengthOfSwap - 1; - lengthOfOriginalString = strlen(originalString); - } - } -} - diff --git a/iotkit-embedded/src/packages/LITE-utils/string_utils.h b/iotkit-embedded/src/packages/LITE-utils/string_utils.h deleted file mode 100644 index 68d6362..0000000 --- a/iotkit-embedded/src/packages/LITE-utils/string_utils.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __COMMON_UTILS_H__ -#define __COMMON_UTILS_H__ - -#include "lite-utils_internal.h" - - -#endif /* __COMMON_UTILS_H__ */ - diff --git a/iotkit-embedded/src/packages/iot-coap-c/CoAPDeserialize.h b/iotkit-embedded/src/packages/iot-coap-c/CoAPDeserialize.h deleted file mode 100644 index dbf6302..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPDeserialize.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include "CoAPExport.h" - -#ifndef __COAP_DESERIALIZE_H__ -#define __COAP_DESERIALIZE_H__ - -int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen); - -#endif diff --git a/iotkit-embedded/src/packages/iot-coap-c/CoAPExport.h b/iotkit-embedded/src/packages/iot-coap-c/CoAPExport.h deleted file mode 100644 index 6eaba95..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPExport.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "CoAPNetwork.h" -#include "lite-utils.h" -#ifndef __COAP_EXPORT_H__ -#define __COAP_EXPORT_H__ - -/* #define COAP_DTLS_SUPPORT */ - - -#define COAP_MSG_MAX_TOKEN_LEN 12 -#define COAP_MSG_MAX_OPTION_NUM 12 -#define COAP_MSG_MAX_PATH_LEN 32 -#define COAP_MSG_MAX_PDU_LEN 1280 - -/*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_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)*/ - - -/*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_INVALID_LENGTH (COAP_ERROR_BASE | 3) /* Invalid Length */ -#define COAP_ERROR_DATA_SIZE (COAP_ERROR_BASE | 4) /* Data size exceeds limit */ -#define COAP_ERROR_INVALID_URI (COAP_ERROR_BASE | 5) -#define COAP_ERROR_NOT_FOUND (COAP_ERROR_BASE | 6) -#define COAP_ERROR_NET_INIT_FAILED (COAP_ERROR_BASE | 7) -#define COAP_ERROR_INTERNAL (COAP_ERROR_BASE | 8) /* Internal Error */ -#define COAP_ERROR_WRITE_FAILED (COAP_ERROR_BASE | 9) -#define COAP_ERROR_READ_FAILED (COAP_ERROR_BASE | 10) - -#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 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 (*CoAPRespMsgHandler)(void *data, void *message); - -typedef void (*CoAPEventNotifier)(unsigned int event, void *p_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; - CoAPRespMsgHandler handler; - struct list_head sendlist; -} CoAPSendNode; - -typedef struct -{ - unsigned char count; - unsigned char maxcount; - struct list_head sendlist; -}CoAPSendList; - - -typedef struct -{ - CoAPMsgHeader header; - unsigned char token[COAP_MSG_MAX_TOKEN_LEN]; - CoAPMsgOption options[COAP_MSG_MAX_OPTION_NUM]; - unsigned char optnum; - unsigned char optdelta; - unsigned char *payload; - unsigned short payloadlen; - CoAPRespMsgHandler handler; - void *user; -}CoAPMessage; - -typedef struct -{ - char *url; - unsigned char maxcount; /*list maximal count*/ - unsigned int waittime; - CoAPEventNotifier notifier; -}CoAPInitParam; - -typedef struct -{ - unsigned short message_id; - coap_network_t network; - CoAPEventNotifier notifier; - unsigned char *sendbuf; - unsigned char *recvbuf; - CoAPSendList list; - unsigned int waittime; -}CoAPContext; - -#define COAP_TRC log_debug -#define COAP_DUMP log_debug -#define COAP_DEBUG log_debug -#define COAP_INFO log_info -#define COAP_ERR log_err - -CoAPContext *CoAPContext_create(CoAPInitParam *param); -void CoAPContext_free(CoAPContext *p_ctx); - - -#endif diff --git a/iotkit-embedded/src/packages/iot-coap-c/CoAPMessage.c b/iotkit-embedded/src/packages/iot-coap-c/CoAPMessage.c deleted file mode 100644 index 672189b..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPMessage.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include "stdio.h" -#include "CoAPExport.h" -#include "CoAPSerialize.h" -#include "CoAPDeserialize.h" -#include "iot_import.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 CoAPRstMsg(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->optnum) { - return COAP_ERROR_INVALID_PARAM; - } - - message->options[message->optnum].num = optnum - message->optdelta; - message->options[message->optnum].len = datalen; - ptr = (unsigned char *)coap_malloc(datalen); - if (NULL != ptr) { - memcpy(ptr, data, datalen); - } - message->options[message->optnum].val = ptr; - message->optdelta = optnum; - message->optnum ++; - - return COAP_SUCCESS; - -} - -int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, unsigned int data) -{ - unsigned char *ptr = NULL; - if (COAP_MSG_MAX_OPTION_NUM <= message->optnum) { - return COAP_ERROR_INVALID_PARAM; - } - message->options[message->optnum].num = optnum - message->optdelta; - - if (0 == data) { - message->options[message->optnum].len = 0; - } else if (256 >= data) { - message->options[message->optnum].len = 1; - ptr = (unsigned char *)coap_malloc(1); - if (NULL != ptr) { - *ptr = (unsigned char)data; - } - } else if (65535 >= data) { - message->options[message->optnum].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->optnum].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->optnum].val = ptr; - message->optdelta = optnum; - message->optnum += 1; - - return COAP_SUCCESS; -} - -unsigned short CoAPMessageId_gen(CoAPContext *context) -{ - unsigned short msg_id = 0; - msg_id = ((COAP_MAX_MESSAGE_ID == context->message_id) ? 1 : context->message_id++); - return msg_id; -} - - -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 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 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 CoAPMessageHandler_set(CoAPMessage *message, CoAPRespMsgHandler handler) -{ - if (NULL == message) { - return COAP_ERROR_NULL; - } - message->handler = handler; - return COAP_SUCCESS; -} - -int CoAPMessage_init(CoAPMessage *message) -{ - 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->optnum = 0; - message->optdelta = 0; - message->handler = 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_TOKEN_LEN; count++) { - if (NULL != message->options[count].val) { - coap_free(message->options[count].val); - message->options[count].val = NULL; - } - } - - return COAP_SUCCESS; -} - -static int CoAPMessageList_add(CoAPContext *context, CoAPMessage *message, int len) -{ - CoAPSendNode *node = NULL; - node = coap_malloc(sizeof(CoAPSendNode)); - - if (NULL != node) { - node->acked = 0; - node->user = message->user; - node->msgid = message->header.msgid; - node->handler = message->handler; - 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 CoAPMessage_send(CoAPContext *context, 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); - 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 = CoAPNetwork_write(&context->network, context->sendbuf, (unsigned int)msglen); - if (COAP_SUCCESS == ret) { - if (CoAPReqMsg(message->header) || CoAPCONRespMsg(message->header)) { - COAP_DEBUG("Add message id %d len %d to the list", - message->header.msgid, msglen); - CoAPMessageList_add(context, message, msglen); - } else { - COAP_DEBUG("The message doesn't need to be retransmitted"); - } - } else { - COAP_ERR("CoAP transoprt write failed, return %d", ret); - } - - return ret; -} - - -static int CoAPAckMessage_handle(CoAPContext *context, CoAPMessage *message) -{ - CoAPSendNode *node = NULL; - - list_for_each_entry(node, &context->list.sendlist, sendlist, CoAPSendNode) { - if (node->msgid == message->header.msgid) { - node->acked = 1; - return COAP_SUCCESS; - } - } - - return COAP_SUCCESS; -} - -static int CoAPAckMessage_send(CoAPContext *context, unsigned short msgid) -{ - CoAPMessage message; - CoAPMessage_init(&message); - CoAPMessageId_set(&message, msgid); - return CoAPMessage_send(context, &message); -} - -static int CoAPRespMessage_handle(CoAPContext *context, CoAPMessage *message) -{ - CoAPSendNode *node = NULL; - - if (COAP_MESSAGE_TYPE_CON == message->header.type) { - CoAPAckMessage_send(context, message->header.msgid); - } - - - list_for_each_entry(node, &context->list.sendlist, sendlist, CoAPSendNode) { - if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen - && 0 == memcmp(node->token, message->token, message->header.tokenlen)) { - - COAP_DEBUG("Find the node by token"); - 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->handler) { - node->handler(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 CoAPMessage_handle(CoAPContext *context, - unsigned char *buf, - unsigned short datalen) -{ - int ret = COAP_SUCCESS; - CoAPMessage message; - memset(&message, 0x00, sizeof(CoAPMessage)); - - ret = CoAPDeserialize_Message(&message, buf, datalen); - if (NULL != message.payload) { - COAP_DEBUG("-----payload: %s---", message.payload); - } - COAP_DEBUG("-----code : 0x%x---", message.header.code); - COAP_DEBUG("-----type : 0x%x---", message.header.type); - COAP_DEBUG("-----msgid : %d---", message.header.msgid); - COAP_DEBUG("-----opt : %d---", message.optnum); - - 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); - CoAPAckMessage_handle(context, &message); - - } else if (CoAPRespMsg(message.header)) { - COAP_DEBUG("Receive CoAP Response Message,ID %d", message.header.msgid); - CoAPRespMessage_handle(context, &message); - } -} - -int CoAPMessage_recv(CoAPContext *context, unsigned int timeout, int readcount) -{ - int len = 0; - int count = readcount; - - while (1) { - len = CoAPNetwork_read(&context->network, context->recvbuf, - COAP_MSG_MAX_PDU_LEN, timeout); - if (len > 0) { - if(0 == readcount){ - CoAPMessage_handle(context, context->recvbuf, len); - } - else{ - count--; - CoAPMessage_handle(context, context->recvbuf, len); - if(0 == count){ - return len; - } - } - } else { - return 0; - } - } -} - -int CoAPMessage_cycle(CoAPContext *context) -{ - unsigned int ret = 0; - CoAPMessage_recv(context, context->waittime, 0); - - CoAPSendNode *node = NULL, *next = NULL; - list_for_each_entry_safe(node, next, &context->list.sendlist, sendlist, 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 = 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/iotkit-embedded/src/packages/iot-coap-c/CoAPMessage.h b/iotkit-embedded/src/packages/iot-coap-c/CoAPMessage.h deleted file mode 100644 index 10b0df2..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPMessage.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "CoAPExport.h" - -#ifndef __COAP_HANDLE_MSG_H__ -#define __COAP_HANDLE_MSG_H__ - -int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum, - unsigned char *data, unsigned short datalen); - - -int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, - unsigned int data); - -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 CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload, - unsigned short payloadlen); - -int CoAPMessageHandler_set(CoAPMessage *message, CoAPRespMsgHandler handler); - -int CoAPMessage_init(CoAPMessage *message); - -int CoAPMessage_destory(CoAPMessage *message); - -int CoAPMessage_send(CoAPContext *context, CoAPMessage *message); - -int CoAPMessage_recv(CoAPContext *context, unsigned int timeout, int readcount); - -int CoAPMessage_cycle(CoAPContext *context); - - - -#endif diff --git a/iotkit-embedded/src/packages/iot-coap-c/CoAPNetwork.h b/iotkit-embedded/src/packages/iot-coap-c/CoAPNetwork.h deleted file mode 100644 index d993c3d..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPNetwork.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include "iot_import_dtls.h" - -#ifndef COAP_TRANSPORT_H__ -#define COAP_TRANSPORT_H__ - -typedef enum -{ - COAP_ENDPOINT_NOSEC = 0, - COAP_ENDPOINT_DTLS, -}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 CoAPNetwork_init (const coap_network_init_t * p_param, coap_network_t *p_network); - - -unsigned int CoAPNetwork_write(coap_network_t *p_network, - const unsigned char * p_data, - unsigned int datalen); - -int CoAPNetwork_read(coap_network_t *network, unsigned char *data, - unsigned int datalen, unsigned int timeout); - -unsigned int CoAPNetwork_deinit(coap_network_t *p_network); - - -#endif - diff --git a/iotkit-embedded/src/packages/iot-coap-c/CoAPSerialize.h b/iotkit-embedded/src/packages/iot-coap-c/CoAPSerialize.h deleted file mode 100644 index e85b8e6..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/CoAPSerialize.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "CoAPExport.h" -#ifndef __COAP_SERIALIZE_H__ -#define __COAP_SERIALIZE_H__ - -unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg); - -int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen); - -#endif - diff --git a/iotkit-embedded/src/packages/iot-coap-c/README.md b/iotkit-embedded/src/packages/iot-coap-c/README.md deleted file mode 100644 index 2a4aa9f..0000000 --- a/iotkit-embedded/src/packages/iot-coap-c/README.md +++ /dev/null @@ -1,4 +0,0 @@ -#### Alibaba IoT-CoAP-c: A C implementation of the Constrained Application Protocol (RFC 7252).#### -### ABOUT IoT-CoAP-c ### -### PACKAGE CONTENTS ### -### LICENSE INFORMATION ### diff --git a/iotkit-embedded/src/sdk-impl/class_interface.h b/iotkit-embedded/src/sdk-impl/class_interface.h deleted file mode 100644 index 472689e..0000000 --- a/iotkit-embedded/src/sdk-impl/class_interface.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __CLASS_INTERFACE_H__ -#define __CLASS_INTERFACE_H__ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -/* base-class define */ -/* abstract class */ -typedef struct { - size_t _size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); -} abstract_class_t; - - -/* new & delete */ -extern void* new_object(const void* _class, ...); -extern void delete_object(void* _class); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CLASS_INTERFACE_H__ */ diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_cloud_connection.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_cloud_connection.h deleted file mode 100644 index 5b7d9d1..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_cloud_connection.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CLOUD_CONNECTION_H_ -#define SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CLOUD_CONNECTION_H_ - - -/* follow as MQTT QoS */ -typedef enum { - IOTX_MESSAGE_QOS0 = 0, - IOTX_MESSAGE_QOS1, - IOTX_MESSAGE_QOS2 -} iotx_message_qos_t; - -/* The message payload encode format */ -typedef enum { - IOTX_MESSAGE_CONTENT_TYPE_JSON, - IOTX_MESSAGE_CONTENT_TYPE_CBOR, -} iotx_message_content_type_t; - -/* The message type */ -typedef enum { - IOTX_MESSAGE_CONFIRMABLE = 0, /* confirmable message */ - IOTX_MESSAGE_NON_CONFIRMABLE = 1, /* non-confirmable message */ -} iotx_message_type_t; - - -/* event type */ -typedef enum IOTX_CLOUD_CONNECTION_EVENT_TYPES { - IOTX_CLOUD_CONNECTION_EVENT_DISCONNECT, - - IOTX_CLOUD_CONNECTION_EVENT_RECONNECT, - - /* Maximum number of protocol */ - IOTX_CLOUD_CONNECTION_EVENT_MAX -}iotx_cloud_connection_event_types_t; - -/* protocol type */ -typedef enum IOTX_CLOUD_CONNECTION_PROTOCOL_TYPES { - /* MQTT */ - IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_MQTT = 1, - - /* CoAP */ - IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_COAP = 2, - - /* HTTP */ - IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_HTTP = 3, - - /* Maximum number of protocol */ - IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_MAX -}iotx_cloud_connection_protocol_types_t; - - -/* response type */ -typedef enum IOTX_CLOUD_CONNECTION_RESPONSE_TYPES { - /* subcribe success */ - IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_SUCCESS = 1, - - /* subcribe fail */ - IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_FAIL = 2, - - /* subcribe success */ - IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_SUCCESS = 3, - - /* subcribe fail */ - IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_FAIL = 4, - - /* send success */ - IOTX_CLOUD_CONNECTION_RESPONSE_SEND_SUCCESS = 5, - - /* send fail */ - IOTX_CLOUD_CONNECTION_RESPONSE_SEND_FAIL = 6, - - /* receive new data */ - IOTX_CLOUD_CONNECTION_RESPONSE_NEW_DATA = 7, - - /* Maximum number of response type */ - IOTX_CLOUD_CONNECTION_RESPONSE_TYPE_MAX -}iotx_cloud_connection_response_types_t; - - - -/* message type */ -typedef enum IOTX_CLOUD_CONNECTION_MESSAGE_TYPES { - /* MQTT: subcribe */ - IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_SUBSCRIBE = 1, - - /* MQTT: unsubcribe */ - IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_UNSUBSCRIBE = 2, - - /* MQTT: publish; CoAP & HTTP: send message */ - IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_PUBLISH = 3, - - /* Maximum number of message type */ - IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_MAX -}iotx_cloud_connection_message_types_t; - - -/* The structure of cloud Connection event struct */ -typedef struct { - uint8_t event_id; - void* msg; -} iotx_cloud_connection_event_msg_t, *iotx_cloud_connection_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 pConnection : The cloud Connection. - * @param msg : The event message. - * - * @return none - */ -typedef void (*iotx_cloud_connection_event_handle_func_fpt)(void *pconnection, iotx_cloud_connection_event_msg_pt msg); - -/* The structure of cloud Connection param */ -typedef struct { - iotx_cloud_connection_response_types_t rsp_type; - char *URI; - uint32_t URI_length; - void *payload; - uint32_t payload_length; - iotx_message_qos_t QoS; -} iotx_cloud_connection_msg_rsp_t, *iotx_cloud_connection_msg_rsp_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 pConnection : The cloud Connection. - * @param msg : The event message. - * - * @return none - */ -typedef void (*iotx_cloud_connection_msg_rsp_func_fpt)(void *pcontext, void *pconnection, iotx_cloud_connection_msg_rsp_pt msg); - - -/* The structure of cloud Connection param */ -typedef struct { - iotx_cloud_connection_protocol_types_t protocol_type; - iotx_device_info_t *device_info; - uint8_t clean_session; /* MQTT: clean_session, HTTP: keep_alive*/ - uint32_t request_timeout_ms; - uint32_t keepalive_interval_ms; /* MQTT keepalive_interval_ms */ - void* event_pcontext; - iotx_cloud_connection_event_handle_func_fpt event_handler; -} iotx_cloud_connection_param_t, *iotx_cloud_connection_param_pt; - - -typedef struct { - iotx_cloud_connection_message_types_t type; - char *URI; - uint32_t URI_length; - void *payload; - uint32_t payload_length; - iotx_message_qos_t QoS; - void* response_pcontext; - iotx_cloud_connection_msg_rsp_func_fpt response_handler; - iotx_message_content_type_t content_type; - iotx_message_type_t message_type; -} iotx_cloud_connection_msg_t, *iotx_cloud_connection_msg_pt; - - -/** - * @brief cloud clinet initial - * This function initialize the cloud connection structures, establish network connection - * - * @param Connection_param, specify the cloud Connection parameter and event handler. - * - * @return NULL, construct failed; NOT NULL, the handle of cloud Connection. - */ -void* IOT_Cloud_Connection_Init(iotx_cloud_connection_param_pt connection_param); - - -/** - * @brief Deconstruct the cloud connection - * Disconnect Network connection and release the related resource. - * - * @param pointer of handle, specify the cloud Connection. - * - * @return 0, deconstruct success; -1, deconstruct failed. - */ -int IOT_Cloud_Connection_Deinit(void** handle); - - -/** - * @brief Deconstruct the cloud connection - * Disconnect Network connection and release the related resource. - * - * @param pointer of handle, specify the cloud connection. - * - * @return 0, deconstruct success; -1, deconstruct failed. - */ -int IOT_Cloud_Connection_Send_Message(void* handle, iotx_cloud_connection_msg_pt msg); - - -/** - * @brief Handle packet from remote point and process timeout request - * - * @param [in] handle: specify the cloud Connection. - * @param [in] timeout_ms: specify the timeout in millisecond in this loop. - * - * @return status. - * @see None. - */ -int IOT_Cloud_Connection_Yield(void *handle, int timeout_ms); - - -#endif /* SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CLOUD_Connection_H_ */ - - diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_cmp.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_cmp.h deleted file mode 100644 index 381e024..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_cmp.h +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CMP_H_ -#define SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CMP_H_ - -#include - -#define CMP_PRODUCT_KEY_LEN (20 + 1) -#define CMP_DEVICE_NAME_LEN (32 + 1) -#define CMP_DEVICE_SECRET_LEN (64 + 1) -#define CMP_DEVICE_ID_LEN (64 + 1) - - -/* support mutli thread -#define CMP_SUPPORT_MULTI_THREAD */ - -/* -* CMP: connection manager platform -*/ - - -#define CMP_TOPIC_LEN_MAX 256 - - -/* domain type */ -typedef enum IOTX_CMP_CLOUD_DOMAIN_TYPES { - /* "iot-as-mqtt.cn-shanghai.aliyuncs.com" */ - IOTX_CMP_CLOUD_DOMAIN_SH, - - /* USA */ - IOTX_CMP_CLOUD_DOMAIN_USA, - - /* Maximum number of domain */ - IOTX_CMP_CLOUD_DOMAIN_MAX -}iotx_cmp_cloud_domain_types_t; - - -/* message confirmation type */ -typedef enum IOTX_CMP_MESSAGE_ACK_TYPES { - /* non ACK */ - /* MQTT: QoS is 0 */ - /* CoAP: NON */ - /* default */ - IOTX_CMP_MESSAGE_NO_ACK, - - /* need ACK */ - /* MQTT: QoS is 1 */ - /* CoAP: CON */ - IOTX_CMP_MESSAGE_NEED_ACK, - - /* Maximum number of domain */ - IOTX_CMP_MESSAGE_ACK_MAX -}iotx_cmp_message_ack_types_t; - - -/* event type */ -typedef enum IOTX_CMP_EVENT_TYPES { - /* cloud connected */ - /* event_msg is null */ - IOTX_CMP_EVENT_CLOUD_CONNECTED = 0, - - /* cloud disconnect */ - /* event_msg is null */ - IOTX_CMP_EVENT_CLOUD_DISCONNECT = 1, - - /* cloud reconnect */ - /* event_msg is null */ - IOTX_CMP_EVENT_CLOUD_RECONNECT = 2, - - /* local: found device */ - /* event_msg is iotx_cmp_event_device_pt */ - IOTX_CMP_EVENT_FOUND_DEVICE = 10, - - /* local: remove device */ - /* event_msg is iotx_cmp_event_device_pt */ - IOTX_CMP_EVENT_REMOVE_DEVICE = 11, - - /* register */ - /* event_msg is iotx_cmp_event_result_pt */ - IOTX_CMP_EVENT_REGISTER_RESULT = 20, - - /* unregister */ - /* event_msg is iotx_cmp_event_result_pt */ - IOTX_CMP_EVENT_UNREGISTER_RESULT = 21, - - /* send */ - /* event_msg is iotx_cmp_event_result_pt */ - IOTX_CMP_EVENT_SEND_RESULT = 22, - - /* new data receive */ - /* used by undefined CMP_SUPPORT_TOPIC_DISPATCH */ - /* event_msg is iotx_cmp_ota_parameter_t */ - IOTX_CMP_EVENT_NEW_DATA_RECEIVED = 30, - - /* Maximum number of protocol */ - IOTX_CMP_EVENT_MAX -}iotx_cmp_event_types_t; - - -/* URI type */ -typedef enum IOTX_CMP_URI_TYPES { - /* /sys/product_key/device_name/... */ - IOTX_CMP_URI_SYS = 1, - - /* /ext/product_key/device_name/... */ - IOTX_CMP_URI_EXT = 2, - - /* set by user */ - IOTX_CMP_URI_UNDEFINE = 3, - - /* Maximum number of protocol */ - IOTX_CMP_URI_MAX -}iotx_cmp_uri_types_t; - - -typedef enum IOTX_CMP_PAYLOAD_TYPE { - /* RAW */ - IOTX_CMP_MESSAGE_RAW = 1, - - /* request */ - /* method and parameter is non-value, code is 0 */ - IOTX_CMP_MESSAGE_REQUEST = 2, - - /* response */ - /* code and parameter is non-value, method is NULL */ - /* parameter is for data node */ - IOTX_CMP_MESSAGE_RESPONSE = 3, - - IOTX_CMP_PAYLOAD_MAX -}iotx_cmp_message_types_t; - - -/* message confirmation type */ -typedef enum IOTX_CMP_DEVICE_SECRET_TYPES { - /* 一型一密 */ - IOTX_CMP_DEVICE_SECRET_PRODUCT, - - /* 一机一密 */ - IOTX_CMP_DEVICE_SECRET_DEVICE, - - /* Maximum number of domain */ - IOTX_CMP_DEVICE_SECRET_TYPES_MAX -}iotx_cmp_device_secret_types_t; - - -#ifdef SERVICE_OTA_ENABLED -/* URI type */ -typedef enum IOTX_CMP_OTA_TYPE { - /* FOTA */ - IOTX_CMP_OTA_TYPE_FOTA = 1, - - /* COTA */ - IOTX_CMP_OTA_TYPE_COTA = 2, - - /* Maximum */ - IOTX_CMP_OTA_TYPE_MAX -}iotx_cmp_ota_types_t; -#endif /* SERVICE_OTA_ENABLED */ - - -/* The structure of event for cloud found new device */ -typedef struct { - char product_key[CMP_PRODUCT_KEY_LEN + 1]; - char device_name[CMP_DEVICE_NAME_LEN + 1]; -} iotx_cmp_event_device_t, *iotx_cmp_event_device_pt; - - -/* The structure of event for register/unregister result */ -typedef struct { - /* 0: success, -1:nack */ - int8_t result; - char *URI; - iotx_cmp_uri_types_t URI_type; -} iotx_cmp_event_result_t, *iotx_cmp_event_result_pt; - - - -#ifdef SERVICE_OTA_ENABLED -/* The structure of fota result */ -typedef struct { - uint32_t size_file; /* size of file */ - char *purl; /* point to URL */ - char *version; /* point to string */ -} iotx_cmp_fota_parameter_t, *iotx_cmp_fota_parameter_pt; - - -/* The structure of cota result */ -typedef struct { - char *configId; /* config ID */ - uint32_t configSize; /* config size */ - char *sign; /* sign */ - char *signMethod; /* sign method */ - char *url; /* point to URL */ - char *getType; /* getType */ -} iotx_cmp_cota_parameter_t, *iotx_cmp_cota_parameter_pt; -#endif /* SERVICE_OTA_ENABLED */ - - -/* The structure of cmp event msg */ -typedef struct { - uint8_t event_id; - void* msg; -} iotx_cmp_event_msg_t, *iotx_cmp_event_msg_pt; - - -/* The structure of cmp event msg */ -typedef struct { - /* If it is the IOTX_CMP_MESSAGE_REQUEST in IOT_CMP_Send, this id is no mean. - * If it is the IOTX_CMP_MESSAGE_RESPONSE in IOT_CMP_Send, - * this id is must have value, read in register_callback's IOTX_CMP_MESSAGE_REQUEST. - * If is is the IOTX_CMP_MESSAGE_RESPONSE in register_callback, this id is no mean. - * If is is the IOTX_CMP_MESSAGE_REQUEST in register_callback, this id must be non-null. */ - int id; - iotx_cmp_message_ack_types_t ack_type; - char *URI; - iotx_cmp_uri_types_t URI_type; - unsigned int code; /* [in/out] */ - char *method; - void *parameter; - unsigned int parameter_length; - iotx_cmp_message_types_t message_type; /* response, request or raw */ -} iotx_cmp_message_info_t, *iotx_cmp_message_info_pt; - - -/* The structure of event for cloud found new device */ -typedef struct { - char product_key[CMP_PRODUCT_KEY_LEN + 1]; - char device_name[CMP_DEVICE_NAME_LEN + 1]; -} iotx_cmp_send_peer_t, *iotx_cmp_send_peer_pt; - - -/* The structure of new data */ -typedef struct { - iotx_cmp_send_peer_pt peer; - iotx_cmp_message_info_pt message_info; -} iotx_cmp_new_data_t, *iotx_cmp_new_data_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 user_data : The user_data set by user. - * @param msg : The event message. - * - * @return none - */ -typedef void (*iotx_cmp_event_handle_func_fpt)(void *pcontext, iotx_cmp_event_msg_pt msg, void *user_data); - - -#ifdef SERVICE_OTA_ENABLED -/** - * @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 ota_parameter : The fota parameter. - * @param user_data : The user_data set by user. - * - * @return none - */ -typedef void (*iotx_cmp_fota_handle_func_fpt)(void *pcontext, iotx_cmp_fota_parameter_pt ota_parameter, void *user_data); - -/** - * @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 ota_parameter : The cota parameter. - * @param user_data : The user_data set by user. - * - * @return none - */ -typedef void (*iotx_cmp_cota_handle_func_fpt)(void *pcontext, iotx_cmp_cota_parameter_pt ota_parameter, void *user_data); -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief It define a datatype of function pointer. - * This type of function will be called when received a related resqust. - * - * @param target : The register source. - * @param user_data : The user_data set by user. - * @param msg : The message info. - * - * @return none - */ -typedef void (*iotx_cmp_register_func_fpt)(iotx_cmp_send_peer_pt source, iotx_cmp_message_info_pt msg, void *user_data); - - -/* The structure of CMP param */ -typedef struct { - iotx_cmp_device_secret_types_t secret_type; - iotx_cmp_cloud_domain_types_t domain_type; - iotx_cmp_event_handle_func_fpt event_func; - void *user_data; -} iotx_cmp_init_param_t, *iotx_cmp_init_param_pt; - - -/* The structure of Register param */ -typedef struct { - char *URI; - iotx_cmp_uri_types_t URI_type; - iotx_cmp_message_types_t message_type; - iotx_cmp_register_func_fpt register_func; - void *user_data; - void *mail_box; -} iotx_cmp_register_param_t, *iotx_cmp_register_param_pt; - - -/* The structure of Register param */ -typedef struct { - char *URI; - iotx_cmp_uri_types_t URI_type; -} iotx_cmp_unregister_param_t, *iotx_cmp_unregister_param_pt; - - -#ifdef SERVICE_OTA_ENABLED -typedef struct { - iotx_cmp_ota_types_t ota_type; - /* if there is more data to download, is_more is 1, else is_more is 0 */ - uint8_t is_more; /* [out] */ - /* is_more is 0, result: */ - /* - * Burn firmware file failed -4 - * Check firmware file failed -3 - * Fetch firmware file failed -2 - * Initialized failed -1 - * success 0 - */ - int8_t result; /* [out] */ - int progress; /* [out] */ - void* buffer; /* [in/out] */ - int buffer_length; /* [in/out] */ -} iotx_cmp_ota_t, *iotx_cmp_ota_pt; -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief CMP init - * This function initialize the CMP structures, establish network connection - * If CMP has been initialized, this function will return success directly. - * - * @param pparam, specify the cmp and event handler. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Init(iotx_cmp_init_param_pt pparam, void* option); - - -#ifdef SERVICE_OTA_ENABLED -/** - * @brief Start OTA - * This function use to start OTA, set cur_version and ota_func. - * - * @param cur_version, current version. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_OTA_Start(char* cur_version, void* option); - - -/** -* @brief Set OTA callback -* This function use to set OTA callback. -* -* @param type, fota or cota. -* @param ota_func, ota callback function. -* @param user_context, ota callback user context. -* @param option, reserve. -* -* @return success or fail. -*/ -int IOT_CMP_OTA_Set_Callback(iotx_cmp_ota_types_t type, void* ota_func, void* user_context, void* option); - - -/** -* @brief Get Config -* -* -* @param configScope, device or product. -* @param getType, file or other type. -* @param attributeKeys -* @param option, reserve. -* -* @return success or fail. -*/ -int IOT_CMP_OTA_Get_Config(const char* configScope, const char* getType, const char* attributeKeys, void* option); - - -/** -* @brief Get firmware image -* -* -* @param version, firmware image version. -* @param option, reserve. -* -* @return success or fail. -*/ -int IOT_CMP_OTA_Request_Image(const char* version, void* option); -#endif /* SERVICE_OTA_ENABLED */ - - -/** - * @brief Register service. - * This function used to register some service by different URI, set the URI's callback. - * If it is received a request, will callback the register_cb. - * If there is no match register_cb (user have not register the service set callback), the request will be discard. - * - * @param pparam, register parameter, include URI and register callback. - * @param option, reserve. - * This API not support one URI register twice, if the URI have been register, it will return fail. - * - * @return success or fail. - */ -int IOT_CMP_Register(iotx_cmp_register_param_pt pparam, void* option); - - -/** - * @brief Unregister service. - * This function used to unregister some service by different URI - * - * @param pparam, unregister parameter, include URI. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Unregister(iotx_cmp_unregister_param_pt pparam, void* option); - - -/** - * @brief Send data. - * This function used to send data to target. - * If the target is NULL, the data will broadcast to all the reachable places. - * If the target is not NULL, the data will send to target only. - * If the target's product_key and device_name is itself, the data will send to cloud. - * - * @param target. - * @param message_info. - * @param option, reserve. - * - * @return success or fail. - * - */ -int IOT_CMP_Send(iotx_cmp_send_peer_pt target, iotx_cmp_message_info_pt message_info, void* option); - - -#ifndef CMP_SUPPORT_MULTI_THREAD - -/** - * @brief Send data. - * This function used to send data to target and wait for response. - * If the target is NULL, the data will broadcast to all the reachable places. - * If the target is not NULL, the data will send to target only. - * If the target's product_key and device_name is itself, the data will send to cloud. - * - * @param target. - * @param message_info [in/out]. - * @param option, reserve. - * - * @return success or fail. - * - */ -int IOT_CMP_Send_Sync(iotx_cmp_send_peer_pt target, iotx_cmp_message_info_pt message_info, void* option); - - -/** - * @brief Yield. - * This function used to yield when want to received data. - * This function just need used in CMP_SUPPORT_MULTI_THREAD = n. - * If the CMP_SUPPORT_MULTI_THREAD = y, this function is no need. - * - * @param target. - * @param message_info. - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Yield(int timeout_ms, void* option); -#endif /* CMP_SUPPORT_MULTI_THREAD */ - - -/** - * @brief deinit - * - * @param option, reserve. - * - * @return success or fail. - */ -int IOT_CMP_Deinit(void* option); - -#ifdef SERVICE_OTA_ENABLED -/** - * @brief OTA yield function. - * Set buffer and length yield the ota data. - * - * @param ota_pt, ota yield params. - * - * @return success or fail. - */ -int IOT_CMP_OTA_Yield(iotx_cmp_ota_pt ota_pt); -#endif /* SERVICE_OTA_ENABLED */ - - -#ifdef UT_TEST -int request_inject(int id, char* uri, char* method, void* parameter, int parameter_len); - -int response_inject(int id, char* uri, int code, void* data, int data_length); - -#endif /* UT_TEST */ - - - -#endif /* SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_CMP_H_ */ - - diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_cota.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_cota.h deleted file mode 100644 index b842f86..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_cota.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * iot_export_cota.h - * - * Created on: 2018313 - * Author: wb-jn347227 - */ - -#ifndef SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_COTA_H_ -#define SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_COTA_H_ - -#include -#include -#include -#define CONFIG_COTA_MODULE_NAME "service_cota" -#define SERVICE_COTA_CLASS get_config_ota_class() - -#define config_ota_lite_free(ptr) \ - do { \ - if(!ptr) { \ - log_err("service_ota_lite_free(%p) aborted.", ptr); \ - break; \ - } \ - \ - LITE_free_internal((void *)ptr); \ - ptr = NULL; \ - } while(0) - -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); -void* config_ota_lite_calloc(size_t nmemb, size_t size); -void* config_ota_lite_malloc(size_t size); -void config_ota_lite_free_func(void* ptr); -typedef struct { - size_t size; - char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - int (*get)(void* _self,const char* configScope, const char* getType, const char* attributeKeys, void* option); - void (*start)(void* _self); - int (*write)(void* _self, void* data, int data_length); - int (*end)(void* _self); - int (*perform_ota_service)(void* _self, void* _data_buf, int _data_buf_length); - void (*install_callback_function)(void* _self, handle_service_cota_callback_fp_t linkkit_callback_fp); -} cota_t; - -typedef struct { - const void* _; - void* _data_buf; - int _data_buf_length; - int _total_len; - void* _linkkit_callback_fp; - char* _current_verison; - char* _req_configscope; - char* _req_gettype; - char* _req_attributekeys; - char* _rsp_configId; - uint32_t _rsp_configSize; - char* _rsp_sign; - char* _rsp_signMethod; - char* _rsp_url; - char* _rsp_getType; - int _ota_inited; - int _destructing; -} config_ota_t; - -extern const void* get_config_ota_class(); -#endif /* SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_COTA_H_ */ diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_dm.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_dm.h deleted file mode 100644 index 1d4356c..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_dm.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef DM_EXPORT_H -#define DM_EXPORT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#define DM_IMPL_CLASS get_dm_impl_class() - -typedef struct { - const void* _; - void* _logger; - char* _name; /* dm thing manager object name. */ - int _get_tsl_from_cloud; - void* _thing_manager; /* thing manager object */ - int _log_level; - int _domain_type; -} dm_impl_t; - - -typedef enum { - dm_callback_type_property_value_set = 0, - dm_callback_type_service_requested, -#ifdef RRPC_ENABLED - dm_callback_type_rrpc_requested, -#endif /* RRPC_ENABLED */ - dm_callback_type_cloud_connected, - dm_callback_type_cloud_disconnected, - dm_callback_type_new_thing_created, - dm_callback_type_thing_disabled, - dm_callback_type_thing_enabled, - dm_callback_type_raw_data_arrived, - dm_callback_type_response_arrived, - - dm_callback_type_number, -} dm_callback_type_t; - -typedef void (*handle_dm_callback_fp_t)(dm_callback_type_t callback_type, void* thing_id, - const char* property_service_identifier, int request_id, - void* raw_data, int raw_data_length); - -/* domain type */ -typedef enum { - /* iot-as-mqtt.cn-shanghai.aliyuncs.com */ - dm_cloud_domain_sh, - /* USA */ - dm_cloud_domain_usa, - - dm_cloud_domain_max, -} dm_cloud_domain_type_t; - -typedef struct { - size_t size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - void* (*generate_new_thing)(void* _self, const char* tsl, int tsl_len); - int (*set_property_value)(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - int (*set_event_output_value)(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - int (*set_service_output_value)(void* _self, const void* thing_id, const void* identifier, const void* value, const char* value_str); - int (*get_property_value)(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*get_service_input_value)(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*get_service_output_value)(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*get_event_output_value)(const void* _self, const void* thing_id, const void* identifier, void* value, char** value_str); - int (*install_callback_function)(void* _self, handle_dm_callback_fp_t linkkit_callback_fp); - int (*trigger_event)(const void* _self, const void* thing_id, const void* event_identifier, const char* property_identifier); -#ifdef DEVICEINFO_ENABLED - int (*trigger_deviceinfo_update)(const void* _self, const void* thing_id, const char* params); - int (*trigger_deviceinfo_delete)(const void* _self, const void* thing_id, const char* params); -#endif /* DEVICEINFO_ENABLED*/ -#ifdef RRPC_ENABLED - int (*answer_service)(const void* _self, const void* thing_id, const void* identifier, int response_id, int code, int rrpc); -#else - int (*answer_service)(const void* _self, const void* thing_id, const void* identifier, int response_id, int code); -#endif /* RRPC_ENABLED */ - int (*invoke_raw_service)(const void* _self, const void* thing_id, void* raw_data, int raw_data_length); - int (*answer_raw_service)(const void* _self, const void* thing_id, void* raw_data, int raw_data_length); -#ifndef CMP_SUPPORT_MULTI_THREAD - int (*yield)(const void* _self, int timeout_ms); -#endif -} dm_t; - -extern const void* get_dm_impl_class(); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* DM_EXPORT_H */ - diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_errno.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_errno.h deleted file mode 100644 index ccbec23..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_errno.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef __IOT_EXPORT_ERRNO__ -#define __IOT_EXPORT_ERRNO__ - -/* From utils_error.h */ -typedef enum IOT_RETURN_CODES { - ERROR_DEVICE_NOT_EXSIT = -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_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*/ - - - 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; -/* From utils_error.h */ - -#endif /* __IOT_EXPORT_ERRNO__ */ diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_fota.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_fota.h deleted file mode 100644 index 383e4e3..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_fota.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef FOTA_EXPORT_H -#define FOTA_EXPORT_H - -#include -#include - -#define SERVICE_FOTA_MODULE_NAME "service_fota" - -#define SERVICE_FOTA_CLASS get_service_ota_class() - -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); - -typedef struct { - size_t size; - char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); - void (*start)(void* _self); - int (*write)(void* _self, void* data, int data_length); - int (*end)(void* _self); - int (*perform_ota_service)(void* _self, void* _data_buf, int _data_buf_length); - void (*install_callback_function)(void* _self, handle_service_fota_callback_fp_t linkkit_callback_fp); -} fota_t; - -void* service_ota_lite_malloc(size_t size); -void* service_ota_lite_calloc(size_t nmemb, size_t size); -void service_ota_lite_free_func(void* ptr); - -#define service_ota_lite_free(ptr) \ - do { \ - if(!ptr) { \ - log_err("service_ota_lite_free(%p) aborted.", ptr); \ - break; \ - } \ - \ - LITE_free_internal((void *)ptr); \ - ptr = NULL; \ - } while(0) - -typedef struct { - const void* _; - void* _data_buf; - char* _version; - int _data_buf_length; - int _total_len; - char* _ota_version; - void* _linkkit_callback_fp; - char* _current_verison; - int _ota_inited; - int _destructing; -} service_ota_t; - -//extern const void* get_service_ota_class(); - - -#endif /* FOTA_EXPORT_H */ diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_shadow.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_shadow.h deleted file mode 100644 index 9c71b87..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_shadow.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef __SHADOW_EXPORT_H__ -#define __SHADOW_EXPORT_H__ - -/* From shadow.h */ -typedef enum { - IOTX_SHADOW_ACK_TIMEOUT = -1, - IOTX_SHADOW_ACK_NONE = 0, - IOTX_SHADOW_ACK_SUCCESS = 200, - IOTX_SHADOW_ACK_ERR_JSON_FMT_IS_INVALID = 400, - IOTX_SHADOW_ACK_ERR_METHOD_IS_NULL = 401, - IOTX_SHADOW_ACK_ERR_STATE_IS_NULL = 402, - IOTX_SHADOW_ACK_ERR_VERSION_IS_INVALID = 403, - IOTX_SHADOW_ACK_ERR_REPORTED_IS_NULL = 404, - IOTX_SHADOW_ACK_ERR_REPORTED_ATTRIBUTE_IS_NULL = 405, - IOTX_SHADOW_ACK_ERR_METHOD_IS_INVALID = 406, - IOTX_SHADOW_ACK_ERR_SHADOW_DOCUMENT_IS_NULL = 407, - IOTX_SHADOW_ACK_ERR_ATTRIBUTE_EXCEEDED = 408, - IOTX_SHADOW_ACK_ERR_SERVER_FAILED = 500, -} iotx_shadow_ack_code_t; - -typedef enum { - IOTX_SHADOW_READONLY, - IOTX_SHADOW_WRITEONLY, - IOTX_SHADOW_RW -} iotx_shadow_datamode_t; - -typedef enum { - IOTX_SHADOW_NULL, - IOTX_SHADOW_INT32, - IOTX_SHADOW_STRING, -} iotx_shadow_attr_datatype_t; - -typedef struct { - int flag_new; - uint32_t buf_size; - uint32_t offset; - char *buf; -} format_data_t, *format_data_pt; - -typedef struct { - uint32_t base_system_time; /* in millisecond */ - uint32_t epoch_time; -} iotx_shadow_time_t, *iotx_shadow_time_pt; - -typedef void (*iotx_push_cb_fpt)( - void *pcontext, - int ack_code, - const char *ack_msg, /* NOTE: NOT a string. */ - uint32_t ack_msg_len); - -struct iotx_shadow_attr_st; - -typedef void (*iotx_shadow_attr_cb_t)(struct iotx_shadow_attr_st *pattr); -typedef struct iotx_shadow_attr_st { - iotx_shadow_datamode_t mode; /* data mode */ - const char *pattr_name; /* attribute name */ - void *pattr_data; /* pointer to the attribute data */ - iotx_shadow_attr_datatype_t attr_type; /* data type */ - uint32_t timestamp; /* timestamp in Epoch(Unix) format */ - iotx_shadow_attr_cb_t callback; /* callback when related control message come. */ -} iotx_shadow_attr_t, *iotx_shadow_attr_pt; - -typedef struct { - iotx_mqtt_param_t mqtt; -} iotx_shadow_para_t, *iotx_shadow_para_pt; - -/** @defgroup group_api api - * @{ - */ - -/** @defgroup group_shadow shadow - * @{ - */ - -/** - * @brief Construct the Device Shadow. - * This function initialize the data structures, establish MQTT connection. - * and subscribe the topic: "/shadow/get/${product_key}/${device_name}". - * - * @param [in] pparam: The specific initial parameter. - * @retval NULL : Construct shadow failed. - * @retval NOT_NULL : Construct success. - * @see None. - */ -void *IOT_Shadow_Construct(iotx_shadow_para_pt pparam); - -/** - * @brief Deconstruct the specific device shadow. - * - * @param [in] handle: The handle of device shaodw. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_Destroy(void *handle); - -/** - * @brief Handle MQTT packet from cloud and wait list. - * - * @param [in] handle: The handle of device shaodw. - * @param [in] timeout_ms: Specify the timeout value in millisecond. In other words, the API block 'timeout'_ms millisecond maximumly. - * @return None. - * @see None. - */ -void IOT_Shadow_Yield(void *handle, uint32_t timeout_ms); - -/** - * @brief Create a data type registered to the server. - * - * @param [in] handle: The handle of device shaodw. - * @param [in] pattr: The parameter which registered to the server. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_RegisterAttribute(void *handle, iotx_shadow_attr_pt pattr); - -/** - * @brief Delete the specific attribute. - * - * @param [in] handle: The handle of device shaodw. - * @param [in] pattr: The parameter to be deleted from server. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_DeleteAttribute(void *handle, iotx_shadow_attr_pt pattr); - -/** - * @brief Start a process the structure of the data type format. - * - * @param [in] handle: The handle of device shaodw. - * @param [out] pformat: The format struct of device shadow. - * @param [in] buf: The buf which store device shadow. - * @param [in] size: Maximum length of device shadow attribute. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_PushFormat_Init( - void *handle, - format_data_pt pformat, - char *buf, - uint16_t size); - -/** - * @brief Format the attribute name and value for update. - * - * @param [in] handle: The handle of device shaodw. - * @param [in] pformat: The format struct of device shadow. - * @param [in] pattr: To have created the data type of the format in the add member attributes. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_PushFormat_Add( - void *handle, - format_data_pt pformat, - iotx_shadow_attr_pt pattr); - -/** - * @brief Complete a process the structure of the data type format. - * - * @param [in] handle: The handle of device shaodw. - * @param [in] pformat: The format struct of device shadow. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_PushFormat_Finalize(void *handle, format_data_pt pformat); - -/** - * @brief Update data to Cloud. It is a synchronous interface. - * - * @param [in] handle: The handle of device shaodw. - * @param [in] data: The buf which synchronization with the server. - * @param [in] data_len: The length, in bytes, of the data pointed to by the data parameter. - * @param [in] timeout_s: The timeout_s in second.In other word,the API will block timeout_s second. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_Push( - void *handle, - char *data, - uint32_t data_len, - uint16_t timeout_s); - -/** - * @brief Update data to Cloud. It is a asynchronous interface. - * The result of this update will be informed by calling the callback function cb_fpt. - * @param [in] handle: The handle of device shadow. - * @param [in] data: The buf which synchronization with the server. - * @param [in] data_len: The length, in bytes, of the data pointed to by the data parameter. - * @param [in] timeout_s: Specify the timeout value in second. Shadow will timeout after 'timeout_s' second if did not receive push response. - * @param [in] cb_fpt: Specify the callback function which recieve ack_code from server after push device shadow. - * @param [in] pcontext: Specify the context which passed to the callback function. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -int IOT_Shadow_Push_Async( - void *handle, - char *data, - size_t data_len, - uint16_t timeout_s, - iotx_push_cb_fpt cb_fpt, - void *pcontext); - -/** - * @brief Synchronize device shadow data from cloud. - * It is a synchronous interface. - * @param [in] handle: The handle of device shaodw. - * @retval SUCCESS_RETURN : Success. - * @retval other : See iotx_err_t. - * @see None. - */ -iotx_err_t IOT_Shadow_Pull(void *handle); - -/* From shadow.h */ - -/** @} */ /* end of api_shadow */ -/** @} */ /* end of api */ - -#endif /* __SHADOW_EXPORT_H__ */ diff --git a/iotkit-embedded/src/sdk-impl/exports/iot_export_subdev.h b/iotkit-embedded/src/sdk-impl/exports/iot_export_subdev.h deleted file mode 100644 index 3bfe9fd..0000000 --- a/iotkit-embedded/src/sdk-impl/exports/iot_export_subdev.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_SUBDEV_H_ -#define SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_SUBDEV_H_ - -#include "iot_export.h" - -#define IOT_GATEWAY_YIELD_MAX_COUNT 100 -#define IOT_SUBDEVICE_CLIENT_ID_LEN 64 - - -/* option defined for gateway support multi-thread */ -/*#define IOT_GATEWAY_SUPPORT_MULTI_THREAD*/ - -/* Topic maximum length value */ -#define GATEWAY_TOPIC_LEN_MAX 256 - -/* Reply message maximum length value */ -#define REPLY_MESSAGE_LEN_MAX 1024 - -/* The format of session combine topic */ -#define TOPIC_SESSION_COMBINE_FMT "/ext/session/%s/%s/combine/%s" - -/* The format of session sub topic */ -#define TOPIC_SESSION_SUB_FMT "/sys/%s/%s/thing/sub/%s" - -/* The format of session topo topic */ -#define TOPIC_SESSION_TOPO_FMT "/sys/%s/%s/thing/topo/%s" - -/* The format of session config topic */ -#define TOPIC_SESSION_CONFIG_FMT "/sys/%s/%s/thing/config/%s" - -/* The format of session found list topic */ -#define TOPIC_SESSION_LIST_FOUND_FMT "/sys/%s/%s/thing/list/%s" - -/* The format of system RRPC topic */ -#define TOPIC_SYS_RRPC_FMT "/sys/%s/%s/rrpc/%s/+" - - -/* Subdevice register/login sign method */ -typedef enum IOTX_SUBDEV_SIGN_METHOD_TYPES { - /* HmacSha1 */ - IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA, - - /* HmacMd5 */ - IOTX_SUBDEV_SIGN_METHOD_TYPE_MD5, - - /* Undefined */ - IOTX_SUBDEV_SIGN_METHOD_TYPE_UNDEFINED, - - /* Maximum number of login sign method */ - IOTX_SUBDEV_SIGN_METHOD_TYPE_MAX -}iotx_subdev_sign_method_types_t; - - -/* Subdevice login clean seesion type */ -typedef enum IOTX_SUBDEV_CLEAN_SESSION_TYPES { - /* True */ - IOTX_SUBDEV_CLEAN_SESSION_TRUE, - - /* False */ - IOTX_SUBDEV_CLEAN_SESSION_FALSE, - - /* Undefined */ - IOTX_SUBDEV_CLEAN_SESSION_UNDEFINED, - - /* Maximum number of login clean seesion type */ - IOTX_SUBDEV_CLEAN_SESSION_MAX -}iotx_subdev_clean_session_types_t; - - -/* Register type */ -typedef enum IOTX_SUBDEV_REGISTER_TYPES { - /* static, via web get device_secert */ - IOTX_SUBDEV_REGISTER_TYPE_STATIC, - - /* dynamic, via register API get device_secert */ - IOTX_SUBDEV_REGISTER_TYPE_DYNAMIC, - - IOTX_SUBDEV_REGISTER_TYPE_MAX -}iotx_subdev_register_types_t; - - -/** - * @brief It define a datatype of function pointer. - * This type of function will be called when a RRPC occur. - * - * @param gateway, the gateway context - * @param product_key, the product key - * @param deveice_name, the deveice name - * @param message_id, the RRPC's message id - * @param payload, the RRPC's payload - * payload is consists by message id, method and params - * for example: - * "method":"thing.service.property.set"; - * "method":"thing.service.property.get"; - * "method":"thing.service.{dsl.service.identifer}"; - * "method":"thing.service.disable"; - * "method":"thing.service.delete"; - * "method":"thing.service.enable"; - * - * @return none - */ -typedef void (*rrpc_request_callback)(void* gateway, - const char* product_key, - const char* deveice_name, - const char* message_id, - const char* payload); - -/** - * @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 subdevice. - * @param msg : The event message. - * if SUBDEV_VIA_CLOUD_CONN is define, the msg is iotx_cloud_connection_msg_rsp_func_fpt - * else the msg is iotx_mqtt_event_msg_pt - * - * @return none - */ -typedef void (*iotx_subdev_event_handle_func_fpt)(void *pcontext, void *pclient, void* msg); - - -/* The structure of gateway param */ -typedef struct { - iotx_mqtt_param_pt mqtt; /* MQTT params */ - /* If there is another user want to handle the MQTT event, - * must set the event_handler and event pcontext */ - void* event_pcontext; /* the user of gateway */ - iotx_subdev_event_handle_func_fpt event_handler; /* event handler for gateway user*/ -} iotx_gateway_param_t, *iotx_gateway_param_pt; - - -/** - * @brief Generate message id. - * - * @param NULL. - * - * @return Message id. - */ -uint32_t IOT_Gateway_Generate_Message_ID(); - - -/** - * @brief Construct the Gateway - * This function initialize the data structures, establish MQTT connection, - * subscribe some default topic. - * - * @param gateway_param, specify the MQTT client parameter and event handler. - * - * @return NULL, construct failed; NOT NULL, the handle of Gateway. - */ -void* IOT_Gateway_Construct(iotx_gateway_param_pt gateway_param); - - -/** - * @brief Deconstruct the Gateway - * This function unsubscribe default topic, disconnect MQTT connection and - * release the related resource. - * - * @param pointer of handle, specify the Gateway. - * - * @return 0, deconstruct success; -1, deconstruct failed. - */ -int IOT_Gateway_Destroy(void** handle); - - -/** - * @brief Device register - * This function used to register device and add topo. - * - * @param pointer of handle, specify the gateway construction. - * @param register type. - * IOTX_SUBDEV_REGISTER_TYPE_STATIC - * IOTX_SUBDEV_REGISTER_TYPE_DYNAMIC - * @param product key. - * @param device name. - * @param timestamp. [if type = dynamic, must be NULL ] - * @param client_id. [if type = dynamic, must be NULL ] - * @param sign. [if type = dynamic, must be NULL ] - * @param sign_method. - * IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA - * IOTX_SUBDEV_SIGN_METHOD_TYPE_MD5 - * - * @return 0, Logout success; -1, Logout fail. - */ -int IOT_Subdevice_Register(void* handle, - iotx_subdev_register_types_t type, - const char* product_key, - const char* device_name, - char* timestamp, - char* client_id, - char* sign, - iotx_subdev_sign_method_types_t sign_type); - - -/** - * @brief Device unregister - * This function used to delete topo and unregister device. - * The device must dynamic register again if it want to use after unregister. - * - * @param pointer of handle, specify the gateway construction. - * @param product key. - * @param device name. - * - * @return 0, Unregister success; -1, Unregister fail. - */ -int IOT_Subdevice_Unregister(void* handle, - const char* product_key, - const char* device_name); - -/** - * @brief Subdevice login - * This function publish a packet with LOGIN topic and wait for the reply (with - * LOGIN_REPLY topic), then subscribe some subdevice topic. - * - * @param pointer of handle, specify the Gateway. - * @param product key. - * @param device name. - * @param timestamp. [if register_type = dynamic, must be NULL ] - * @param client_id. [if register_type = dynamic, must be NULL ] - * @param sign. [if register_type = dynamic, must be NULL ] - * @param sign method, HmacSha1 or HmacMd5. - * @param clean session, ture or false. - * - * @return 0, login success; -1, login failed. - */ -int IOT_Subdevice_Login(void* handle, - const char* product_key, - const char* device_name, - const char* timestamp, - const char* client_id, - const char* sign, - iotx_subdev_sign_method_types_t sign_method_type, - iotx_subdev_clean_session_types_t clean_session_type); - - -/** - * @brief Subdevice logout - * This function unsubscribe some subdevice topic, then publish a packet with - * LOGOUT topic and wait for the reply (with LOGOUT_REPLY topic). - * - * @param pointer of handle, specify the Gateway. - * @param product key. - * @param device name. - * - * @return 0, logout success; -1, logout failed. - */ -int IOT_Subdevice_Logout(void* handle, - const char* product_key, - const char* device_name); - - -/** - * @brief Gateway get topo - * This function publish a packet with topo/get topic and wait for the reply (with TOPO_GET_REPLY topic). - * - * @param pointer of handle, specify the Gateway. - * @param get_toop_reply. - * @param length [in/out]. in -- get_topo_reply buffer length, out -- reply length - * - * @return 0, logout success; -1, logout failed. - */ -int IOT_Gateway_Get_TOPO(void* handle, - char* get_topo_reply, - uint32_t* length); - -/** - * @brief Gateway get config - * This function publish a packet with config/get topic and wait for the reply (with CONFIG_GET_REPLY topic). - * - * @param pointer of handle, specify the Gateway. - * @param get_config_reply. - * @param length [in/out]. in -- get_config_reply buffer length, out -- reply length - * - * @return 0, logout success; -1, logout failed. - */ -int IOT_Gateway_Get_Config(void* handle, - char* get_config_reply, - uint32_t* length); - -/** - * @brief Gateway publish found list - * This function publish a packet with new subdevice found list. - * - * @param pointer of handle, specify the Gateway. - * - * @return 0, publish success; -1, publish failed. - */ -int IOT_Gateway_Publish_Found_List(void* handle, const char* product_key, - const char* device_name); - - -/** - * @brief Gateway Yield - * This function used to received some packets. - * - * @param pointer of handle, specify the Gateway. - * @param timeout interval. - * - * @return 0, yield success; -1, parameter error. - */ -int IOT_Gateway_Yield(void* handle, uint32_t timeout); - - -/** - * @brief Gateway Subscribe - * This function used to subscribe some topic. - * - * @param pointer of handle, specify the Gateway. - * @param topic list. - * @param QoS. - * @param receive data function. - * @param topic_handle_func's userdata. - * - * @return 0, Subscribe success; -1, Subscribe fail. - */ -int IOT_Gateway_Subscribe(void* handle, - const char *topic_filter, - int qos, - iotx_subdev_event_handle_func_fpt topic_handle_func, - void *pcontext); - - -/** - * @brief Gateway Unsubscribe - * This function used to unsubscribe some topic. - * - * @param pointer of handle, specify the Gateway. - * @param topic list. - * - * @return 0, Unsubscribe success; -1, Unsubscribe fail. - */ -int IOT_Gateway_Unsubscribe(void* handle, const char* topic_filter); - - -/** - * @brief Gateway Publish - * This function used to Publish some packet. - * - * @param pointer of handle, specify the Gateway. - * @param topic. - * @param mqtt packet. - * - * @return 0, Publish success; -1, Publish fail. - */ -int IOT_Gateway_Publish(void* handle, - const char *topic_name, - iotx_mqtt_topic_info_pt topic_msg); - - -/** - * @brief Register RRPC callback - * This function used to register one RRPC callback. - * - * @param pointer of handle, specify the Gateway. - * @param product key. - * @param device name. - * @param rrpc callback function. - * every device has RRPC callback by itself. - * - * @return 0, Register success; -1, Register fail. - */ -int IOT_Gateway_RRPC_Register(void* handle, - const char* product_key, - const char* device_name, - rrpc_request_callback rrpc_callback); - - -/** - * @brief Response RRPC request - * This function used to response the RRPC request. - * - * @param pointer of handle, specify the Gateway. - * @param product key. - * @param device name. - * @param The message id of RRPC request. - * @param Response data. - * - * @return 0, Response success; -1, Response fail. - */ -int IOT_Gateway_RRPC_Response(void* handle, - const char* product_key, - const char* device_name, - const char* message_id, - const char* response); - - -#endif /* SRC_SDK_IMPL_EXPORTS_IOT_EXPORT_SUBDEV_H_ */ - - diff --git a/iotkit-embedded/src/sdk-impl/imports/iot_import_coap.h b/iotkit-embedded/src/sdk-impl/imports/iot_import_coap.h deleted file mode 100644 index e9f327e..0000000 --- a/iotkit-embedded/src/sdk-impl/imports/iot_import_coap.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __COAP_PLATFORM_H__ -#define __COAP_PLATFORM_H__ -#include "iot_import.h" - -#define coap_malloc(size) HAL_Malloc(size) -#define coap_free(ptr) HAL_Free(ptr) - -#endif diff --git a/iotkit-embedded/src/sdk-impl/imports/iot_import_config.h b/iotkit-embedded/src/sdk-impl/imports/iot_import_config.h deleted file mode 100644 index b6eba39..0000000 --- a/iotkit-embedded/src/sdk-impl/imports/iot_import_config.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __IOT_IMPORT_CONFIG_H__ -#define __IOT_IMPORT_CONFIG_H__ - -#ifndef CONFIG_HTTP_AUTH_TIMEOUT - #define CONFIG_HTTP_AUTH_TIMEOUT (5 * 1000) -#endif - -#ifndef CONFIG_MID_HTTP_TIMEOUT - #define CONFIG_MID_HTTP_TIMEOUT (5 * 1000) -#endif - -#ifndef CONFIG_GUIDER_AUTH_TIMEOUT - #define CONFIG_GUIDER_AUTH_TIMEOUT (10 * 1000) -#endif - -#ifndef CONFIG_COAP_AUTH_TIMEOUT - #define CONFIG_COAP_AUTH_TIMEOUT (10 * 1000) -#endif - -#endif /* __IOT_IMPORT_CONFIG_H__ */ diff --git a/iotkit-embedded/src/sdk-impl/imports/iot_import_dtls.h b/iotkit-embedded/src/sdk-impl/imports/iot_import_dtls.h deleted file mode 100644 index 30f4c04..0000000 --- a/iotkit-embedded/src/sdk-impl/imports/iot_import_dtls.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include -#include - -#include "iot_import_coap.h" - -#ifndef __COAP_DTLS_H__ -#define __COAP_DTLS_H__ - -#define dtls_log_print(level, ...) \ - {\ - fprintf(stderr, "%s [%s #%d] ",level, __FILE__, __LINE__); \ - fprintf(stderr, __VA_ARGS__);\ - } - -#define DTLS_TRC(fmt, ...) dtls_log_print("", fmt, ##__VA_ARGS__) -#define DTLS_DUMP(fmt, ...) dtls_log_print(" ", fmt, ##__VA_ARGS__) -#define DTLS_DEBUG(fmt,...) dtls_log_print("", fmt, ##__VA_ARGS__) -#define DTLS_INFO(fmt, ...) dtls_log_print(" ", fmt, ##__VA_ARGS__) -#define DTLS_ERR(fmt, ...) dtls_log_print("", fmt, ##__VA_ARGS__) - -#define DTLS_ERROR_BASE (1<<24) - - -#define DTLS_SUCCESS 0 -#define DTLS_INVALID_PARAM (DTLS_ERROR_BASE | 1) -#define DTLS_INVALID_CA_CERTIFICATE (DTLS_ERROR_BASE | 2) -#define DTLS_HANDSHAKE_IN_PROGRESS (DTLS_ERROR_BASE | 3) -#define DTLS_HANDSHAKE_FAILED (DTLS_ERROR_BASE | 4) -#define DTLS_FATAL_ALERT_MESSAGE (DTLS_ERROR_BASE | 5) -#define DTLS_PEER_CLOSE_NOTIFY (DTLS_ERROR_BASE | 6) -#define DTLS_SESSION_CREATE_FAILED (DTLS_ERROR_BASE | 7) -#define DTLS_READ_DATA_FAILED (DTLS_ERROR_BASE | 8) - - -typedef struct { - unsigned char *p_ca_cert_pem; - char *p_host; - unsigned short port; -} coap_dtls_options_t; - - -typedef void DTLSContext; - -/** @defgroup group_platform platform - * @{ - */ - - -/** @defgroup group_platform_dtls dtls - * @{ - */ - - -/** - * @brief Establish a DSSL connection. - * - * @param [in] p_options: @n Specify paramter of DTLS - @verbatim - p_host : @n Specify the hostname(IP) of the DSSL server - port : @n Specify the DSSL port of DSSL server - p_ca_cert_pem : @n Specify the root certificate which is PEM format. - @endverbatim - * @return DSSL handle. - * @see None. - * @note None. - */ -DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options); - -/** - * @brief Write data into the specific DSSL connection. - * - * @param [in] context @n A descriptor identifying a connection. - * @param [in] p_data @n A pointer to a buffer containing the data to be transmitted. - * @param [in] p_datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. - * @retval DTLS_SUCCESS : Success. - @retval other : Fail. - * @see None. - */ -unsigned int HAL_DTLSSession_write(DTLSContext *context, - const unsigned char *p_data, - unsigned int *p_datalen); -/** - * @brief Read data from the specific DSSL connection with timeout parameter. - * The API will return immediately if len be received from the specific DSSL connection. - * - * @param [in] context @n A descriptor identifying a DSSL connection. - * @param [in] p_data @n A pointer to a buffer to receive incoming data. - * @param [in] p_datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * @return The result of read data from DSSL connection - * @retval DTLS_SUCCESS : Read success. - * @retval DTLS_FATAL_ALERT_MESSAGE : Recv peer fatal alert message. - * @retval DTLS_PEER_CLOSE_NOTIFY : The DTLS session was closed by peer. - * @retval DTLS_READ_DATA_FAILED : Read data fail. - * @see None. - */ -unsigned int HAL_DTLSSession_read(DTLSContext *context, - unsigned char *p_data, - unsigned int *p_datalen, - unsigned int timeout_ms); -/** - * @brief Destroy the specific DSSL connection. - * - * @param[in] context: @n Handle of the specific connection. - * - * @return The result of free dtls session - * @retval DTLS_SUCCESS : Read success. - * @retval DTLS_INVALID_PARAM : Invalid parameter. - * @retval DTLS_INVALID_CA_CERTIFICATE : Invalid CA Certificate. - * @retval DTLS_HANDSHAKE_IN_PROGRESS : Handshake in progress. - * @retval DTLS_HANDSHAKE_FAILED : Handshake failed. - * @retval DTLS_FATAL_ALERT_MESSAGE : Recv peer fatal alert message. - * @retval DTLS_PEER_CLOSE_NOTIFY : The DTLS session was closed by peer. - * @retval DTLS_SESSION_CREATE_FAILED : Create session fail. - * @retval DTLS_READ_DATA_FAILED : Read data fail. - */ -unsigned int HAL_DTLSSession_free(DTLSContext *context); - -/** @} */ /* end of platform_dtls */ -/** @} */ /* end of platform */ - -#endif diff --git a/iotkit-embedded/src/sdk-impl/imports/iot_import_ota.h b/iotkit-embedded/src/sdk-impl/imports/iot_import_ota.h deleted file mode 100644 index 725d96c..0000000 --- a/iotkit-embedded/src/sdk-impl/imports/iot_import_ota.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _OTA_IMPORT_H_ -#define _OTA_IMPORT_H_ - -#include "iot_import.h" -#include "iot_export_mqtt.h" -#include "lite-log.h" -#include "json_parser.h" -#include "utils_md5.h" -#include "utils_httpc.h" - - -#define OTA_MALLOC HAL_Malloc -#define OTA_FREE HAL_Free -#define OTA_LOG_DEBUG log_debug -#define OTA_LOG_INFO log_info -#define OTA_LOG_ERROR log_err -#define OTA_ASSERT LITE_ASSERT -#define OTA_SNPRINTF HAL_Snprintf - -#endif /* _OTA_IMPORT_H_ */ diff --git a/iotkit-embedded/src/sdk-impl/imports/iot_import_product.h b/iotkit-embedded/src/sdk-impl/imports/iot_import_product.h deleted file mode 100644 index e39ccdc..0000000 --- a/iotkit-embedded/src/sdk-impl/imports/iot_import_product.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef __IMPORT_PRODUCT_H__ -#define __IMPORT_PRODUCT_H__ - -#include "iot_import.h" - -#define _IN_ /* indicate that this is an input parameter */ -#define _OU_ /* indicate that this is an output parameter */ -#define IOT_TRUE (1) /* indicate boolean value true */ -#define IOT_FALSE (0) /* indicate boolean value false */ - -#define PID_STRLEN_MAX (64) -#define MID_STRLEN_MAX (64) -#define IOTX_URI_MAX_LEN (135) /* IoTx CoAP/HTTP uri & MQTT topic maximal length */ -#define PID_STR_MAXLEN (64) -#define MID_STR_MAXLEN (64) -#define PRODUCT_KEY_MAXLEN (20 + 1) -#define DEVICE_NAME_MAXLEN (32 + 1) -#define DEVICE_ID_MAXLEN (64 + 1) -#define DEVICE_SECRET_MAXLEN (64 + 1) -#define PRODUCT_SECRET_MAXLEN (64 + 1) -#define FIRMWARE_VERSION_MAXLEN (32 + 1) -#define HAL_CID_LEN (64 + 1) - -/** - * @brief 获取设备的`Partner ID`, 仅用于紧密合作伙伴 - * - * @param pid_str : 用来存放Partner ID字符串的数组 - * @return 写到pid_str[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetPartnerID(_OU_ char pid_str[PID_STR_MAXLEN]); - -/** - * @brief 获取设备的`Module ID`, 仅用于紧密合作伙伴 - * - * @param mid_str : 用来存放Module ID字符串的数组 - * @return 写到mid_str[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetModuleID(_OU_ char mid_str[MID_STR_MAXLEN]); - -/** - * @brief 设置设备的`ProductKey`, 用于标识设备的品类, 三元组之一 - * - * @param product_key : 用来存放ProductKey字符串的数组 - * @return 写到product_key[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_SetProductKey(_IN_ char* product_key); - -/** - * @brief 设置设备的`DeviceName`, 用于标识设备单品的名字, 三元组之一 - * - * @param device_name : 用来存放DeviceName字符串的数组 - * @return 写到device_name[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_SetDeviceName(_IN_ char* device_name); - -/** - * @brief 设置设备的`DeviceSecret`, 用于标识设备单品的密钥, 三元组之一 - * - * @param device_secret : 用来存放DeviceSecret字符串的数组 - * @return 写到device_secret[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_SetDeviceSecret(_IN_ char* device_secret); - -/** - * @brief 设置设备的`ProductSecret`, 用于标识设备单品的密钥, 三元组之一 - * - * @param product_secret : 用来存放ProductSecret字符串的数组 - * @return 写到product_secret[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_SetProductSecret(_IN_ char* product_secret); - -/** - * @brief 获取设备的`ProductKey`, 用于标识设备的品类, 三元组之一 - * - * @param product_key : 用来存放ProductKey字符串的数组 - * @return 写到product_key[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetProductKey(_OU_ char product_key[PRODUCT_KEY_LEN]); - -/** - * @brief 获取设备的`DeviceName`, 用于标识设备单品的名字, 三元组之一 - * - * @param device_name : 用来存放DeviceName字符串的数组 - * @return 写到device_name[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetDeviceName(_OU_ char device_name[DEVICE_NAME_LEN]); - -/** - * @brief 获取设备的`DeviceSecret`, 用于标识设备单品的密钥, 三元组之一 - * - * @param device_secret : 用来存放DeviceSecret字符串的数组 - * @return 写到device_secret[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetDeviceSecret(_OU_ char device_secret[DEVICE_SECRET_LEN]); - -/** - * @brief 获取设备的`ProductSecret`, 用于标识设备单品的密钥, 三元组之一 - * - * @param product_secret : 用来存放ProductSecret字符串的数组 - * @return 写到product_secret[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetProductSecret(_OU_ char product_secret[DEVICE_SECRET_LEN]); - -/** - * @brief 获取设备的`DeviceID`, 用于标识设备单品的ID - * - * @param device_id : 用来存放DeviceID字符串的数组 - * @return 写到device_id[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetDeviceID(_OU_ char device_id[DEVICE_ID_LEN]); - -/** - * @brief 获取设备的固件版本字符串 - * - * @param version : 用来存放版本字符串的数组 - * @return 写到version[]数组中的字符长度, 单位是字节(Byte) - */ -int HAL_GetFirmwareVesion(_OU_ char version[FIRMWARE_VERSION_MAXLEN]); - -/** - * @brief 获取唯一的芯片ID字符串 - * - * @param cid_str : 存放芯片ID字符串的缓冲区数组 - * @return 指向缓冲区数组的起始地址 - */ -char *HAL_GetChipID(_OU_ char cid_str[HAL_CID_LEN]); - -/** - * @brief 获取ID2 - * - * @param id2_str : 存放ID2字符串的缓冲区数组 - * @return 写到id2_str[]数组中的字符长度,单位是字节(Byte) - */ -#ifdef MQTT_ID2_AUTH -int HAL_GetID2(_OU_ char* id2_str); -#endif /**< MQTT_ID2_AUTH*/ - -/** - * @brief 开始固件写入 - * - * @param NULL - * @return 成功或失败 - */ -void HAL_Firmware_Persistence_Start(void); - - -/** - * @brief 写入固件 - * - * @param buffer : 写入内容 - * @param length : 写入内容长度 - * @return 实际写入长度 - */ -int HAL_Firmware_Persistence_Write(_IN_ char *buffer, _IN_ uint32_t length); - - -/** - * @brief 结束固件写入 - * - * @param NULL - * @return 成功或失败 - */ -int HAL_Firmware_Persistence_Stop(void); - -#endif /* __IMPORT_PRODUCT_H__ */ diff --git a/iotkit-embedded/src/sdk-impl/iot_export.h b/iotkit-embedded/src/sdk-impl/iot_export.h deleted file mode 100644 index 009df08..0000000 --- a/iotkit-embedded/src/sdk-impl/iot_export.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef __IOT_EXPORT_H__ -#define __IOT_EXPORT_H__ -#if defined(__cplusplus) -extern "C" { -#endif - -#include - -typedef enum _IOT_LogLevel { - IOT_LOG_EMERG = 0, - IOT_LOG_CRIT, - IOT_LOG_ERROR, - IOT_LOG_WARNING, - IOT_LOG_INFO, - IOT_LOG_DEBUG, -} IOT_LogLevel; - -/* From device.h */ -#define PRODUCT_KEY_LEN (20) -#define DEVICE_NAME_LEN (32) -#define DEVICE_ID_LEN (64) -#define DEVICE_SECRET_LEN (64) -#define PRODUCT_SECRET_LEN (64) - -#define MODULE_VENDOR_ID (32) /* Partner ID */ - -#define HOST_ADDRESS_LEN (128) -#define HOST_PORT_LEN (8) -#define CLIENT_ID_LEN (256) -#define USER_NAME_LEN (512) /* Extend length for ID2 */ -#define PASSWORD_LEN (256) /* Extend length for ID2 */ -#define AESKEY_STR_LEN (32) -#define AESKEY_HEX_LEN (128/8) - -typedef struct { - char product_key[PRODUCT_KEY_LEN + 1]; - char device_name[DEVICE_NAME_LEN + 1]; - char device_id[DEVICE_ID_LEN + 1]; - char device_secret[DEVICE_SECRET_LEN + 1]; - char module_vendor_id[MODULE_VENDOR_ID + 1]; -} iotx_device_info_t, *iotx_device_info_pt; - -typedef struct { - uint16_t port; - char host_name[HOST_ADDRESS_LEN + 1]; - char client_id[CLIENT_ID_LEN + 1]; - char username[USER_NAME_LEN + 1]; - char password[PASSWORD_LEN + 1]; - const char *pub_key; -#ifdef MQTT_ID2_AUTH - char aeskey_str[AESKEY_STR_LEN]; - uint8_t aeskey_hex[AESKEY_HEX_LEN]; -#endif -} iotx_conn_info_t, *iotx_conn_info_pt; -/* From device.h */ - -/** @defgroup group_api api - * @{ - */ - -/** @defgroup group_api_log log - * @{ - */ - -/** - * @brief Began to print log information. - * - * @param [in] ident: module name. - * - * @return None. - * @see None. - */ -void IOT_OpenLog(const char *ident); - -/** - * @brief Stop print log information. - * - * @return None. - * @see None. - */ -void IOT_CloseLog(void); - -/** - * @brief Set the print level. - * - * @param [in] level: @n level from 1 to 5, the greater the number, the more detailed the printing. - * - * @return None. - * @see None. - */ -void IOT_SetLogLevel(IOT_LogLevel level); - -/** - * @brief Print the memory usage statistics. - * - * @param [in] level: @n level from 1 to 5, the greater the number, the more detailed the printing. - * - * @return None. - * @see None. - */ -void IOT_DumpMemoryStats(IOT_LogLevel level); - -/** @} */ /* end of api_log */ - -/** @defgroup group_api_conninfo conninfo - * @{ - */ - - -/** - * @brief Based on the 'product_key' + 'device_name' + 'device_secret' produce an MQTT connection username and password. - * - * @param [in] product_key: @n Apply for 'product_key' in the AliYun Console. - * @param [in] device_name: @n Apply for 'device_name' in the AliYun Console. - * @param [in] device_secret: @n Apply for 'device_secret' in the AliYun Console. - * @param [out] info_ptr: @n return MQTT connection parameter. - * - * @retval -1 : Fail. - * @retval 0 : Success. - * @see None. - */ -int IOT_SetupConnInfo(const char *product_key, - const char *device_name, - const char *device_secret, - void **info_ptr); -/** - * @brief Based on the product_key + device_name + device_secret produce an MQTT connection username and password by ID2_AUTH. - * - * @param [in] product_key: @n Apply for 'product_key' in the AliYun Console. - * @param [in] device_name: @n Apply for 'device_name' in the AliYun Console. - * @param [in] device_secret: @n Apply for 'device_secret' in the AliYun Console. - * @param [out] info_ptr: @n return MQTT connection parameter. - * - * @retval -1 : Fail. - * @retval 0 : Success. - * @see None. - */ - -int IOT_SetupConnInfoSecure(const char *product_key, - const char *device_name, - const char *device_secret, - void **info_ptr); -/** @} */ /* end of api_conninfo */ - -/** @} */ /* end of api */ - -#include "exports/iot_export_errno.h" -#include "exports/iot_export_mqtt.h" -#include "exports/iot_export_shadow.h" -#include "exports/iot_export_coap.h" -#include "exports/iot_export_ota.h" -#include "exports/iot_export_http.h" -#ifdef SUBDEVICE_ENABLED -#include "exports/iot_export_subdev.h" -#endif /* SUBDEVICE_ENABLED */ -#ifdef CLOUD_CONN_ENABLED -#include "exports/iot_export_cloud_connection.h" -#endif /* CLOUD_CONN_ENABLED */ -#ifdef CMP_ENABLED -#include "exports/iot_export_cmp.h" -#endif /* CMP_ENABLED */ -#ifdef DM_ENABLED -#include "exports/iot_export_dm.h" -#endif /* DM_ENABLED */ -//#ifdef SERVICE_OTA_ENABLED -#include "exports/iot_export_fota.h" -//#endif /* SERVICE_OTA_ENABLED */ - - -#if defined(__cplusplus) -} -#endif -#endif /* __IOT_EXPORT_H__ */ diff --git a/iotkit-embedded/src/sdk-impl/iot_import.h b/iotkit-embedded/src/sdk-impl/iot_import.h deleted file mode 100644 index 1252ff6..0000000 --- a/iotkit-embedded/src/sdk-impl/iot_import.h +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef __IOT_IMPORT_H__ -#define __IOT_IMPORT_H__ -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include -#include -#include - -#include "iot_export.h" -#include "imports/iot_import_config.h" -#include "imports/iot_import_product.h" - -/** @defgroup group_platform platform - * @{ - */ - -#ifdef SIM7000C_DAM -#include "qapi_ali_iot.h" -#else - -#include "itls.h" -/*********************************** mutex interface ***********************************/ - -/** @defgroup group_platform_mutex mutex - * @{ - */ - -/** - * @brief Create a mutex. - * - * @retval NULL : Initialize mutex failed. - * @retval NOT_NULL : The mutex handle. - * @see None. - * @note None. - */ -void *HAL_MutexCreate(void); - -/** - * @brief Destroy the specified mutex object, it will release related resource. - * - * @param [in] mutex @n The specified mutex. - * @return None. - * @see None. - * @note None. - */ -void HAL_MutexDestroy(_IN_ void *mutex); - - - -/** - * @brief Waits until the specified mutex is in the signaled state. - * - * @param [in] mutex @n the specified mutex. - * @return None. - * @see None. - * @note None. - */ -void HAL_MutexLock(_IN_ void *mutex); - - - -/** - * @brief Releases ownership of the specified mutex object.. - * - * @param [in] mutex @n the specified mutex. - * @return None. - * @see None. - * @note None. - */ -void HAL_MutexUnlock(_IN_ void *mutex); - - -/** @} */ /* end of platform_mutex */ - - -/** @defgroup group_platform_memory_manage memory - * @{ - */ - -/** - * @brief Allocates a block of size bytes of memory, returning a pointer to the beginning of the block. - * - * @param [in] size @n specify block size in bytes. - * @return A pointer to the beginning of the block. - * @see None. - * @note Block value is indeterminate. - */ -void *HAL_Malloc(_IN_ uint32_t size); - - -/** - * @brief Deallocate memory block - * - * @param[in] ptr @n Pointer to a memory block previously allocated with platform_malloc. - * @return None. - * @see None. - * @note None. - */ -void HAL_Free(_IN_ void *ptr); - - -/** @} */ /* end of platform_memory_manage */ - -/** @defgroup group_platform_other other - * @{ - */ - -/** - * @brief Retrieves the number of milliseconds that have elapsed since the system was boot. - * - * @return the number of milliseconds. - * @see None. - * @note None. - */ -uint64_t HAL_UptimeMs(void); - - -/** - * @brief Sleep thread itself. - * - * @param [in] ms @n the time interval for which execution is to be suspended, in milliseconds. - * @return None. - * @see None. - * @note None. - */ -void HAL_SleepMs(_IN_ uint32_t ms); - -/** - * @brief Set seed for a sequence of pseudo-random integers, which will be returned by HAL_Random() - * - * @param [in] seed @n A start point for the random number sequence - * @return None. - * @see None. - * @note None. - */ -void HAL_Srandom(_IN_ uint32_t seed); - -/** - * @brief Get a random integer - * - * @param [in] region @n Range of generated random numbers - * @return Random number - * @see None. - * @note None. - */ -uint32_t HAL_Random(_IN_ uint32_t region); - -/** - * @brief Writes formatted data to stream. - * - * @param [in] fmt: @n String that contains the text to be written, it can optionally contain embedded format specifiers - that specifies how subsequent arguments are converted for output. - * @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. - * @return None. - * @see None. - * @note None. - */ -void HAL_Printf(_IN_ const char *fmt, ...); - -/** - * @brief Writes formatted data to string. - * - * @param [out] str: @n String that holds written text. - * @param [in] len: @n Maximum length of character will be written - * @param [in] fmt: @n Format that contains the text to be written, it can optionally contain embedded format specifiers - that specifies how subsequent arguments are converted for output. - * @param [in] ...: @n the variable argument list, for formatted and inserted in the resulting string replacing their respective specifiers. - * @return bytes of character successfully written into string. - * @see None. - * @note None. - */ -int HAL_Snprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, ...); - -/** - * @brief Writes formatted data to string. - * - * @param [out] str: @n String that holds written text. - * @param [in] len: @n Maximum length of character will be written. - * @param [in] fmt: @n Format that contains the text to be written. - * @param [in] ap: @n the variable argument list. - * @return bytes of character successfully format into string. - * @see None. - * @note None. - */ -int HAL_Vsnprintf(_OU_ char *str, _IN_ const int len, _IN_ const char *fmt, _IN_ va_list ap); - -/** - * @brief Get vendor ID of hardware module. - * - * @param [out] pid_str: @n Get vendor ID of hardware module form HAL_GetParternID - * @return the strlen of pid_str[] successfully written into. - */ -int HAL_GetPartnerID(_OU_ char pid_str[PID_STRLEN_MAX]); - -/** - * @brief Get Module ID of hardware module. - * - * @param [out] mid_str: @n Get Module ID of hardware module form HAL_GetModuleID - * @return the strlen of mid_str[] successfully written into. - */ -int HAL_GetModuleID(_OU_ char mid_str[MID_STRLEN_MAX]); - -/** @} */ /* end of group_platform_other */ - -/** @defgroup group_platform_network network - * @{ - */ - -/** - * @brief Establish a TCP connection. - * - * @param [in] host: @n Specify the hostname(IP) of the TCP server - * @param [in] port: @n Specify the TCP port of TCP server - * - * @return The handle of TCP connection. - @retval 0 : Fail. - @retval > 0 : Success, the value is handle of this TCP connection. - */ -uintptr_t HAL_TCP_Establish(_IN_ const char *host, _IN_ uint16_t port); - - -/** - * @brief Destroy the specific TCP connection. - * - * @param [in] fd: @n Specify the TCP connection by handle. - * - * @return The result of destroy TCP connection. - * @retval < 0 : Fail. - * @retval 0 : Success. - */ -int32_t HAL_TCP_Destroy(_IN_ uintptr_t fd); - - -/** - * @brief Write data into the specific TCP connection. - * The API will return immediately if 'len' be written into the specific TCP connection. - * - * @param [in] fd @n A descriptor identifying a connection. - * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. - * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * - * @retval < 0 : TCP connection error occur.. - * @retval 0 : No any data be write into the TCP connection in 'timeout_ms' timeout period. - * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. - - * @see None. - */ -int32_t HAL_TCP_Write(_IN_ uintptr_t fd, _IN_ const char *buf, _IN_ uint32_t len, _IN_ uint32_t timeout_ms); - - -/** - * @brief Read data from the specific TCP connection with timeout parameter. - * The API will return immediately if 'len' be received from the specific TCP connection. - * - * @param [in] fd @n A descriptor identifying a TCP connection. - * @param [out] buf @n A pointer to a buffer to receive incoming data. - * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * - * @retval -2 : TCP connection error occur. - * @retval -1 : TCP connection be closed by remote server. - * @retval 0 : No any data be received in 'timeout_ms' timeout period. - * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. - - * @see None. - */ -int32_t HAL_TCP_Read(_IN_ uintptr_t fd, _OU_ char *buf, _OU_ uint32_t len, _IN_ uint32_t timeout_ms); - -/** - * @brief Establish a SSL connection. - * - * @param [in] host: @n Specify the hostname(IP) of the SSL server - * @param [in] port: @n Specify the SSL port of SSL server - * @param [in] ca_crt @n Specify the root certificate which is PEM format. - * @param [in] ca_crt_len @n Length of root certificate, in bytes. - * @return SSL handle. - * @see None. - * @note None. - */ -uintptr_t HAL_SSL_Establish( - _IN_ const char *host, - _IN_ uint16_t port, - _IN_ const char *ca_crt, - _IN_ size_t ca_crt_len); - - -/** - * @brief Destroy the specific SSL connection. - * - * @param[in] handle: @n Handle of the specific connection. - * - * @return The result of destroy ssl - * - * @retval < 0 : Fail. - * @retval 0 : Success. - */ -int32_t HAL_SSL_Destroy(_IN_ uintptr_t handle); - - -/** - * @brief Write data into the specific SSL connection. - * The API will return immediately if 'len' be written into the specific SSL connection. - * - * @param [in] handle @n A descriptor identifying a connection. - * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. - * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * @retval < 0 : SSL connection error occur.. - * @retval 0 : No any data be write into the SSL connection in 'timeout_ms' timeout period. - * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. - * @see None. - */ -int32_t HAL_SSL_Write(_IN_ uintptr_t handle, _IN_ const char *buf, _IN_ int len, _IN_ int timeout_ms); - - -/** - * @brief Read data from the specific SSL connection with timeout parameter. - * The API will return immediately if 'len' be received from the specific SSL connection. - * - * @param [in] handle @n A descriptor identifying a SSL connection. - * @param [out] buf @n A pointer to a buffer to receive incoming data. - * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * - * @retval -2 : SSL connection error occur. - * @retval -1 : SSL connection be closed by remote server. - * @retval 0 : No any data be received in 'timeout_ms' timeout period. - * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. - * @see None. - */ -int32_t HAL_SSL_Read(_IN_ uintptr_t handle, _OU_ char *buf, _OU_ int len, _IN_ int timeout_ms); - -/** - * @brief Establish a UDP connection. - * - * @param [in] host: @n Specify the hostname(IP) of the UDP server - * @param [in] port: @n Specify the UDP port of UDP server - * - * @retval < 0 : Fail. - * @retval >= 0 : Success, the value is handle of this UDP connection. - * @see None. - */ -void *HAL_UDP_create(_IN_ char *host, _IN_ unsigned short port); - -/** - * @brief Destroy the specific UDP connection. - * - * @param [in] p_socket: @n Specify the UDP connection by handle. - * @return None. - * @see None . - */ -void HAL_UDP_close(_IN_ void *p_socket); - -/** - * @brief Write data into the specific UDP connection. - * - * @param [in] p_socket @n A descriptor identifying a connection. - * @param [in] p_data @n A pointer to a buffer containing the data to be transmitted. - * @param [in] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. - - * @retval < 0 : UDP connection error occur. - * @retval [0,datalen ] : The number of bytes sent. - * @see None. - */ -int HAL_UDP_write( - _IN_ void *p_socket, - _IN_ const unsigned char *p_data, - _IN_ unsigned int datalen); - -/** - * @brief Read data from the specific UDP connection by blocked - * - * @param [in] p_socket @n A descriptor identifying a UDP connection. - * @param [in] p_data @n A pointer to a buffer to receive incoming data. - * @param [out] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. - * @return - * - * @retval < 0 : UDP connect error occur. - * @retval = 0 : End of file. - * @retval > 0 : The number of byte read. - * @see None. - */ -int HAL_UDP_read( - _IN_ void *p_socket, - _OU_ unsigned char *p_data, - _OU_ unsigned int datalen); - -/** - * @brief Read data from the specific UDP connection with timeout parameter. - * The API will return immediately if 'datalen' be received from the specific UDP connection. - * - * @param [in] p_socket @n A descriptor identifying a UDP connection. - * @param [out] p_data @n A pointer to a buffer to receive incoming data. - * @param [out] datalen @n The length, in bytes, of the data pointed to by the 'p_data' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block timeout_ms millisecond maximumly. - * - * @retval -4 : UDP connect error occur. - * @retval -3 : The call was interrupted by a signal before any data was read. - * @retval -2 : No any data be received in 'timeout_ms' timeout period. - * @retval -1 : Invalid parameter. - * @retval 0 : End of file. - * @retval (0,datalen] : The number of byte read. - * @see None. - */ -int HAL_UDP_readTimeout( - _IN_ void *p_socket, - _OU_ unsigned char *p_data, - _OU_ unsigned int datalen, - _IN_ unsigned int timeout_ms); - -/** @} */ /* end of platform_network */ -/** @} */ /* end of platform */ - -#endif /* SIM7000C_DAM */ - -#if defined(__cplusplus) -} -#endif -#endif /* __IOT_IMPORT_H__ */ diff --git a/iotkit-embedded/src/sdk-impl/itls.h b/iotkit-embedded/src/sdk-impl/itls.h deleted file mode 100644 index 60ac82c..0000000 --- a/iotkit-embedded/src/sdk-impl/itls.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2014-2018 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef __ITLS_H__ -#define __ITLS_H__ - -#if defined(__cplusplus) -extern "C" { -#endif - -#include -#include -#include -#include -#include "iot_import.h" - -/** - * @brief Establish a iTLS connection. - * - * @param [in] host: @n Specify the hostname(IP) of the iTLS server - * @param [in] port: @n Specify the iTLS port of iTLS server - * @param [in] product_key @n Specify the product key. - * @return iTLS handle. - * @see None. - * @note None. - */ -uintptr_t HAL_iTLS_Establish( - _IN_ const char *host, - _IN_ uint16_t port, - _IN_ const char *product_key); - - -/** - * @brief Destroy the specific iTLS connection. - * - * @param[in] handle: @n Handle of the specific connection. - * - * @return The result of destroy iTLS - * - * @retval < 0 : Fail. - * @retval 0 : Success. - */ -int32_t HAL_iTLS_Destroy(_IN_ uintptr_t handle); - - -/** - * @brief Write data into the specific iTLS connection. - * The API will return immediately if 'len' be written into the specific iTLS connection. - * - * @param [in] handle @n A descriptor identifying a connection. - * @param [in] buf @n A pointer to a buffer containing the data to be transmitted. - * @param [in] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * @retval < 0 : iTLS connection error occur.. - * @retval 0 : No any data be write into the iTLS connection in 'timeout_ms' timeout period. - * @retval (0, len] : The total number of bytes be written in 'timeout_ms' timeout period. - * @see None. - */ -int32_t HAL_iTLS_Write(_IN_ uintptr_t handle, _IN_ const char *buf, _IN_ int len, _IN_ int timeout_ms); - - -/** - * @brief Read data from the specific iTLS connection with timeout parameter. - * The API will return immediately if 'len' be received from the specific SSL connection. - * - * @param [in] handle @n A descriptor identifying a iTLS connection. - * @param [out] buf @n A pointer to a buffer to receive incoming data. - * @param [out] len @n The length, in bytes, of the data pointed to by the 'buf' parameter. - * @param [in] timeout_ms @n Specify the timeout value in millisecond. In other words, the API block 'timeout_ms' millisecond maximumly. - * - * @retval -2 : iTLS connection error occur. - * @retval -1 : iTLS connection be closed by remote server. - * @retval 0 : No any data be received in 'timeout_ms' timeout period. - * @retval (0, len] : The total number of bytes be received in 'timeout_ms' timeout period. - * @see None. - */ -int32_t HAL_iTLS_Read(_IN_ uintptr_t handle, _OU_ char *buf, _OU_ int len, _IN_ int timeout_ms); - -#if defined(__cplusplus) -} -#endif - -#endif /* __ITLS_H__ */ - - diff --git a/iotkit-embedded/src/sdk-impl/lite-system.h b/iotkit-embedded/src/sdk-impl/lite-system.h deleted file mode 100644 index a0be1eb..0000000 --- a/iotkit-embedded/src/sdk-impl/lite-system.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _IOTX_AUTH_H_ -#define _IOTX_AUTH_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -#include "iot_import.h" -#include "iot_export.h" - -#define MQTT_SDK_VERSION "2.0" - -int iotx_guider_authenticate(void); -#ifdef MQTT_ID2_AUTH -/* func name: iotx_guider_id2_authenticate - * description: used for id2 authentication - * intput : - * output : - * return : int - * 0 success - * -1 error - */ -int iotx_guider_id2_authenticate(void); -#endif - -int iotx_device_info_init(void); - -int iotx_device_info_set( - const char *product_key, - const char *device_name, - const char *device_secret); - -iotx_device_info_pt iotx_device_info_get(void); -iotx_conn_info_pt iotx_conn_info_get(void); - - -#include - - -#define MIDREPORT_PAYLOAD_LEN (62 + PID_STRLEN_MAX + MID_STRLEN_MAX + 32 +1) -#define MIDREPORT_REQID_LEN (PRODUCT_KEY_LEN + DEVICE_NAME_LEN + 6) - -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); - - -const char *iotx_ca_get(void); - -#if defined(__cplusplus) -} -#endif -#endif diff --git a/iotkit-embedded/src/sdk-impl/sdk-impl_internal.h b/iotkit-embedded/src/sdk-impl/sdk-impl_internal.h deleted file mode 100644 index 6df38be..0000000 --- a/iotkit-embedded/src/sdk-impl/sdk-impl_internal.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef __SDK_IMPL_INTERNAL__ -#define __SDK_IMPL_INTERNAL__ -#if defined(__cplusplus) -extern "C" { -#endif - -#include "iot_import.h" -#include "iot_export.h" - -#include "lite-log.h" -#include "lite-utils.h" -#include "lite-system.h" - -#define POINTER_SANITY_CHECK(ptr, err) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, ptr); \ - return (err); \ - } \ - } while(0) - -#define STRING_PTR_SANITY_CHECK(ptr, err) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, (ptr)); \ - return (err); \ - } \ - if (0 == strlen((ptr))) { \ - log_err("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return (err); \ - } \ - } while(0) - -#if defined(__cplusplus) -} -#endif -#endif /* __SDK_IMPL_INTERNAL__ */ diff --git a/iotkit-embedded/src/shadow/CMakeLists.txt b/iotkit-embedded/src/shadow/CMakeLists.txt deleted file mode 100644 index 37f87d1..0000000 --- a/iotkit-embedded/src/shadow/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(iot_shadow OBJECT ${C_SOURCES}) diff --git a/iotkit-embedded/src/shadow/iot.mk b/iotkit-embedded/src/shadow/iot.mk deleted file mode 100644 index 0420f36..0000000 --- a/iotkit-embedded/src/shadow/iot.mk +++ /dev/null @@ -1,2 +0,0 @@ -LIBA_TARGET := libiot_shadow.a -HDR_REFS := src diff --git a/iotkit-embedded/src/shadow/shadow.c b/iotkit-embedded/src/shadow/shadow.c deleted file mode 100644 index 8fd06c4..0000000 --- a/iotkit-embedded/src/shadow/shadow.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "shadow.h" -#include "shadow_common.h" -#include "shadow_update.h" -#include "shadow_delta.h" - - -/* check return code */ -#define CHECK_RETURN_CODE(ret_code) \ - do{ \ - if (ret_code < 0) { \ - return ret_code; \ - } \ - }while(0); - - -/* check return code of snprintf */ -#define CHECK_SNPRINTF_RET(ret_code, buf_len) \ - do{ \ - if ((ret_code) < 0) { \ - return FAIL_RETURN; \ - } else if ((ret_code) >= (buf_len)) { \ - return ERROR_NO_ENOUGH_MEM; \ - } \ - }while(0); - - -static void iotx_ds_handle_expire(iotx_shadow_pt pshadow) -{ - iotx_ds_update_wait_ack_list_handle_expire(pshadow); -} - - -/* This function will be called back when message published to topic(/shadow/get/) arrives. */ -static void iotx_shadow_callback_get(iotx_shadow_pt pshadow, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - const char *pname; - - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - - log_debug("topic=%.*s", topic_info->topic_len, topic_info->ptopic); - log_debug("data of topic=%.*s", topic_info->payload_len, (char *)topic_info->payload); - - /* update time if there is 'timestamp' key in JSON string */ - pname = LITE_json_value_of((char *)"timestamp", (char *)topic_info->payload); - if (NULL != pname) { - iotx_ds_common_update_time(pshadow, atoi(pname)); - } - LITE_free(pname); - - /* update 'version' if there is 'version' key in JSON string */ - pname = LITE_json_value_of((char *)"version", (char *)topic_info->payload); - if (NULL != pname) { - iotx_ds_common_update_version(pshadow, atoi(pname)); - LITE_free(pname); - } - - /* get 'method' */ - pname = LITE_json_value_of((char *)"method", (char *)topic_info->payload); - /* log_debug("pname(%d) = %s", (int)strlen(pname), pname); */ - if (NULL == pname) { - log_err("Invalid JSON document: not 'method' key"); - } else if ((strlen("control") == strlen(pname)) && !strcmp(pname, "control")) { - /* call delta handle function */ - log_debug("receive 'control' method"); - - iotx_shadow_delta_entry( - pshadow, - topic_info->payload, - topic_info->payload_len); - LITE_free(pname); - } else if ((strlen("reply") == strlen(pname)) && !strcmp(pname, "reply")) { - /* call update ACK handle function. */ - log_debug("receive 'reply' method"); - iotx_ds_update_wait_ack_list_handle_response( - pshadow, - topic_info->payload, - topic_info->payload_len); - LITE_free(pname); - } else { - log_err("Invalid 'method' key"); - LITE_free(pname); - } - - log_debug("End of method handle"); -} - -static int iotx_shadow_subcribe_get(iotx_shadow_pt pshadow) -{ - if (NULL == pshadow->inner_data.ptopic_get) { - pshadow->inner_data.ptopic_get = iotx_ds_common_generate_topic_name(pshadow, "get"); - if (NULL == pshadow->inner_data.ptopic_get) { - return FAIL_RETURN; - } - } - - return IOT_MQTT_Subscribe(pshadow->mqtt, - pshadow->inner_data.ptopic_get, - IOTX_MQTT_QOS1, - (iotx_mqtt_event_handle_func_fpt)iotx_shadow_callback_get, - pshadow); -} - - -iotx_err_t IOT_Shadow_PushFormat_Init(void *pshadow, - format_data_pt pformat, - char *buf, - uint16_t size) -{ - return iotx_ds_common_format_init((iotx_shadow_pt)pshadow, pformat, buf, size, "update", "\"state\":{\"reported\":{"); -} - - -iotx_err_t IOT_Shadow_PushFormat_Add(void *pshadow, - format_data_pt pformat, - iotx_shadow_attr_pt pattr) -{ - return iotx_ds_common_format_add((iotx_shadow_pt)pshadow, pformat, pattr->pattr_name, pattr->pattr_data, - pattr->attr_type); -} - - -iotx_err_t IOT_Shadow_PushFormat_Finalize(void *pshadow, format_data_pt pformat) -{ - return iotx_ds_common_format_finalize((iotx_shadow_pt)pshadow, pformat, "}}"); -} - - -int IOT_Shadow_Push_Async( - void *handle, - char *data, - size_t data_len, - uint16_t timeout_s, - iotx_push_cb_fpt cb_fpt, - void *pcontext) -{ - int rc = SUCCESS_RETURN; - iotx_update_ack_wait_list_pt pelement; - const char *ptoken; - iotx_shadow_pt pshadow = (iotx_shadow_pt)handle; - - if ((NULL == handle) || (NULL == data)) { - return NULL_VALUE_ERROR; - } - - if (!IOT_MQTT_CheckStateNormal(pshadow->mqtt)) { - log_err("The MQTT connection must be established before UPDATE data."); - return ERROR_SHADOW_INVALID_STATE; - } - - /*Add to callback list */ - - log_debug("data(%d) = %s", (int)data_len, data); - ptoken = LITE_json_value_of((char *)"clientToken", (char *)data); - - LITE_ASSERT(NULL != ptoken); - - pelement = iotx_shadow_update_wait_ack_list_add(pshadow, ptoken, strlen(ptoken), cb_fpt, pcontext, timeout_s); - if (NULL == pelement) { - LITE_free(ptoken); - return ERROR_SHADOW_WAIT_LIST_OVERFLOW; - } - LITE_free(ptoken); - - if ((rc = iotx_ds_common_publish2update(pshadow, data, data_len)) < 0) { - iotx_shadow_update_wait_ack_list_remove(pshadow, pelement); - return rc; - } - - return SUCCESS_RETURN; -} - - - -static void iotx_update_ack_cb( - void *pcontext, - int ack_code, - const char *ack_msg, /* NOTE: NOT a string. */ - uint32_t ack_msg_len) -{ - log_debug("ack_code=%d", ack_code); - - if (NULL != ack_msg) { - log_debug("ack_msg=%.*s", ack_msg_len, ack_msg); - } else { - log_debug("ack_msg is NULL"); - } - - *((int *)pcontext) = ack_code; -} - - -iotx_err_t IOT_Shadow_Push( - void *handle, - char *data, - uint32_t data_len, - uint16_t timeout_s) -{ - iotx_shadow_ack_code_t ack_update = IOTX_SHADOW_ACK_NONE; - iotx_shadow_pt pshadow = (iotx_shadow_pt)handle; - - if ((NULL == pshadow) || (NULL == data)) { - return NULL_VALUE_ERROR; - } - - if (!IOT_MQTT_CheckStateNormal(pshadow->mqtt)) { - log_err("The MQTT connection must be established before UPDATE data."); - return ERROR_SHADOW_INVALID_STATE; - } - - /* update asynchronously */ - IOT_Shadow_Push_Async(pshadow, data, data_len, timeout_s, iotx_update_ack_cb, &ack_update); - - /* wait ACK */ - while (IOTX_SHADOW_ACK_NONE == ack_update) { - IOT_Shadow_Yield(pshadow, 200); - } - - if ((IOTX_SHADOW_ACK_SUCCESS == ack_update) - || (IOTX_SHADOW_ACK_ERR_SHADOW_DOCUMENT_IS_NULL == ack_update)) { - /* It is not the error that device shadow document is null */ - log_info("update success."); - return SUCCESS_RETURN; - } else if (IOTX_SHADOW_ACK_TIMEOUT == ack_update) { - log_info("update timeout."); - return ERROR_SHADOW_UPDATE_TIMEOUT; - } else { - log_info("update negative ack."); - return ERROR_SHADOW_UPDATE_NACK; - } -} - - -iotx_err_t IOT_Shadow_Pull(void *handle) -{ -#define SHADOW_SYNC_MSG_SIZE (256) - - iotx_err_t ret; - void *buf; - format_data_t format; - iotx_shadow_pt pshadow = (iotx_shadow_pt)handle; - - log_info("Device Shadow sync start."); - - buf = LITE_malloc(SHADOW_SYNC_MSG_SIZE); - if (NULL == buf) { - log_err("Device Shadow sync failed"); - return ERROR_NO_MEM; - } - - iotx_ds_common_format_init(pshadow, &format, buf, SHADOW_SYNC_MSG_SIZE, "get", NULL); - iotx_ds_common_format_finalize(pshadow, &format, NULL); - - ret = IOT_Shadow_Push(pshadow, format.buf, format.offset, 10); - if (SUCCESS_RETURN == ret) { - log_info("Device Shadow sync success."); - } else { - log_info("Device Shadow sync failed."); - } - - LITE_free(buf); - HAL_SleepMs(1000); - - return ret; - -#undef SHADOW_SYNC_MSG_SIZE -} - - -void iotx_ds_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - iotx_shadow_pt pshadow = (iotx_shadow_pt)pcontext; - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg; - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - log_info("subscribe success, packet-id=%u", (unsigned int)packet_id); - if (pshadow->inner_data.sync_status == packet_id) { - pshadow->inner_data.sync_status = 0; - } - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - log_info("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id); - if (pshadow->inner_data.sync_status == packet_id) { - pshadow->inner_data.sync_status = -1; - } - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - log_info("subscribe nack, packet-id=%u", (unsigned int)packet_id); - if (pshadow->inner_data.sync_status == packet_id) { - pshadow->inner_data.sync_status = -1; - } - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: - log_info("topic message arrived but without any related handle: topic=%.*s, topic_msg=%.*s", - topic_info->topic_len, - topic_info->ptopic, - topic_info->payload_len, - topic_info->payload); - break; - - default: - /* log_info("Should NOT arrive here."); */ - break; - } -} - -void *IOT_Shadow_Construct(iotx_shadow_para_pt pparams) -{ - int rc = 0; - iotx_shadow_pt pshadow = NULL; - - /* initialize shadow */ - if (NULL == (pshadow = LITE_malloc(sizeof(iotx_shadow_t)))) { - log_err("Not enough memory"); - return NULL; - } - memset(pshadow, 0x0, sizeof(iotx_shadow_t)); - - if (NULL == (pshadow->mutex = HAL_MutexCreate())) { - log_err("create mutex failed"); - goto do_exit; - } - - pparams->mqtt.handle_event.h_fp = iotx_ds_event_handle; - pparams->mqtt.handle_event.pcontext = pshadow; - - /* construct MQTT client */ -#ifndef MQTT_ID2_AUTH - if (NULL == (pshadow->mqtt = IOT_MQTT_Construct(&pparams->mqtt))) { -#else - if (NULL == (pshadow->mqtt = IOT_MQTT_ConstructSecure(&pparams->mqtt))) { -#endif /**< MQTT_ID2_AUTH*/ - log_err("construct MQTT failed"); - goto do_exit; - } - - rc = iotx_shadow_subcribe_get(pshadow); - if (rc < 0) { - log_err("subscribe 'get' topic fialed, rc=%d", rc); - goto do_exit; - } - - pshadow->inner_data.sync_status = rc; - - while (rc == pshadow->inner_data.sync_status) { - IOT_Shadow_Yield(pshadow, 100); - } - - if (0 == pshadow->inner_data.sync_status) { - log_info("Sync device data successfully"); - } else { - log_info("Sync device data failed"); - } - - - pshadow->inner_data.attr_list = list_new(); - if (NULL == pshadow->inner_data.attr_list) { - log_err("new list failed"); - goto do_exit; - } - - return pshadow; - -do_exit: - IOT_Shadow_Destroy(pshadow); - - return NULL; -} - - -void IOT_Shadow_Yield(void *handle, uint32_t timeout) -{ - iotx_shadow_pt pshadow = (iotx_shadow_pt)handle; - IOT_MQTT_Yield(pshadow->mqtt, timeout); - iotx_ds_handle_expire(pshadow); -} - - -iotx_err_t IOT_Shadow_Destroy(void *handle) -{ - iotx_shadow_pt pshadow = (iotx_shadow_pt) handle; - - if (NULL != pshadow->mqtt) { - if (NULL != pshadow->inner_data.ptopic_get) { - IOT_MQTT_Unsubscribe(pshadow->mqtt, pshadow->inner_data.ptopic_get); - } - - HAL_SleepMs(2000); - IOT_MQTT_Destroy(&pshadow->mqtt); - } - - if (NULL != pshadow->inner_data.ptopic_get) { - LITE_free(pshadow->inner_data.ptopic_get); - } - - if (NULL != pshadow->inner_data.ptopic_update) { - LITE_free(pshadow->inner_data.ptopic_update); - } - - if (NULL != pshadow->inner_data.attr_list) { - list_destroy(pshadow->inner_data.attr_list); - } - - if (NULL != pshadow->mutex) { - HAL_MutexDestroy(pshadow->mutex); - } - - LITE_free(handle); - - return SUCCESS_RETURN; -} - - -iotx_err_t IOT_Shadow_RegisterAttribute(void *handle, iotx_shadow_attr_pt pattr) -{ - /* check if already registered */ - if (iotx_ds_common_check_attr_existence((iotx_shadow_pt)handle, pattr)) { - return ERROR_SHADOW_ATTR_EXIST; - } - - if (SUCCESS_RETURN != iotx_ds_common_register_attr((iotx_shadow_pt)handle, pattr)) { - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - - -/* Remove attribute from Device Shadow in cloud by delete method. */ -iotx_err_t IOT_Shadow_DeleteAttribute(void *handle, iotx_shadow_attr_pt pattr) -{ -#define SHADOW_DELETE_MSG_SIZE (256) - - iotx_err_t ret; - void *buf; - format_data_t format; - iotx_shadow_pt pshadow = (iotx_shadow_pt) handle; - - if (!iotx_ds_common_check_attr_existence(pshadow, pattr)) { - return ERROR_SHADOW_ATTR_NO_EXIST; - } - - buf = LITE_malloc(SHADOW_DELETE_MSG_SIZE); - if (NULL == buf) { - return ERROR_NO_MEM; - } - - iotx_ds_common_format_init(pshadow, &format, buf, SHADOW_DELETE_MSG_SIZE, "delete", ",\"state\":{\"reported\":{"); - iotx_ds_common_format_add(pshadow, &format, pattr->pattr_name, NULL, IOTX_SHADOW_NULL); - iotx_ds_common_format_finalize(pshadow, &format, "}}"); - - ret = IOT_Shadow_Push(pshadow, format.buf, format.offset, 10); - if (SUCCESS_RETURN != ret) { - LITE_free(buf); - return ret; - } - - LITE_free(buf); - - return iotx_ds_common_remove_attr(pshadow, pattr); - -#undef SHADOW_DELETE_MSG_SIZE -} diff --git a/iotkit-embedded/src/shadow/shadow.h b/iotkit-embedded/src/shadow/shadow.h deleted file mode 100644 index 23ea161..0000000 --- a/iotkit-embedded/src/shadow/shadow.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _IOTX_SHADOW_H_ -#define _IOTX_SHADOW_H_ -#if defined(__cplusplus) -extern "C" { -#endif - -#include "iot_import.h" -#include "iot_export.h" - - -#endif /* _IOTX_SHADOW_H_ */ diff --git a/iotkit-embedded/src/shadow/shadow_common.c b/iotkit-embedded/src/shadow/shadow_common.c deleted file mode 100644 index f7732e5..0000000 --- a/iotkit-embedded/src/shadow/shadow_common.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include "iot_import.h" -#include "lite-log.h" -#include "lite-utils.h" -#include "utils_timer.h" -#include "utils_list.h" -#include "lite-system.h" - -#include "shadow.h" -#include "shadow_common.h" - -/* check return code */ -#define CHECK_RETURN_CODE(ret_code) \ - do{ \ - if (ret_code < 0) { \ - return ret_code; \ - } \ - }while(0); - - -/* check return code of HAL_Snprintf */ -#define CHECK_SNPRINTF_RET(ret_code, buf_len) \ - do{ \ - if ((ret_code) < 0) { \ - return FAIL_RETURN; \ - } else if ((ret_code) >= (buf_len)) { \ - return ERROR_NO_ENOUGH_MEM; \ - } \ - }while(0); - - -/* return handle of format data. */ -iotx_err_t iotx_ds_common_format_init(iotx_shadow_pt pshadow, - format_data_pt pformat, - char *buf, - uint16_t size, - const char *method, - const char *head_str) -{ - int ret; - uint32_t size_free_space; - memset(pformat, 0, sizeof(format_data_t)); - - pformat->buf = buf; - pformat->buf_size = size; - - if (NULL == method) { - return ERROR_SHADOW_NO_METHOD; - } - - size_free_space = pformat->buf_size; - - ret = HAL_Snprintf(pformat->buf, - size_free_space, - "{\"%s\":\"%s\"", - "method", - method); - - CHECK_SNPRINTF_RET(ret, size_free_space); - pformat->offset = ret; - - - /* copy the JOSN head */ - size_free_space = pformat->buf_size - pformat->offset; - if (NULL != head_str) { - ret = HAL_Snprintf(pformat->buf + pformat->offset, - size_free_space, - ",%s", - head_str); - CHECK_SNPRINTF_RET(ret, size_free_space); - pformat->offset += ret; - } - - pformat->flag_new = IOT_TRUE; - - return SUCCESS_RETURN; -} - - -iotx_err_t iotx_ds_common_format_add(iotx_shadow_pt pshadow, - format_data_pt pformat, - const char *name, - const void *pvalue, - iotx_shadow_attr_datatype_t datatype) -{ - int ret; - uint32_t size_free_space; - - if (pformat->flag_new) { - pformat->flag_new = IOT_FALSE; - } else { - /* Add comma char. */ - size_free_space = pformat->buf_size - pformat->offset; - if (size_free_space > 1) { /* there is enough space to accommodate ',' char. */ - *(pformat->buf + pformat->offset) = ','; - *(pformat->buf + pformat->offset + 1) = '\0'; - ++pformat->offset; - } else { - return FAIL_RETURN; - } - } - - size_free_space = pformat->buf_size - pformat->offset; - - /* add the string: "${pattr->pattr_name}":" */ - ret = HAL_Snprintf(pformat->buf + pformat->offset, - size_free_space, - "\"%s\":", - name); - - CHECK_SNPRINTF_RET(ret, size_free_space); - - pformat->offset += ret; - size_free_space = pformat->buf_size - pformat->offset; - - /* convert attribute data to JSON string, and add to buffer */ - ret = iotx_ds_common_convert_data2string(pformat->buf + pformat->offset, - size_free_space, - datatype, - pvalue); - if (ret < 0) { - return FAIL_RETURN; - } - - pformat->offset += ret; - - return SUCCESS_RETURN; -} - - -iotx_err_t iotx_ds_common_format_finalize(iotx_shadow_pt pshadow, format_data_pt pformat, const char *tail_str) -{ -#define UPDATE_JSON_STR_END ",\"clientToken\":\"%s-%d\",\"version\":%d}" - - int ret; - uint16_t size_free_space = pformat->buf_size - pformat->offset; - - if (NULL != tail_str) { - ret = HAL_Snprintf(pformat->buf + pformat->offset, size_free_space, "%s", tail_str); - CHECK_SNPRINTF_RET(ret, size_free_space); - pformat->offset += ret; - } - - size_free_space = pformat->buf_size - pformat->offset; - - ret = HAL_Snprintf(pformat->buf + pformat->offset, - size_free_space, - UPDATE_JSON_STR_END, - iotx_device_info_get()->device_id, - iotx_ds_common_get_tokennum(pshadow), - iotx_ds_common_get_version(pshadow)); - - CHECK_SNPRINTF_RET(ret, size_free_space); - pformat->offset += ret; - - return SUCCESS_RETURN; - -#undef UPDATE_JSON_STR_END -} - - -int iotx_ds_common_convert_data2string( - char *buf, - size_t buf_len, - iotx_shadow_attr_datatype_t type, - const void *pData) -{ - - int ret = -1; - - if ((NULL == buf) || (buf_len == 0) - || ((IOTX_SHADOW_NULL != type) && (NULL == pData))) { - return ERROR_NULL_VALUE; - } - - if (IOTX_SHADOW_INT32 == type) { - ret = HAL_Snprintf(buf, buf_len, "%" PRIi32, *(int32_t *)(pData)); - } else if (IOTX_SHADOW_STRING == type) { - ret = HAL_Snprintf(buf, buf_len, "\"%s\"", (char *)(pData)); - } else if (IOTX_SHADOW_NULL == type) { - ret = HAL_Snprintf(buf, buf_len, "%s", "\"null\""); - } else { - log_err("Error data type"); - ret = -1; - } - - if ((ret < 0) || (ret >= buf_len)) { - return -1; - } - - return ret; -} - - -iotx_err_t iotx_ds_common_convert_string2data( - const char *buf, - size_t buf_len, - iotx_shadow_attr_datatype_t type, - void *pdata) -{ - if ((NULL == buf) || (buf_len == 0) || (NULL == pdata)) { - return ERROR_NULL_VALUE; - } - - if (type == IOTX_SHADOW_INT32) { - if (0 == strcmp(pdata, "true")) { - *((int32_t *)pdata) = 1; - } else if (0 == strcmp(pdata, "false")) { - *((int32_t *)pdata) = 0; - } else if (0 == strcmp(pdata, "null")) { - *((int32_t *)pdata) = 0; - } else { - *((int32_t *)pdata) = atoi(buf); - } - } else if (type == IOTX_SHADOW_STRING) { - memcpy(pdata, buf, buf_len); - } else { - log_err("Error data type"); - return ERROR_SHADOW_UNDEF_TYPE; - } - - return SUCCESS_RETURN; -} - - -void iotx_ds_common_update_time(iotx_shadow_pt pshadow, uint32_t new_timestamp) -{ - HAL_MutexLock(pshadow->mutex); - pshadow->inner_data.time.base_system_time = utils_time_get_ms(); - pshadow->inner_data.time.epoch_time = new_timestamp; - HAL_MutexUnlock(pshadow->mutex); - - log_info("update system time"); -} - - -int iotx_ds_common_check_attr_existence( - iotx_shadow_pt pshadow, - iotx_shadow_attr_pt pattr) -{ - list_node_t *node; - - HAL_MutexLock(pshadow->mutex); - node = list_find(pshadow->inner_data.attr_list, pattr); - HAL_MutexUnlock(pshadow->mutex); - - return (NULL != node); -} - - -/* register attribute to list */ -iotx_err_t iotx_ds_common_register_attr( - iotx_shadow_pt pshadow, - iotx_shadow_attr_pt pattr) -{ - list_node_t *node = list_node_new(pattr); - if (NULL == node) { - return ERROR_NO_MEM; - } - - HAL_MutexLock(pshadow->mutex); - list_lpush(pshadow->inner_data.attr_list, node); - HAL_MutexUnlock(pshadow->mutex); - - return SUCCESS_RETURN; -} - - -/* remove attribute to list */ -iotx_err_t iotx_ds_common_remove_attr( - iotx_shadow_pt pshadow, - iotx_shadow_attr_pt pattr) -{ - iotx_err_t rc = SUCCESS_RETURN; - list_node_t *node; - - HAL_MutexLock(pshadow->mutex); - node = list_find(pshadow->inner_data.attr_list, pattr); - if (NULL == node) { - rc = ERROR_SHADOW_NO_ATTRIBUTE; - log_err("Try to remove a non-existent attribute."); - } else { - list_remove(pshadow->inner_data.attr_list, node); - } - HAL_MutexUnlock(pshadow->mutex); - - return rc; -} - - -void iotx_ds_common_update_version(iotx_shadow_pt pshadow, uint32_t version) -{ - HAL_MutexLock(pshadow->mutex); - - /* version number always grow up */ - if (version > pshadow->inner_data.version) { - pshadow->inner_data.version = version; - } - HAL_MutexUnlock(pshadow->mutex); - - log_info("update shadow version"); -} - - - -uint32_t iotx_ds_common_get_version(iotx_shadow_pt pshadow) -{ - uint32_t ver; - HAL_MutexLock(pshadow->mutex); - ++pshadow->inner_data.version; - ver = pshadow->inner_data.version; - ++pshadow->inner_data.version; - HAL_MutexUnlock(pshadow->mutex); - return ver; -} - - -uint32_t iotx_ds_common_get_tokennum(iotx_shadow_pt pshadow) -{ - uint32_t ver; - HAL_MutexLock(pshadow->mutex); - ++pshadow->inner_data.token_num; - ver = pshadow->inner_data.token_num; - ++pshadow->inner_data.token_num; - HAL_MutexUnlock(pshadow->mutex); - return ver; -} - - -char *iotx_ds_common_generate_topic_name(iotx_shadow_pt pshadow, const char *topic) -{ -#define SHADOW_TOPIC_FMT "/shadow/%s/%s/%s" -#define SHADOW_TOPIC_LEN (PRODUCT_KEY_LEN + DEVICE_NAME_LEN) - - int len, ret; - char *topic_full = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - len = SHADOW_TOPIC_LEN + sizeof(SHADOW_TOPIC_FMT); - - topic_full = LITE_malloc(len + 1); - if (NULL == topic_full) { - log_err("Not enough memory"); - return NULL; - } - - ret = HAL_Snprintf(topic_full, - len, - SHADOW_TOPIC_FMT, - topic, - pdevice_info->product_key, - pdevice_info->device_name); - if (ret < 0) { - LITE_free(topic_full); - return NULL; - } - - LITE_ASSERT(ret < len); - - return topic_full; -} - - -int iotx_ds_common_publish2update(iotx_shadow_pt pshadow, char *data, uint32_t data_len) -{ - iotx_mqtt_topic_info_t topic_msg; - - /* check if topic name have been generated or not */ - if (NULL == pshadow->inner_data.ptopic_update) { - /* Have NOT update topic name, generate it. */ - pshadow->inner_data.ptopic_update = iotx_ds_common_generate_topic_name(pshadow, "update"); - if (NULL == pshadow->inner_data.ptopic_update) { - return FAIL_RETURN; - } - } - - log_debug("publish msg: len=%d, str=%s", data_len, data); - - topic_msg.qos = IOTX_MQTT_QOS1; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)data; - topic_msg.payload_len = data_len; - topic_msg.packet_id = 0; - - return IOT_MQTT_Publish(pshadow->mqtt, pshadow->inner_data.ptopic_update, &topic_msg); -} diff --git a/iotkit-embedded/src/shadow/shadow_common.h b/iotkit-embedded/src/shadow/shadow_common.h deleted file mode 100644 index 762e4f3..0000000 --- a/iotkit-embedded/src/shadow/shadow_common.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef _SHADOW_IOTX_SHADOW_COMMON_H_ -#define _SHADOW_IOTX_SHADOW_COMMON_H_ - - -#include "iot_import.h" -#include "utils_timer.h" -#include "utils_list.h" -#include "shadow.h" -#include "shadow_config.h" - -typedef struct iotx_update_ack_wait_list_st { - int flag_busy; /* 0, free; 1, busy. */ - char token[IOTX_DS_TOKEN_LEN]; - iotx_push_cb_fpt callback; - void *pcontext; - iotx_time_t timer; -} iotx_update_ack_wait_list_t, *iotx_update_ack_wait_list_pt; - - -typedef struct iotx_inner_data_st { - uint32_t token_num; - uint32_t version; - iotx_shadow_time_t time; - iotx_update_ack_wait_list_t update_ack_wait_list[IOTX_DS_UPDATE_WAIT_ACK_LIST_NUM]; - list_t *attr_list; - char *ptopic_update; - char *ptopic_get; - int32_t sync_status; -} iotx_inner_data_t, *iotx_inner_data_pt;; - - -typedef struct iotx_shadow_st { - void *mqtt; - void *mutex; - iotx_inner_data_t inner_data; -} iotx_shadow_t, *iotx_shadow_pt; - -iotx_err_t iotx_ds_common_format_init(iotx_shadow_pt pshadow, - format_data_pt pformat, - char *buf, - uint16_t size, - const char *method, - const char *head_str); - -iotx_err_t iotx_ds_common_format_add(iotx_shadow_pt pshadow, - format_data_pt pformat, - const char *name, - const void *pvalue, - iotx_shadow_attr_datatype_t datatype); - -iotx_err_t iotx_ds_common_format_finalize(iotx_shadow_pt pshadow, format_data_pt pformat, const char *tail_str); - -void iotx_ds_common_update_time(iotx_shadow_pt pshadow, uint32_t new_timestamp); - -int iotx_ds_common_convert_data2string( - char *buf, - size_t buf_len, - iotx_shadow_attr_datatype_t type, - const void *pData); - -iotx_err_t iotx_ds_common_convert_string2data( - const char *buf, - size_t buf_len, - iotx_shadow_attr_datatype_t type, - void *pData); - -int iotx_ds_common_check_attr_existence(iotx_shadow_pt pshadow, const iotx_shadow_attr_pt pattr); - -iotx_err_t iotx_ds_common_register_attr( - iotx_shadow_pt pshadow, - iotx_shadow_attr_pt pattr); - -iotx_err_t iotx_ds_common_remove_attr( - iotx_shadow_pt pshadow, - iotx_shadow_attr_pt pattr); - -char *iotx_ds_common_generate_topic_name(iotx_shadow_pt pshadow, const char *topic); - -int iotx_ds_common_publish2update(iotx_shadow_pt pshadow, char *data, uint32_t data_len); - -void iotx_ds_common_update_version(iotx_shadow_pt pshadow, uint32_t version); - -uint32_t iotx_ds_common_get_version(iotx_shadow_pt pshadow); - -uint32_t iotx_ds_common_get_tokennum(iotx_shadow_pt pshadow); - -#endif /* _SHADOW_IOTX_SHADOW_COMMON_H_ */ diff --git a/iotkit-embedded/src/shadow/shadow_config.h b/iotkit-embedded/src/shadow/shadow_config.h deleted file mode 100644 index d76fa63..0000000 --- a/iotkit-embedded/src/shadow/shadow_config.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef _IOTX_SHADOW_CONFIG_H_ -#define _IOTX_SHADOW_CONFIG_H_ - - -#define IOTX_DS_TOKEN_LEN (128) /**< indicate the maximum length of shadow token in byte. */ - -#define IOTX_DS_UPDATE_WAIT_ACK_LIST_NUM (5) /**< indicate the maximum element of UPDATE ACK list. */ - -#endif /* _IOTX_SHADOW_CONFIG_H_ */ diff --git a/iotkit-embedded/src/shadow/shadow_delta.c b/iotkit-embedded/src/shadow/shadow_delta.c deleted file mode 100644 index 397ae62..0000000 --- a/iotkit-embedded/src/shadow/shadow_delta.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include "iot_import.h" - -#include "lite-log.h" -#include "lite-utils.h" -#include "utils_list.h" -#include "shadow_delta.h" - -static int iotx_shadow_delta_response(iotx_shadow_pt pshadow) -{ -#define IOTX_SHADOW_DELTA_RESPONSE_LEN (256) - - int rc; - void *buf; - format_data_t format; - - buf = LITE_malloc(IOTX_SHADOW_DELTA_RESPONSE_LEN); - if (NULL == buf) { - return ERROR_NO_MEM; - } - - iotx_ds_common_format_init(pshadow, &format, buf, IOTX_SHADOW_DELTA_RESPONSE_LEN, "update", - "\"state\":{\"desired\":\"null\""); - iotx_ds_common_format_finalize(pshadow, &format, "}"); - - rc = iotx_ds_common_publish2update(pshadow, format.buf, format.offset); - - LITE_free(buf); - - return (rc >= 0) ? SUCCESS_RETURN : rc; -} - - - -static uint32_t iotx_shadow_get_timestamp(const char *pmetadata_desired, - size_t len_metadata_desired, - const char *pname) -{ - const char *pdata; - - /* attribute be matched, and then get timestamp */ - - pdata = LITE_json_value_of((char *)pname, (char *)pmetadata_desired); - - if (NULL != pdata) { - pdata = LITE_json_value_of((char *)"timestamp", (char *)pdata); - if (NULL != pdata) { - return atoi(pdata); - } - } - - log_err("NOT timestamp in JSON doc"); - return 0; -} - - -static iotx_err_t iotx_shadow_delta_update_attr_value( - iotx_shadow_attr_pt pattr, - const char *pvalue, - size_t value_len) -{ - return iotx_ds_common_convert_string2data(pvalue, value_len, pattr->attr_type, pattr->pattr_data); -} - - -static void iotx_shadow_delta_update_attr(iotx_shadow_pt pshadow, - const char *json_doc_attr, - uint32_t json_doc_attr_len, - const char *json_doc_metadata, - uint32_t json_doc_metadata_len) -{ - const char *pvalue; - iotx_shadow_attr_pt pattr; - list_iterator_t *iter; - list_node_t *node; - - /* Iterate the list and check JSON document according to list_node.val.pattr_name */ - /* If the attribute be found, call the function registered by calling iotx_shadow_delta_register_attr() */ - - HAL_MutexLock(pshadow->mutex); - iter = list_iterator_new(pshadow->inner_data.attr_list, LIST_TAIL); - if (NULL == iter) { - HAL_MutexUnlock(pshadow->mutex); - log_warning("Allocate memory failed"); - return ; - } - - while (node = list_iterator_next(iter), NULL != node) { - pattr = (iotx_shadow_attr_pt)node->val; - pvalue = LITE_json_value_of((char *)pattr->pattr_name, (char *)json_doc_attr); - - /* check if match attribute or not be matched */ - if (NULL != pvalue) { /* attribute be matched */ - /* get timestamp */ - pattr->timestamp = iotx_shadow_get_timestamp( - json_doc_metadata, - json_doc_metadata_len, - pattr->pattr_name); - - /* convert string of JSON value according to destination data type. */ - if (SUCCESS_RETURN != iotx_shadow_delta_update_attr_value(pattr, pvalue, strlen(pvalue))) { - log_warning("Update attribute value failed."); - } - - if (NULL != pattr->callback) { - HAL_MutexUnlock(pshadow->mutex); - /* call related callback function */ - pattr->callback(pattr); - HAL_MutexLock(pshadow->mutex); - } - } - } - - list_iterator_destroy(iter); - HAL_MutexUnlock(pshadow->mutex); -} - -/* handle response ACK of UPDATE */ -void iotx_shadow_delta_entry( - iotx_shadow_pt pshadow, - const char *json_doc, - size_t json_doc_len) -{ - const char *key_metadata; - const char *pstate, *pmetadata; - - pstate = LITE_json_value_of((char *)"payload.state.desired", (char *)json_doc); - if (NULL != pstate) { - key_metadata = "payload.metadata.desired"; - } else { - /* if have not desired key, get reported key instead. */ - key_metadata = "payload.metadata.reported"; - pstate = LITE_json_value_of((char *)"payload.state.reported", (char *)json_doc); - } - - pmetadata = LITE_json_value_of((char *)key_metadata, (char *)json_doc); - - if ((NULL == pstate) || (NULL == pmetadata)) { - log_err("Invalid JSON Doc"); - return; - } - - iotx_shadow_delta_update_attr(pshadow, - pstate, - strlen(pstate), - pmetadata, - strlen(pmetadata)); - - LITE_free(pstate); - LITE_free(pmetadata); - - /* generate ACK and publish to @update topic using QOS1 */ - iotx_shadow_delta_response(pshadow); -} - diff --git a/iotkit-embedded/src/shadow/shadow_delta.h b/iotkit-embedded/src/shadow/shadow_delta.h deleted file mode 100644 index 6485fc0..0000000 --- a/iotkit-embedded/src/shadow/shadow_delta.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef _IOTX_SHADOW_DELTA_H_ -#define _IOTX_SHADOW_DELTA_H_ - -#include "iot_import.h" -#include "shadow.h" -#include "shadow_config.h" -#include "shadow_common.h" -#include "shadow_update.h" - - -int iotx_shadow_delta_check_existence(iotx_shadow_pt pshadow, const char *attr_name); - -void iotx_shadow_delta_entry( - iotx_shadow_pt pshadow, - const char *json_doc, - size_t json_doc_len); - -iotx_err_t iotx_shadow_delta_register_attr( - iotx_shadow_pt pshadow, - iotx_shadow_attr_pt pattr); - -#endif /* _IOTX_SHADOW_DELTA_H_ */ diff --git a/iotkit-embedded/src/shadow/shadow_update.c b/iotkit-embedded/src/shadow/shadow_update.c deleted file mode 100644 index bd162c1..0000000 --- a/iotkit-embedded/src/shadow/shadow_update.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include "iot_import.h" - -#include "lite-log.h" -#include "lite-utils.h" -#include "lite-system.h" - -#include "shadow_update.h" - -extern void iotx_shadow_delta_entry( - iotx_shadow_pt pshadow, - const char *json_doc, - size_t json_doc_len); - - -/* add a new wait element */ -/* return: NULL, failed; others, pointer of element. */ -iotx_update_ack_wait_list_pt iotx_shadow_update_wait_ack_list_add( - iotx_shadow_pt pshadow, - const char *ptoken, /* NOTE: this is NOT a string. */ - size_t token_len, - iotx_push_cb_fpt cb, - void *pcontext, - uint32_t timeout) -{ - int i; - iotx_update_ack_wait_list_pt list = pshadow->inner_data.update_ack_wait_list; - - HAL_MutexLock(pshadow->mutex); - - for (i = 0; i < IOTX_DS_UPDATE_WAIT_ACK_LIST_NUM; ++i) { - if (0 == list[i].flag_busy) { - list[i].flag_busy = 1; - break; - } - } - - HAL_MutexUnlock(pshadow->mutex); - - if (i >= IOTX_DS_UPDATE_WAIT_ACK_LIST_NUM) { - return NULL; - } - - list[i].callback = cb; - list[i].pcontext = pcontext; - - if (token_len >= IOTX_DS_TOKEN_LEN) { - log_warning("token is too long."); - token_len = IOTX_DS_TOKEN_LEN - 1; - } - memcpy(list[i].token, ptoken, token_len); - list[i].token[token_len] = '\0'; - - iotx_time_init(&list[i].timer); - utils_time_countdown_ms(&list[i].timer, timeout); - - log_debug("Add update ACK list"); - - return &list[i]; -} - - -void iotx_shadow_update_wait_ack_list_remove(iotx_shadow_pt pshadow, iotx_update_ack_wait_list_pt element) -{ - HAL_MutexLock(pshadow->mutex); - element->flag_busy = 0; - memset(element, 0, sizeof(iotx_update_ack_wait_list_t)); - HAL_MutexUnlock(pshadow->mutex); -} - - -void iotx_ds_update_wait_ack_list_handle_expire(iotx_shadow_pt pshadow) -{ - size_t i; - - iotx_update_ack_wait_list_pt pelement = pshadow->inner_data.update_ack_wait_list; - - HAL_MutexLock(pshadow->mutex); - - for (i = 0; i < IOTX_DS_UPDATE_WAIT_ACK_LIST_NUM; ++i) { - if (0 != pelement[i].flag_busy) { - if (utils_time_is_expired(&pelement[i].timer)) { - if (NULL != pelement[i].callback) { - pelement[i].callback(pelement[i].pcontext, IOTX_SHADOW_ACK_TIMEOUT, NULL, 0); - } - /* free it. */ - memset(&pelement[i], 0, sizeof(iotx_update_ack_wait_list_t)); - } - } - } - - HAL_MutexUnlock(pshadow->mutex); -} - - -/* handle response ACK of UPDATE */ -void iotx_ds_update_wait_ack_list_handle_response( - iotx_shadow_pt pshadow, - const char *json_doc, - size_t json_doc_len) -{ - int i; - const char *pdata, *ppayload, *pToken; - iotx_update_ack_wait_list_pt pelement = pshadow->inner_data.update_ack_wait_list; - - /* get token */ - pdata = LITE_json_value_of("clientToken", (char *)json_doc); - if (NULL == pdata) { - log_warning("Invalid JSON document: not 'clientToken' key"); - return; - } - pToken = pdata; - - ppayload = LITE_json_value_of("payload", (char *)json_doc); - if (NULL == ppayload) { - log_warning("Invalid JSON document: not 'payload' key"); - LITE_free(pdata); - return; - } else { - log_debug("ppayload = %s", ppayload); - } - - HAL_MutexLock(pshadow->mutex); - for (i = 0; i < IOTX_DS_UPDATE_WAIT_ACK_LIST_NUM; ++i) { - if (0 != pelement[i].flag_busy) { - /* check the related */ - if (0 == memcmp(pdata, pelement[i].token, strlen(pelement[i].token))) { - LITE_free(pdata); - HAL_MutexUnlock(pshadow->mutex); - /* log_debug("token=%s", pelement[i].token); */ - do { - pdata = LITE_json_value_of("status", (char *)ppayload); - if (NULL == pdata) { - log_warning("Invalid JSON document: not 'payload.status' key"); - break; - } - - if (0 == strncmp(pdata, "success", strlen(pdata))) { - char *temp = NULL; - - /* If have 'state' keyword in @json_shadow.payload, attribute value should be updated. */ - temp = LITE_json_value_of("state", (char *)ppayload); - if (NULL != temp) { - iotx_shadow_delta_entry(pshadow, json_doc, json_doc_len); /* update attribute */ - LITE_free(temp); - } - - pelement[i].callback(pelement[i].pcontext, IOTX_SHADOW_ACK_SUCCESS, NULL, 0); - } else if (0 == strncmp(pdata, "error", strlen(pdata))) { - int ack_code; - - pdata = LITE_json_value_of("content.errorcode", (char *)ppayload); - if (NULL == pdata) { - log_warning("Invalid JSON document: not 'content.errorcode' key"); - break; - } - ack_code = atoi(pdata); - LITE_free(pdata); - - pdata = LITE_json_value_of("content.errormessage", (char *)ppayload); - if (NULL == pdata) { - log_warning("Invalid JSON document: not 'content.errormessage' key"); - break; - } - - pelement[i].callback(pelement[i].pcontext, ack_code, pdata, strlen(pdata)); - LITE_free(pdata); - } else { - log_warning("Invalid JSON document: value of 'status' key is invalid."); - LITE_free(pdata); - } - - LITE_free(pdata); - LITE_free(ppayload); - } while (0); - - HAL_MutexLock(pshadow->mutex); - memset(&pelement[i], 0, sizeof(iotx_update_ack_wait_list_t)); - HAL_MutexUnlock(pshadow->mutex); - return; - } - } - } - - LITE_free(pToken); - LITE_free(ppayload); - HAL_MutexUnlock(pshadow->mutex); - log_warning("Not match any wait element in list."); -} diff --git a/iotkit-embedded/src/shadow/shadow_update.h b/iotkit-embedded/src/shadow/shadow_update.h deleted file mode 100644 index 7969997..0000000 --- a/iotkit-embedded/src/shadow/shadow_update.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef _IOTX_SHADOW_UPDATE_H_ -#define _IOTX_SHADOW_UPDATE_H_ - -#include "iot_import.h" - -#include "shadow.h" -#include "shadow_config.h" -#include "shadow_common.h" - - -iotx_update_ack_wait_list_pt iotx_shadow_update_wait_ack_list_add( - iotx_shadow_pt pshadow, - const char *token, - size_t token_len, - iotx_push_cb_fpt cb, - void *pcontext, - uint32_t timeout); - -void iotx_shadow_update_wait_ack_list_remove(iotx_shadow_pt pshadow, iotx_update_ack_wait_list_pt element); - -void iotx_ds_update_wait_ack_list_handle_expire(iotx_shadow_pt pshadow); - -void iotx_ds_update_wait_ack_list_handle_response( - iotx_shadow_pt pshadow, - const char *json_doc, - size_t json_doc_len); - - -#endif /* _IOTX_SHADOW_UPDATE_H_ */ diff --git a/iotkit-embedded/src/subdev/CMakeLists.txt b/iotkit-embedded/src/subdev/CMakeLists.txt deleted file mode 100644 index 97ca36a..0000000 --- a/iotkit-embedded/src/subdev/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -if(FEATURE_CLOUD_CONN_ENABLED) - add_definitions(-DSUBDEV_VIA_CLOUD_CONN) -endif(FEATURE_CLOUD_CONN_ENABLED) - -file(GLOB C_SOURCES "*.c") -add_library(iot_subdev OBJECT ${C_SOURCES}) diff --git a/iotkit-embedded/src/subdev/iot.mk b/iotkit-embedded/src/subdev/iot.mk deleted file mode 100644 index 2784446..0000000 --- a/iotkit-embedded/src/subdev/iot.mk +++ /dev/null @@ -1,2 +0,0 @@ -LIBA_TARGET := libiot_subdev.a -HDR_REFS := src diff --git a/iotkit-embedded/src/subdev/iotx_subdev_api.c b/iotkit-embedded/src/subdev/iotx_subdev_api.c deleted file mode 100644 index f141207..0000000 --- a/iotkit-embedded/src/subdev/iotx_subdev_api.c +++ /dev/null @@ -1,1770 +0,0 @@ -#include "iot_import.h" - -#include "utils_list.h" -#include "lite-utils.h" -#include "lite-system.h" -#include "iotx_subdev_common.h" - -iotx_gateway_t g_gateway_subdevice = {0}; -iotx_gateway_pt g_gateway_subdevice_t = &g_gateway_subdevice; - -static void iotx_mqtt_reconnect_callback(iotx_gateway_pt gateway); - -static int iotx_gateway_recv_publish_callbacks(iotx_gateway_pt gateway, - char* recv_topic, - char* recv_payload); - -static int iotx_subdevice_recv_rrpc_callback(iotx_gateway_pt gateway, - char* recv_topic, - char* recv_payload); - - -#ifdef SUBDEV_VIA_CLOUD_CONN -static void _event_handle(void *pcontext, iotx_cloud_connection_event_msg_pt msg) -{ - log_info("_event_handle type %d", msg->event_id); - - if (msg->event_id == IOTX_CLOUD_CONNECTION_EVENT_RECONNECT) { - iotx_mqtt_reconnect_callback(pcontext); - } -} - -void _response_handle(void *pcontext, void *pconnection, iotx_cloud_connection_msg_rsp_pt msg) -{ - iotx_gateway_pt gateway = (iotx_gateway_pt)pcontext; - - log_info("response %d", msg->rsp_type); - - switch(msg->rsp_type) { - case IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_SUCCESS: - case IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_SUCCESS: - gateway->gateway_data.sync_status = 0; - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SUBSCRIBE_FAIL: - case IOTX_CLOUD_CONNECTION_RESPONSE_UNSUBSCRIBE_FAIL: - gateway->gateway_data.sync_status = -1; - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SEND_SUCCESS: - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_SEND_FAIL: - break; - - case IOTX_CLOUD_CONNECTION_RESPONSE_NEW_DATA:{ - char* publish_topic = NULL; - char* publish_payload = NULL; - - /* printf payload */ - log_info("topic message arrived : topic [%.*s]\n", - msg->URI_length, - msg->URI); - - log_info("payload length [%d]", msg->payload_length); - - MALLOC_MEMORY(publish_topic, msg->payload_length + 1); - MALLOC_MEMORY_WITH_FREE(publish_payload, msg->payload_length + 1, publish_topic); - - strncpy(publish_topic, msg->URI, msg->URI_length); - strncpy(publish_payload, msg->payload, msg->payload_length); - - - if (SUCCESS_RETURN == iotx_gateway_recv_publish_callbacks(gateway, publish_topic, publish_payload) - || SUCCESS_RETURN == iotx_subdevice_recv_rrpc_callback(gateway, publish_topic, publish_payload)) { - LITE_free(publish_topic); - LITE_free(publish_payload); - return; - } - - LITE_free(publish_topic); - LITE_free(publish_payload); - } - - break; - default: - break; - } -} - -#endif - - -static int iotx_subdevice_common_reply_proc(iotx_gateway_pt gateway, - char* payload, - iotx_gateway_publish_t reply_type) -{ - char* node = NULL; - iotx_common_reply_data_pt reply_data = NULL; - - log_info("recv reply"); - - if (gateway == NULL || payload == NULL) { - log_info("param error"); - return ERROR_SUBDEV_NULL_VALUE; - } - - switch(reply_type) { - case IOTX_GATEWAY_PUBLISH_REGISTER: - reply_data = &gateway->gateway_data.register_reply; - break; - case IOTX_GATEWAY_PUBLISH_UNREGISTER: - reply_data = &gateway->gateway_data.unregister_reply; - break; - case IOTX_GATEWAY_PUBLISH_LOGIN: - reply_data = &gateway->gateway_data.login_reply; - break; - case IOTX_GATEWAY_PUBLISH_LOGOUT: - reply_data = &gateway->gateway_data.logout_reply; - break; - case IOTX_GATEWAY_PUBLISH_TOPO_ADD: - reply_data = &gateway->gateway_data.topo_add_reply; - break; - case IOTX_GATEWAY_PUBLISH_TOPO_DELETE: - reply_data = &gateway->gateway_data.topo_delete_reply; - break; - case IOTX_GATEWAY_PUBLISH_TOPO_GET: - reply_data = &gateway->gateway_data.topo_get_reply; - break; - case IOTX_GATEWAY_PUBLISH_CONFIG_GET: - reply_data = &gateway->gateway_data.config_get_reply; - break; - case IOTX_GATEWAY_PUBLISH_LIST_FOUND: - reply_data = &gateway->gateway_data.list_found_reply; - break; - default: - log_info("param error"); - return ERROR_SUBDEV_REPLY_TYPE_NOT_DEF; - } - - /* parse result */ - /* parse id */ - node = LITE_json_value_of("id", payload); - if (node == NULL) { - log_err("get id of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - - if (reply_data->id == atoi(node)) { - reply_data->id = 0; - } - - LITE_free(node); - node = NULL; - /* parse code */ - node = LITE_json_value_of("code", payload); - if (node == NULL) { - log_err("get code of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - - reply_data->code = atoi(node); - LITE_free(node); - node = NULL; - - if (IOTX_GATEWAY_PUBLISH_REGISTER == reply_type) { - /* parse code */ - node = LITE_json_value_of("data", payload); - if (node == NULL) { - log_err("register reply: get data of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - if (strlen(node) > REPLY_MESSAGE_LEN_MAX) { - log_err("topo_get reply size is large then REPLY_MESSAGE_LEN_MAX, please modify the REPLY_MESSAGE_LEN_MAX"); - return ERROR_SUBDEV_DATA_LEN_OVERFLOW; - } - memset(gateway->gateway_data.register_message, 0x0, REPLY_MESSAGE_LEN_MAX); - strncpy(gateway->gateway_data.register_message, node, strlen(node)); - - LITE_free(node); - node = NULL; - } else if (IOTX_GATEWAY_PUBLISH_TOPO_GET == reply_type) { - /* parse code */ - node = LITE_json_value_of("data", payload); - if (node == NULL) { - log_err("topo_get reply: get data of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - if (strlen(node) > REPLY_MESSAGE_LEN_MAX) { - LITE_free(node); - log_err("topo_get reply size is large then REPLY_MESSAGE_LEN_MAX, please modify the REPLY_MESSAGE_LEN_MAX"); - return ERROR_SUBDEV_DATA_LEN_OVERFLOW; - } - memset(gateway->gateway_data.topo_get_message, 0x0, REPLY_MESSAGE_LEN_MAX); - strncpy(gateway->gateway_data.topo_get_message, node, strlen(node)); - LITE_free(node); - node = NULL; - } else if (IOTX_GATEWAY_PUBLISH_CONFIG_GET == reply_type) { - /* parse code */ - node = LITE_json_value_of("data", payload); - if (node == NULL) { - log_err("config_get reply: get data of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - if (strlen(node) > REPLY_MESSAGE_LEN_MAX) { - LITE_free(node); - log_err("config_get reply size is large then REPLY_MESSAGE_LEN_MAX, please modify the REPLY_MESSAGE_LEN_MAX"); - return ERROR_SUBDEV_DATA_LEN_OVERFLOW; - } - memset(gateway->gateway_data.config_get_message, 0x0, REPLY_MESSAGE_LEN_MAX); - strncpy(gateway->gateway_data.config_get_message, node, strlen(node)); - LITE_free(node); - node = NULL; - } - - return SUCCESS_RETURN; -} - -static int iotx_parse_rrpc_message_id(const char* topic, char* message, uint32_t message_len) -{ - char* temp; - temp = strstr(topic, "/rrpc/request/"); - if (temp == NULL) { - log_err("parse error"); - return ERROR_SUBDEV_NULL_VALUE; - } - - temp = temp + strlen("/rrpc/request/"); - - if (strlen(temp) + 1 > message_len) { - log_info("message len error"); - return ERROR_SUBDEV_MSG_LEN; - } - - strncpy(message, temp, strlen(temp)); - - log_info("message %s", message); - - return SUCCESS_RETURN; -} - - -/*recv subdev publish message proc*/ -static int iotx_subdevice_recv_rrpc_callback(iotx_gateway_pt gateway, - char* recv_topic, - char* recv_payload) -{ - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_subdevice_session_pt session = NULL; - - if (gateway == NULL || recv_topic == NULL || recv_payload == NULL) { - log_info("param error"); - return ERROR_SUBDEV_NULL_VALUE; - } - - session = gateway->session_list; - - while (session) { - memset(topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(topic, GATEWAY_TOPIC_LEN_MAX, TOPIC_SYS_RRPC_FMT, session->product_key, - session->device_name, "request"); - if ((strlen(recv_topic) >= strlen(topic) - 2) && - (0 == strncmp(recv_topic, topic, strlen(topic) - 2))) { - /* subdev rrpc */ - log_info("session rrpc callback"); - - if (session->rrpc_callback) { - char message_id[200] = {0}; - if (SUCCESS_RETURN == iotx_parse_rrpc_message_id(recv_topic, message_id, 20)) { - session->rrpc_callback((void*)gateway, - session->product_key, - session->device_name, - message_id, - recv_payload); - } - } - else - log_info("recv rrpc request, but not register callback"); - return SUCCESS_RETURN; - } - session = session->next; - } - - return ERROR_SUBDEV_SESSION_NOT_FOUND; -} - -/*recv gateway publish message proc*/ -static int iotx_gateway_recv_publish_callbacks(iotx_gateway_pt gateway, - char* recv_topic, - char* recv_payload) -{ - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_device_info_pt pdevice_info = NULL; - - if (gateway == NULL || recv_topic == NULL || recv_payload == NULL) { - log_info("param error"); - return ERROR_SUBDEV_NULL_VALUE; - } - - pdevice_info = iotx_device_info_get(); - - /* login_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_COMBINE_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "login_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_LOGIN); - return SUCCESS_RETURN; - } - - /* logout_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_COMBINE_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "logout_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_LOGOUT); - return SUCCESS_RETURN; - } - - /* register_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_SUB_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "register_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - if (SUCCESS_RETURN == iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_REGISTER)) - return SUCCESS_RETURN; - else - return ERROR_SUBDEV_REPLY_PROC; - } - - /* unregister_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_SUB_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "unregister_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_UNREGISTER); - return SUCCESS_RETURN; - } - - /* todo_add_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_TOPO_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "add_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_TOPO_ADD); - return SUCCESS_RETURN; - } - - /* todo_delete_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_TOPO_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "delete_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_TOPO_DELETE); - return SUCCESS_RETURN; - } - - /* todo_get_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_TOPO_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "get_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_TOPO_GET); - return SUCCESS_RETURN; - } - - /* config_get_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_CONFIG_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "get_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_CONFIG_GET); - return SUCCESS_RETURN; - } - - /* list_found_reply */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_LIST_FOUND_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "found_reply"); - if ((strlen(recv_topic) == strlen(topic)) && - (0 == strncmp(recv_topic, topic, strlen(topic)))) { - iotx_subdevice_common_reply_proc(gateway, recv_payload, IOTX_GATEWAY_PUBLISH_LIST_FOUND); - return SUCCESS_RETURN; - } - - - /* rrpc request */ - memset(topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SYS_RRPC_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "request"); - /* note: rrpc topic /+ */ - if ((strlen(recv_topic) >= strlen(topic) - 2) && - (0 == strncmp(recv_topic, topic, strlen(topic) - 2))) { - log_info("gateway rrpc callback"); - - if (gateway->gateway_data.rrpc_callback) { - char message_id[200] = {0}; - if (SUCCESS_RETURN == iotx_parse_rrpc_message_id(recv_topic, message_id, 20)) { - gateway->gateway_data.rrpc_callback((void*)gateway, - pdevice_info->product_key, - pdevice_info->device_name, - message_id, - recv_payload); - } - } - else - log_info("there is no gateway rrpc callback, please call IOT_RRPC_Register with gateway's device_cloud_id first"); - - return SUCCESS_RETURN; - } - - return ERROR_SUBDEV_REPLY_TOPIC_NOT_MATCH; -} - - -/* login all subdev */ -static void iotx_mqtt_reconnect_callback(iotx_gateway_pt gateway) -{ - iotx_subdevice_session_pt session = NULL; - iotx_subdevice_session_pt next_session = NULL; - - if (NULL == gateway) { - log_info("param error"); - return; - } - - log_info("iotx_mqtt_reconnect_callback"); - - session = gateway->session_list; - - while (session) { - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(session->lock_status); - #endif - session->session_status = IOTX_SUBDEVICE_SEESION_STATUS_INIT; - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(session->lock_status); - #endif - next_session = session->next; - if (SUCCESS_RETURN != IOT_Subdevice_Login(gateway, - session->product_key, - session->device_name, - session->timestamp, - session->client_id, - session->sign, - session->sign_method, - session->clean_session)) { - log_info("reconnect, %s re_login error", session->device_cloud_id); - } - session = next_session; - } -} - - -/* parse reigster_reply result */ -static int iotx_subdevice_parse_register_reply( char* message, - const char* product_key, - const char* device_name, - char* device_secret) -{ - char* node = NULL; - char* data = message; - - /* check parameter */ - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(data, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_NULL_CHECK_WITH_RESULT(device_secret, ERROR_SUBDEV_NULL_VALUE); - - /* there is a '[' in data */ - if (data[0] == '[') - data++; - - /* product key */ - node = LITE_json_value_of("productKey", data); - if (node == NULL) { - log_err("get id of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - if (0 != strncmp(node, product_key, strlen(product_key))) { - LITE_free(node); - log_err("productkey error!"); - return ERROR_SUBDEV_REPLY_VAL_CHECK; - } - - /* device name */ - LITE_free(node); - node = NULL; - node = LITE_json_value_of("deviceName", data); - if (node == NULL) { - log_err("get id of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - if (0 != strncmp(node, device_name, strlen(device_name))) { - LITE_free(node); - log_err("deviceName error!"); - return ERROR_SUBDEV_REPLY_VAL_CHECK; - } - - /* device secret */ - LITE_free(node); - node = NULL; - node = LITE_json_value_of("deviceSecret", data); - if (node == NULL) { - log_err("get id of json error!"); - return ERROR_SUBDEV_GET_JSON_VAL; - } - strncpy(device_secret, node, strlen(node)); - - LITE_free(node); - node = NULL; - - return SUCCESS_RETURN; -} - -#ifndef SUBDEV_VIA_CLOUD_CONN -void iotx_gateway_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) -{ - uintptr_t packet_id = (uintptr_t)msg->msg; - iotx_gateway_pt gateway = (iotx_gateway_pt)pcontext; - iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)(msg->msg); - - if (gateway == NULL) { - log_info("param error"); - return; - } - - log_info("event type %d", msg->event_type); - - switch (msg->event_type) { - case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: - case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(gateway->gateway_data.lock_sync); - #endif - if (gateway->gateway_data.sync_status == packet_id) { - gateway->gateway_data.sync_status = 0; - return; - } - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(gateway->gateway_data.lock_sync); - #endif - break; - - case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: - case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: - case IOTX_MQTT_EVENT_SUBCRIBE_NACK: - case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK: - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(gateway->gateway_data.lock_sync); - #endif - if (gateway->gateway_data.sync_status == packet_id) { - gateway->gateway_data.sync_status = -1; - return; - } - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(gateway->gateway_data.lock_sync); - #endif - break; - - case IOTX_MQTT_EVENT_PUBLISH_RECVEIVED: { - char* publish_topic = NULL; - char* publish_payload = NULL; - int printf_num = 0; - char dsltemplate_printf[512] = {0}; - - /* printf payload */ - log_info("topic message arrived : topic [%.*s]\n", - topic_info->topic_len, - topic_info->ptopic); - - log_info("payload length [%d]", topic_info->payload_len); - log_info("payload:"); - while(printf_num < topic_info->payload_len) { - memset(dsltemplate_printf, 0x0, 512); - if (topic_info->payload_len - printf_num > 500) { - strncpy(dsltemplate_printf, &topic_info->payload[printf_num], 500); - printf_num += 500; - } else if (topic_info->payload_len - printf_num <= 500){ - strncpy(dsltemplate_printf, &topic_info->payload[printf_num], topic_info->payload_len - printf_num); - printf_num = topic_info->payload_len; - } - log_info("%s", dsltemplate_printf); - } - MALLOC_MEMORY(publish_topic, topic_info->topic_len + 1); - MALLOC_MEMORY_WITH_FREE(publish_payload, topic_info->payload_len + 1, publish_topic); - - strncpy(publish_topic, topic_info->ptopic, topic_info->topic_len); - strncpy(publish_payload, topic_info->payload, topic_info->payload_len); - - if (SUCCESS_RETURN == iotx_gateway_recv_publish_callbacks(gateway, publish_topic, publish_payload) - || SUCCESS_RETURN == iotx_subdevice_recv_rrpc_callback(gateway, publish_topic, publish_payload)) { - LITE_free(publish_topic); - LITE_free(publish_payload); - return; - } - - LITE_free(publish_topic); - LITE_free(publish_payload); - } - break; - - case IOTX_MQTT_EVENT_RECONNECT: - iotx_mqtt_reconnect_callback(pcontext); - return; - break; - - case IOTX_MQTT_EVENT_DISCONNECT: - case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: - return; - break; - - case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: - case IOTX_MQTT_EVENT_PUBLISH_NACK: - log_info("publish fail"); - return; - break; - - default: - return; - break; - } - - if (gateway->event_handler) { - gateway->event_handler(gateway->event_pcontext, pclient, msg); - } - - return; -} -#endif - -/* global message id */ -uint32_t global_gateway_cloud_id = 0; - -uint32_t IOT_Gateway_Generate_Message_ID() -{ - global_gateway_cloud_id += 1; - - return ((global_gateway_cloud_id == 0 )? global_gateway_cloud_id += 1 : global_gateway_cloud_id); -} - - -void* IOT_Gateway_Construct(iotx_gateway_param_pt gateway_param) -{ -#ifdef SUBDEV_VIA_CLOUD_CONN - void* handle = NULL; - iotx_cloud_connection_param_t param = {0}; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); -#endif - - PARAMETER_NULL_CHECK_WITH_RESULT(gateway_param, NULL); - PARAMETER_NULL_CHECK_WITH_RESULT(gateway_param->mqtt, NULL); - - if (g_gateway_subdevice_t->is_construct) { - log_err("gateway have been construct"); - return NULL; - } - - memset(g_gateway_subdevice_t, 0x0, sizeof(iotx_gateway_t)); - -#ifndef SUBDEV_VIA_CLOUD_CONN - gateway_param->mqtt->handle_event.h_fp = iotx_gateway_event_handle; - gateway_param->mqtt->handle_event.pcontext = g_gateway_subdevice_t; - - /* construct MQTT client */ -#ifndef MQTT_ID2_AUTH - if (NULL == (g_gateway_subdevice_t->mqtt = IOT_MQTT_Construct(gateway_param->mqtt))) { -#else - if (NULL == (g_gateway_subdevice_t->mqtt = IOT_MQTT_ConstructSecure(gateway_param->mqtt))) { -#endif /**< MQTT_ID2_AUTH*/ - log_err("construct MQTT failed"); - return NULL; - } -#else /* SUBDEV_VIA_CLOUD_CONN */ - param.device_info = LITE_malloc(sizeof(iotx_deviceinfo_t)); - if (NULL == param.device_info) { - log_info("memory error!"); - return NULL; - } - memset(param.device_info, 0x00, sizeof(iotx_device_info_t)); - strncpy(param.device_info->device_id, pdevice_info->device_id, IOTX_DEVICE_ID_LEN); - strncpy(param.device_info->product_key, pdevice_info->product_key, IOTX_PRODUCT_KEY_LEN); - strncpy(param.device_info->device_secret, pdevice_info->device_secret, IOTX_DEVICE_SECRET_LEN); - strncpy(param.device_info->device_name, pdevice_info->device_name, IOTX_DEVICE_NAME_LEN); - - param.clean_session = gateway_param->mqtt->clean_session; - param.keepalive_interval_ms = gateway_param->mqtt->keepalive_interval_ms; - param.request_timeout_ms = gateway_param->mqtt->request_timeout_ms; - param.protocol_type = IOTX_CLOUD_CONNECTION_PROTOCOL_TYPE_MQTT; - param.event_handler = _event_handle; - param.event_pcontext = (void*)g_gateway_subdevice_t; - - handle = IOT_Cloud_Connection_Init(¶m); - - if (handle == NULL) { - return NULL; - } - - g_gateway_subdevice_t->mqtt = handle; -#endif /* SUBDEV_VIA_CLOUD_CONN */ - -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - g_gateway_subdevice_t->gateway_data.lock_sync = HAL_MutexCreate(); - g_gateway_subdevice_t->gateway_data.lock_sync_enter = HAL_MutexCreate(); - if (NULL == g_gateway_subdevice_t->gateway_data.lock_sync || - NULL == g_gateway_subdevice_t->gateway_data.lock_sync_enter) - { - log_err("create mutex error"); - return NULL; - } -#endif - - /* handle mqtt event for user */ - g_gateway_subdevice_t->event_handler = gateway_param->event_handler; - g_gateway_subdevice_t->event_pcontext = gateway_param->event_pcontext; - - /* subscribe default topic */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_default(g_gateway_subdevice_t, 1)) { - log_err("subscribe default topic fialed"); - IOT_Gateway_Destroy((void**)&g_gateway_subdevice_t); - return NULL; - } - - g_gateway_subdevice_t->is_construct = 1; - - return g_gateway_subdevice_t; -} - - -/* Register: static and dynamic */ -int IOT_Subdevice_Register(void* handle, - iotx_subdev_register_types_t type, - const char* product_key, - const char* device_name, - char* timestamp, - char* client_id, - char* sign, - iotx_subdev_sign_method_types_t sign_type) -{ - uint32_t msg_id = 0; - int rc = 0; - char* packet = NULL; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - char device_secret[DEVICE_SECRET_LEN] = {0}; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - iotx_subdevice_session_pt session = NULL; - - /* parameter check */ - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, ERROR_SUBDEV_STRING_NULL_VALUE); - /* check register type */ - if (type != IOTX_SUBDEV_REGISTER_TYPE_DYNAMIC && - type != IOTX_SUBDEV_REGISTER_TYPE_STATIC) { - log_info("register type not support"); - return ERROR_SUBDEV_REGISTER_TYPE_NOT_DEF; - } - - /* dynamic: get device secret first */ - /* sync wait for response */ - if (IOTX_SUBDEV_REGISTER_TYPE_DYNAMIC == type) { - if (NULL != timestamp && NULL != client_id && NULL != sign) { - log_info("parameter error, if dynamic register, timestamp = client_id = sign = NULL"); - return ERROR_SUBDEV_NOT_NULL_VALUE; - } - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_SUB_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "register"); - - /* packet */ - packet = iotx_gateway_splice_common_packet(product_key, - device_name, - "thing.sub.register", - &msg_id); - - if (packet == NULL) { - log_err("login packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - /* publish packet */ - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - packet, - msg_id, - &(gateway->gateway_data.register_reply), - IOTX_GATEWAY_PUBLISH_REGISTER))) { - LITE_free(packet); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(packet); - - if (SUCCESS_RETURN != (rc = iotx_subdevice_parse_register_reply(gateway->gateway_data.register_message, - product_key, - device_name, - device_secret))) { - log_info("parse register reply error"); - return rc; - } - //log_info("register success, secret %s", device_secret); - - /* timestamp */ - MALLOC_MEMORY_WITH_RESULT(timestamp, 20, FAIL_RETURN); - strncpy(timestamp, "2524608000000", strlen("2524608000000") + 1); - - /* client id */ - MALLOC_MEMORY_WITH_FREE_AND_RESULT(client_id, IOT_SUBDEVICE_CLIENT_ID_LEN, timestamp, FAIL_RETURN); - iotx_subdevice_calc_client_id(client_id, product_key, device_name); - - /* sign */ - MALLOC_MEMORY_WITH_FREE_AND_RESULT(sign, 41, timestamp, FAIL_RETURN); - if (FAIL_RETURN == (rc = iotx_gateway_calc_sign(product_key, - device_name, - device_secret, - sign, - 41, - sign_type, - client_id, - timestamp))) { - log_err("sign fail"); - goto exit; - } - - if (NULL == (session = iotx_subdevice_add_session(gateway, - product_key, - device_name, - NULL, - sign, - timestamp, - client_id, - sign_type, - IOTX_SUBDEV_CLEAN_SESSION_FALSE))) { - log_err("create session error!"); - rc = ERROR_SUBDEV_CREATE_SESSION_FAIL; - goto exit; - } - iotx_subdevice_set_session_status(session, IOTX_SUBDEVICE_SEESION_STATUS_REGISTER); - iotx_subdevice_set_session_dynamic_register(session); - } - - /* check parameter */ - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(timestamp, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(client_id, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign, FAIL_RETURN); - - /* check sign type */ - if (sign_type != IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA && - sign_type != IOTX_SUBDEV_SIGN_METHOD_TYPE_MD5) { - log_info("register type not support"); - rc = ERROR_SUBDEV_REGISTER_TYPE_NOT_DEF; - goto exit; - } - - /* topo add */ - /* topic */ - memset(topic, 0x0, GATEWAY_TOPIC_LEN_MAX); - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_TOPO_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "add"); - - /* topo packet */ - if (sign_type == IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA) { - packet = iotx_gateway_splice_topo_add_packet(product_key, - device_name, - client_id, - timestamp, - "hmacsha1", - sign, - "thing.topo.add", - &msg_id); - } else if (sign_type == IOTX_SUBDEV_SIGN_METHOD_TYPE_MD5) { - packet = iotx_gateway_splice_topo_add_packet(product_key, - device_name, - client_id, - timestamp, - "hmacmd5", - sign, - "thing.topo.add", - &msg_id); - } - - if (packet == NULL) { - log_err("login packet splice error!"); - rc = ERROR_SUBDEV_PACKET_SPLICE_FAIL; - goto exit; - } - - /* publish packet */ - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - packet, - msg_id, - &(gateway->gateway_data.topo_add_reply), - IOTX_GATEWAY_PUBLISH_TOPO_ADD))) { - goto exit; - } - -exit: - if (packet) - LITE_free(packet); - - if (IOTX_SUBDEV_REGISTER_TYPE_DYNAMIC == type) { - LITE_free(timestamp); - LITE_free(client_id); - LITE_free(sign); - } - - return rc; -} - -/* unregister: topo delete first, then unregister */ -int IOT_Subdevice_Unregister(void* handle, - const char* product_key, - const char* device_name) -{ - uint32_t msg_id = 0; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - char* packet = NULL; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - int rc = 0; - - /* parameter check */ - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, ERROR_SUBDEV_STRING_NULL_VALUE); - - /* unregister */ - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_SUB_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "unregister"); - - /* splice unregister packet */ - packet = iotx_gateway_splice_common_packet(product_key, - device_name, - "thing.sub.unregister", - &msg_id); - if (packet == NULL) { - log_err("unregister packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - packet, - msg_id, - &(gateway->gateway_data.unregister_reply), - IOTX_GATEWAY_PUBLISH_UNREGISTER))) { - LITE_free(packet); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(packet); - - /* topo delete */ - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_TOPO_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "delete"); - - /* splice logout packet */ - packet = iotx_gateway_splice_common_packet(product_key, - device_name, - "thing.topo.delete", - &msg_id); - if (packet == NULL) { - log_err("topo_delete packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - packet, - msg_id, - &(gateway->gateway_data.topo_delete_reply), - IOTX_GATEWAY_PUBLISH_TOPO_DELETE))) { - LITE_free(packet); - log_err("MQTT Publish error!"); - return FAIL_RETURN; - } - - LITE_free(packet); - - /* unregister */ - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_SUB_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "unregister"); - - /* splice unregister packet */ - packet = iotx_gateway_splice_common_packet(product_key, - device_name, - "thing.sub.unregister", - &msg_id); - if (packet == NULL) { - log_err("unregister packet splice error!"); - return FAIL_RETURN; - } - - if (FAIL_RETURN == iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - packet, - msg_id, - &(gateway->gateway_data.unregister_reply), - IOTX_GATEWAY_PUBLISH_UNREGISTER)) { - LITE_free(packet); - log_err("MQTT Publish error!"); - return FAIL_RETURN; - } - - LITE_free(packet); - - return SUCCESS_RETURN; -} - - -int IOT_Subdevice_Login(void* handle, - const char* product_key, - const char* device_name, - const char* timestamp, - const char* client_id, - const char* sign, - iotx_subdev_sign_method_types_t sign_method_type, - iotx_subdev_clean_session_types_t clean_session_type) -{ - int rc = 0; - uint32_t msg_id = 0; - char * login_packet = NULL; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - char sign_method[10] = {0}; - char clean_session[10] = {0}; - iotx_subdevice_session_pt session = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, ERROR_SUBDEV_STRING_NULL_VALUE); - - /* check sign method */ - if (clean_session_type != IOTX_SUBDEV_CLEAN_SESSION_TRUE && - clean_session_type != IOTX_SUBDEV_CLEAN_SESSION_FALSE) { - log_info("clean session not support"); - return ERROR_SUBDEV_INVALID_CLEAN_SESSION_TYPE; - } - - if (NULL == (session = iotx_subdevice_find_session(gateway, - product_key, - device_name))) { - log_info("there is no seesion, create a new session"); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(client_id, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(timestamp, FAIL_RETURN); - - /* create subdev session */ - if (NULL == (session = iotx_subdevice_add_session(gateway, - product_key, - device_name, - NULL, - sign, - timestamp, - client_id, - sign_method_type, - clean_session_type))) { - log_err("create session error!"); - return ERROR_SUBDEV_CREATE_SESSION_FAIL; - } - } else { - if (IOTX_SUBDEVICE_SEESION_STATUS_LOGIN == session->session_status) { - log_info("device have been login"); - return ERROR_SUBDEV_HAS_BEEN_LOGIN; - } - } - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_COMBINE_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "login"); - - if (IOTX_SUBDEVICE_SEESION_STATUS_REGISTER == session->session_status) { - sign = session->sign; - sign_method_type = session->sign_method; - client_id = session->client_id; - timestamp = session->timestamp; - } - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(client_id, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(timestamp, ERROR_SUBDEV_STRING_NULL_VALUE); - - if (sign_method_type == IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA) { - strncpy(sign_method, "hmacsha1", strlen("hmacsha1")); - } else { - strncpy(sign_method, "hmacmd5", strlen("hmacmd5")); - } - - if (clean_session_type == IOTX_SUBDEV_CLEAN_SESSION_TRUE) { - strncpy(clean_session, "true", strlen("true")); - } else { - strncpy(clean_session, "false", strlen("false")); - } - - /* packet */ - login_packet = iotx_gateway_splice_login_packet(session->product_key, - session->device_name, - client_id, - timestamp, - sign_method, - sign, - clean_session, - &msg_id); - - - if (login_packet == NULL) { - log_err("login packet splice error!"); - iotx_subdevice_remove_session(gateway, session->product_key, session->device_name); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - /* publish packet */ - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - login_packet, - msg_id, - &(gateway->gateway_data.login_reply), - IOTX_GATEWAY_PUBLISH_LOGIN))) { - LITE_free(login_packet); - iotx_subdevice_remove_session(gateway, session->product_key, session->device_name); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(login_packet); - -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(session->lock_status); -#endif - session->session_status = IOTX_SUBDEVICE_SEESION_STATUS_LOGIN; -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(session->lock_status); -#endif - - /* subscribe rrpc request */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - session->product_key, - session->device_name, - TOPIC_SYS_RRPC_FMT, - "request", - 1)) { - iotx_subdevice_remove_session(gateway, session->product_key, session->device_name); - return ERROR_SUBDEV_SUB_UNSUB_FAIL; - } - - return SUCCESS_RETURN; -} - - -int IOT_Subdevice_Logout(void* handle, - const char * product_key, - const char * device_name) -{ - int rc = 0; - uint32_t msg_id = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_subdevice_session_pt session = NULL; - char* logout_packet = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - session = iotx_subdevice_find_session(gateway, product_key, device_name); - if (NULL == session) { - log_info("no session, can not logout"); - return ERROR_SUBDEV_SESSION_NOT_FOUND; - } - - if (IOTX_SUBDEVICE_SEESION_STATUS_LOGIN != session->session_status) { - log_info("status is not login, can not logout"); - iotx_subdevice_remove_session(gateway, product_key, device_name); - return ERROR_SUBDEV_SESSION_STATE_FAIL; - } - - /* unsubscribe rrpc request */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - session->product_key, - session->device_name, - TOPIC_SYS_RRPC_FMT, - "request", - 0)){ - return ERROR_SUBDEV_SUB_UNSUB_FAIL; - } - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_COMBINE_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "logout"); - - /* splice logout packet */ - logout_packet = iotx_gateway_splice_logout_packet(session->product_key, - session->device_name, - &msg_id); - if (logout_packet == NULL) { - log_err("logout packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - /* publish logout packet */ - iotx_mqtt_topic_info_t topic_msg; - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)logout_packet; - topic_msg.payload_len = strlen(logout_packet); - topic_msg.packet_id = 0; - - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - logout_packet, - msg_id, - &(gateway->gateway_data.logout_reply), - IOTX_GATEWAY_PUBLISH_LOGIN))) { - LITE_free(logout_packet); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(logout_packet); - -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(session->lock_status); -#endif - session->session_status = IOTX_SUBDEVICE_SEESION_STATUS_LOGOUT; -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(session->lock_status); -#endif - - /* free session */ - iotx_subdevice_remove_session(gateway, session->product_key, session->device_name); - - return SUCCESS_RETURN; -} - - -int IOT_Gateway_Get_TOPO(void* handle, - char* get_toop_reply, - uint32_t* length) -{ - int rc = 0; - uint32_t msg_id = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - char* topo_get_packet = NULL; - iotx_mqtt_topic_info_t topic_msg; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_NULL_CHECK_WITH_RESULT(get_toop_reply, ERROR_SUBDEV_NULL_VALUE); - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_TOPO_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "get"); - - /* splice topo_get packet */ - topo_get_packet = iotx_gateway_splice_topo_get_packet(&msg_id); - if (topo_get_packet == NULL) { - log_err("topo_get packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - /* publish topo_get packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)topo_get_packet; - topic_msg.payload_len = strlen(topo_get_packet); - topic_msg.packet_id = 0; - - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - topo_get_packet, - msg_id, - &(gateway->gateway_data.topo_get_reply), - IOTX_GATEWAY_PUBLISH_LOGIN))) { - LITE_free(topo_get_packet); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(topo_get_packet); - - if (*length < strlen(gateway->gateway_data.topo_get_message)) { - log_err("set memory too small"); - return ERROR_SUBDEV_MEMORY_NOT_ENOUGH; - } - - strncpy(get_toop_reply, gateway->gateway_data.topo_get_message, strlen(gateway->gateway_data.topo_get_message)); - - *length = strlen(gateway->gateway_data.topo_get_message); - - return SUCCESS_RETURN; -} - -int IOT_Gateway_Get_Config(void* handle, - char* get_config_reply, - uint32_t* length) -{ - int rc = 0; - uint32_t msg_id = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - char* config_get_packet = NULL; - iotx_mqtt_topic_info_t topic_msg; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_NULL_CHECK_WITH_RESULT(get_config_reply, ERROR_SUBDEV_NULL_VALUE); - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_CONFIG_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "get"); - - /* splice config_get packet */ - config_get_packet = iotx_gateway_splice_config_get_packet(&msg_id); - if (config_get_packet == NULL) { - log_err("config_get packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - /* publish topo_get packet */ - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)config_get_packet; - topic_msg.payload_len = strlen(config_get_packet); - topic_msg.packet_id = 0; - - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - config_get_packet, - msg_id, - &(gateway->gateway_data.config_get_reply), - IOTX_GATEWAY_PUBLISH_CONFIG_GET))) { - LITE_free(config_get_packet); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(config_get_packet); - - if (*length < strlen(gateway->gateway_data.config_get_message)) { - log_err("set memory too small"); - return ERROR_SUBDEV_MEMORY_NOT_ENOUGH; - } - - strncpy(get_config_reply, gateway->gateway_data.config_get_message, strlen(gateway->gateway_data.config_get_message)); - - *length = strlen(gateway->gateway_data.config_get_message); - - return SUCCESS_RETURN; -} - -int IOT_Gateway_Publish_Found_List(void* handle, const char* product_key, - const char* device_name) -{ - int rc = 0; - uint32_t msg_id = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - char* list_found_packet = NULL; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - - /* topic */ - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_SESSION_LIST_FOUND_FMT, - pdevice_info->product_key, - pdevice_info->device_name, - "found"); - - /* splice list_found packet */ - list_found_packet = iotx_gateway_splice_common_packet(product_key, - device_name, - "thing.list.found", - &msg_id); - if (list_found_packet == NULL) { - log_err("list found packet splice error!"); - return ERROR_SUBDEV_PACKET_SPLICE_FAIL; - } - - if (SUCCESS_RETURN != (rc = iotx_gateway_publish_sync(gateway, - IOTX_MQTT_QOS0, - topic, - list_found_packet, - msg_id, - &(gateway->gateway_data.list_found_reply), - IOTX_GATEWAY_PUBLISH_LIST_FOUND))) { - LITE_free(list_found_packet); - log_err("MQTT Publish error!"); - return rc; - } - - LITE_free(list_found_packet); - - return SUCCESS_RETURN; -} - - - -int IOT_Gateway_Destroy(void** handle) -{ - iotx_subdevice_session_pt session, pre_session; - iotx_gateway_pt gateway = NULL; - - PARAMETER_NULL_CHECK_WITH_RESULT(handle, ERROR_SUBDEV_NULL_VALUE); - - gateway = (iotx_gateway_pt)(*handle); - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - - /* free session list */ - pre_session = session = gateway->session_list; - - while (session) { - pre_session = session; - session = session->next; - IOT_Subdevice_Logout(gateway, pre_session->product_key, pre_session->device_name); - } - - /* send unsubscribe packet */ - iotx_gateway_subscribe_unsubscribe_default(gateway, 0); - -#ifdef SUBDEV_VIA_CLOUD_CONN - IOT_Cloud_Connection_Deinit(&gateway->mqtt); -#else - /* MQTT disconnect*/ - IOT_MQTT_Destroy(&gateway->mqtt); -#endif - -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexDestroy(gateway->gateway_data.lock_login); - HAL_MutexDestroy(gateway->gateway_data.lock_login_enter); - HAL_MutexDestroy(gateway->gateway_data.lock_sync); - HAL_MutexDestroy(gateway->gateway_data.lock_sync_enter); -#endif - - /* actually *handle is g_gateway_subdevice_t */ - g_gateway_subdevice_t->is_construct = 0; - *handle = NULL; - - return SUCCESS_RETURN; -} - - -int IOT_Gateway_Yield(void* handle, uint32_t timeout) -{ - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - -#ifdef SUBDEV_VIA_CLOUD_CONN - return IOT_Cloud_Connection_Yield(gateway->mqtt, timeout); -#else - return IOT_MQTT_Yield(gateway->mqtt, timeout); -#endif -} - -int IOT_Gateway_Subscribe(void* handle, - const char *topic_filter, - int qos, - iotx_subdev_event_handle_func_fpt topic_handle_func, - void *pcontext) -{ - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); -#ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_t msg = {0}; - int rc = 0; - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_SUBSCRIBE; - msg.QoS = IOTX_MESSAGE_QOS1; - msg.URI = (char*)topic_filter; - msg.URI_length = strlen(topic_filter); - msg.payload = NULL; - msg.payload_length = 0; - msg.response_handler = (iotx_cloud_connection_msg_rsp_func_fpt)topic_handle_func; - msg.response_pcontext = NULL; - msg.content_type = IOTX_MESSAGE_CONTENT_TYPE_JSON; - msg.message_type = IOTX_MESSAGE_CONFIRMABLE; - rc = IOT_Cloud_Connection_Send_Message(gateway->mqtt, &msg); - if (SUCCESS_RETURN == rc) - return 2; - else - return rc; -#else - return IOT_MQTT_Subscribe(gateway->mqtt, topic_filter, qos, - (iotx_mqtt_event_handle_func_fpt)topic_handle_func, pcontext); -#endif -} - - -int IOT_Gateway_Unsubscribe(void* handle, - const char *topic_filter) -{ - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); -#ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_t msg = {0}; - int rc = 0; - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_UNSUBSCRIBE; - msg.QoS = IOTX_MESSAGE_QOS1; - msg.URI = (char*)topic_filter; - msg.URI_length = strlen(topic_filter); - msg.payload = NULL; - msg.payload_length = 0; - msg.content_type = IOTX_MESSAGE_CONTENT_TYPE_JSON; - msg.message_type = IOTX_MESSAGE_CONFIRMABLE; - rc = IOT_Cloud_Connection_Send_Message(gateway->mqtt, &msg); - if (SUCCESS_RETURN == rc) - return 2; - else - return rc; -#else - return IOT_MQTT_Unsubscribe(gateway->mqtt, topic_filter); -#endif -} - - -int IOT_Gateway_Publish(void* handle, - const char *topic_name, - iotx_mqtt_topic_info_pt topic_msg) -{ - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - int printf_num = 0; - char dsltemplate_printf[512] = {0}; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_NULL_CHECK_WITH_RESULT(topic_msg, ERROR_SUBDEV_NULL_VALUE); - - log_info("Publish topic_name [%s]", topic_name); - log_info("Publish payload length [%d]", topic_msg->payload_len); - log_info("payload:"); - while(printf_num < topic_msg->payload_len) { - memset(dsltemplate_printf, 0x0, 512); - if (topic_msg->payload_len - printf_num > 500) { - strncpy(dsltemplate_printf, &topic_msg->payload[printf_num], 500); - printf_num += 500; - } else if (topic_msg->payload_len - printf_num <= 500){ - strncpy(dsltemplate_printf, &topic_msg->payload[printf_num], topic_msg->payload_len - printf_num); - printf_num = topic_msg->payload_len; - } - log_info("%s", dsltemplate_printf); - } - -#ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_t msg = {0}; - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_PUBLISH; - msg.QoS = topic_msg->qos; - msg.URI = (char*)topic_name; - msg.URI_length = strlen(topic_name); - msg.payload = (void*)topic_msg->payload; - msg.payload_length = topic_msg->payload_len; - msg.content_type = IOTX_MESSAGE_CONTENT_TYPE_JSON; - msg.message_type = IOTX_MESSAGE_CONFIRMABLE; - return IOT_Cloud_Connection_Send_Message(gateway->mqtt, &msg); -#else - return IOT_MQTT_Publish(gateway->mqtt, topic_name, topic_msg); -#endif - -} - -int IOT_Gateway_RRPC_Register(void* handle, - const char* product_key, - const char* device_name, - rrpc_request_callback rrpc_callback) -{ - iotx_subdevice_session_pt session = NULL; - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_NULL_CHECK_WITH_RESULT(rrpc_callback, ERROR_SUBDEV_NULL_VALUE); - - /* gateway rrpc */ - if(0 == strncmp(pdevice_info->product_key, product_key, strlen(product_key)) && - 0 == strncmp(pdevice_info->device_name, device_name, strlen(device_name))) { - if (gateway->gateway_data.rrpc_callback != NULL) { - log_info("rrpc_callback have been set"); - return ERROR_SUBDEV_RRPC_CB_NOT_NULL; - } - - gateway->gateway_data.rrpc_callback = rrpc_callback; - - return SUCCESS_RETURN; - } - - session = iotx_subdevice_find_session(gateway, product_key, device_name); - if(NULL == session) { - log_info("RRPC register fail, can not find device session"); - return ERROR_SUBDEV_SESSION_NOT_FOUND; - } - - /* rrpc callback can not set twice */ - if (session->rrpc_callback != NULL) { - log_info("rrpc_callback have been set, can not set again"); - return ERROR_SUBDEV_RRPC_CB_NOT_NULL; - } - - session->rrpc_callback = rrpc_callback; - - return SUCCESS_RETURN; -} - - -int IOT_Gateway_RRPC_Response(void* handle, - const char* product_key, - const char* device_name, - const char* message_id, - const char* response) -{ -#define TOPIC_RRPC_RESPONSE_FMT "/sys/%s/%s/rrpc/response/%s" - - int rc = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - iotx_mqtt_topic_info_t topic_msg; - iotx_gateway_pt gateway = (iotx_gateway_pt)handle; - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - iotx_subdevice_session_pt session = NULL; - - PARAMETER_GATEWAY_CHECK(gateway, ERROR_SUBDEV_INVALID_GATEWAY_HANDLE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, ERROR_SUBDEV_STRING_NULL_VALUE); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(response, ERROR_SUBDEV_STRING_NULL_VALUE); - - if (0 == strncmp(product_key, pdevice_info->product_key, strlen(product_key)) && - 0 == strncmp(device_name, pdevice_info->device_name, strlen(device_name))) { - log_info("gateway RRPC response"); - goto publish_response; - } else { - session = gateway->session_list; - while (session) { - if (0 == strncmp(product_key, session->product_key, strlen(product_key)) && - 0 == strncmp(device_name, session->device_name, strlen(device_name))) { - log_info("session RRPC response"); - goto publish_response; - } - session = session->next; - } - log_info("no session, can not response"); - return ERROR_SUBDEV_SESSION_NOT_FOUND; - } - - publish_response: - - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - TOPIC_RRPC_RESPONSE_FMT, - product_key, - device_name, - message_id); - - topic_msg.qos = IOTX_MQTT_QOS0; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)response; - topic_msg.payload_len = strlen(response); - topic_msg.packet_id = 0; - - rc = IOT_MQTT_Publish(gateway->mqtt, topic, &topic_msg); - log_info("rc %d", rc); - return rc; -} - diff --git a/iotkit-embedded/src/subdev/iotx_subdev_common.c b/iotkit-embedded/src/subdev/iotx_subdev_common.c deleted file mode 100644 index c6d7adb..0000000 --- a/iotkit-embedded/src/subdev/iotx_subdev_common.c +++ /dev/null @@ -1,835 +0,0 @@ -#include "iot_import.h" -#include "lite-log.h" -#include "lite-utils.h" -#include "utils_timer.h" -#include "utils_list.h" -#include "lite-system.h" -#include "utils_hmac.h" -#include "iot_export_mqtt.h" - -#include "iotx_subdev_common.h" - -#ifndef SUBDEV_VIA_CLOUD_CONN -extern void iotx_gateway_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg); -#endif - - -char *iotx_gateway_splice_common_packet(const char *product_key, - const char* device_name, - const char* method, - uint32_t* msg_id) -{ -#define COMMON_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":[{\"productKey\":\"%s\",\"deviceName\":\"%s\"}],\"method\":\"%s\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(method, NULL); - - /* sum the string length */ - len = strlen(COMMON_PACKET_FMT) + strlen(product_key) + strlen(device_name) + strlen(method) + 12; - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - COMMON_PACKET_FMT, - id, - product_key, - device_name, - method); - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - - - -char *iotx_gateway_splice_topo_get_packet(uint32_t* msg_id) -{ -#define TOPOADD_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":{},\"method\":\"thing.topo.get\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - - /* sum the string length */ - len = strlen(TOPOADD_PACKET_FMT) + 12; - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - TOPOADD_PACKET_FMT, - id); - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - -char *iotx_gateway_splice_config_get_packet(uint32_t* msg_id) -{ -#define CONFIGGET_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":{\"configScope\":\"product\",\"getType\":\"file\"},\"method\":\"thing.config.get\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - - /* sum the string length */ - len = strlen(CONFIGGET_PACKET_FMT) + 12; - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - CONFIGGET_PACKET_FMT, - id); - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - - -char *iotx_gateway_splice_logout_packet(const char *product_key, - const char* device_name, - uint32_t* msg_id) -{ -#define LOGOUT_PACKET_FMT "{\"id\":%d,\"version\":\"1.0\",\"params\":{\"productKey\":\"%s\",\"deviceName\":\"%s\"}}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - - /* sum the string length */ - len = strlen(LOGOUT_PACKET_FMT) + strlen(product_key) + strlen(device_name) + 12; - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - LOGOUT_PACKET_FMT, - id, - product_key, - device_name); - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - - -char *iotx_gateway_splice_login_packet(const char *product_key, - const char* device_name, - const char* clientId, - const char* timestamp, - const char* sign_method, - const char* sign, - const char* cleanSession, - uint32_t* msg_id) -{ -#define LOGIN_PACKET_FMT "{\"id\":%d,\"params\":{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\",\"timestamp\":\"%s\",\"signMethod\":\"%s\",\"sign\":\"%s\",\"cleanSession\":\"%s\"}}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - PARAMETER_NULL_CHECK_WITH_RESULT(clientId, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(timestamp, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign_method, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(cleanSession, NULL); - - /* sum the string length */ - len = strlen(LOGIN_PACKET_FMT) + strlen(product_key) + strlen(device_name) + strlen(clientId) - + strlen(timestamp) + strlen(sign_method) + strlen(sign) +strlen(cleanSession) + 12; - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - LOGIN_PACKET_FMT, - id, - product_key, - device_name, - clientId, - timestamp, - sign_method, - sign, - cleanSession); - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - -char *iotx_gateway_splice_topo_add_packet(const char *product_key, - const char* device_name, - const char* clientId, - const char* timestamp, - const char* sign_method, - const char* sign, - const char* method, - uint32_t* msg_id) -{ -#define TODO_ADD_PACKET_FMT "{\"id\":%d,\"params\":[{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\",\"timestamp\":\"%s\",\"signMethod\":\"%s\",\"sign\":\"%s\"}],\"method\":\"%s\"}" - - int len, ret; - char* msg = NULL; - uint32_t id = 0; - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - PARAMETER_NULL_CHECK_WITH_RESULT(clientId, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(timestamp, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign_method, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(sign, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(method, NULL); - - /* sum the string length */ - len = strlen(TODO_ADD_PACKET_FMT) + strlen(product_key) + strlen(device_name) + strlen(clientId) - + strlen(timestamp) + strlen(sign_method) + strlen(sign) +strlen(method) + 12; - MALLOC_MEMORY_WITH_RESULT(msg, len, NULL); - id = IOT_Gateway_Generate_Message_ID(); - ret = HAL_Snprintf(msg, - len, - TODO_ADD_PACKET_FMT, - id, - product_key, - device_name, - clientId, - timestamp, - sign_method, - sign, - method); - if (ret < 0) { - log_err("splice packet error!"); - LITE_free(msg); - return NULL; - } - - *msg_id = id; - - return msg; -} - -static void iotx_gateway_splice_device_cloud_id(char* device_cloud_id, - const char* product_key, - const char* device_name) -{ - PARAMETER_STRING_NULL_CHECK(product_key); - PARAMETER_STRING_NULL_CHECK(device_name); - PARAMETER_NULL_CHECK(device_cloud_id); - - HAL_Snprintf(device_cloud_id, DEVICE_ID_LEN, "%s.%s", product_key, device_name); -} - - -int iotx_gateway_calc_sign(const char* product_key, - const char* device_name, - const char* device_secret, - char* hmac_sigbuf, - const int hmac_buflen, - iotx_subdev_sign_method_types_t sign_method, - const char *client_id, - const char *timestamp_str) -{ - char signature[64]; - char hmac_source[256]; - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_secret, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(hmac_sigbuf, FAIL_RETURN); - PARAMETER_NULL_CHECK_WITH_RESULT(client_id, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(timestamp_str, FAIL_RETURN); - - memset(signature, 0, sizeof(signature)); - memset(hmac_source, 0, sizeof(hmac_source)); - HAL_Snprintf(hmac_source, - sizeof(hmac_source), - "clientId%s" "deviceName%s" "productKey%s" "timestamp%s", - client_id, - device_name, - product_key, - timestamp_str); - - if (sign_method == IOTX_SUBDEV_SIGN_METHOD_TYPE_SHA) { - utils_hmac_sha1(hmac_source, strlen(hmac_source), - signature, - device_secret, - strlen(device_secret)); - } else if (sign_method == IOTX_SUBDEV_SIGN_METHOD_TYPE_MD5) { - utils_hmac_md5(hmac_source, strlen(hmac_source), - signature, - device_secret, - strlen(device_secret)); - } - - memcpy(hmac_sigbuf, signature, hmac_buflen); - return 0; -} - -static int iotx_gateway_get_secure_mode(void) -{ -#ifdef MQTT_DIRECT -#ifdef IOTX_WITHOUT_TLS - return 3; /* MODE_TCP_DIRECT_PLAIN */ -#else - return 2; /* MODE_TLS_DIRECT */ -#endif /* IOTX_WITHOUT_TLS */ -#else /* MQTT_DIRECT */ -#ifdef IOTX_WITHOUT_TLS - return 0; /* MODE_TCP_GUIDER_PLAIN */ -#else - return -1; /* MODE_TLS_GUIDER */ -#endif /* IOTX_WITHOUT_TLS */ - -#endif /* MQTT_DIRECT */ - - return -1; /* MODE_TLS_GUIDER */ -} - - -void iotx_subdevice_calc_client_id(char* client_id, - const char* product_key, - const char* device_name) -{ - PARAMETER_NULL_CHECK(client_id); - PARAMETER_STRING_NULL_CHECK(product_key); - PARAMETER_STRING_NULL_CHECK(device_name); - - HAL_Snprintf(client_id, - IOT_SUBDEVICE_CLIENT_ID_LEN, - "%s.%s", - product_key, - device_name); - log_info("client_id %s", client_id); -} - -void iotx_gateway_calc_client_id(char* client_id, - const char* device_cloud_id, - const char* timestamp_str, - const char* sign_method) -{ - int secure_mode = iotx_gateway_get_secure_mode(); - char partner_id[64 + 16] = {0}; - char temp[64] = {0}; - - PARAMETER_NULL_CHECK(client_id); - PARAMETER_STRING_NULL_CHECK(device_cloud_id); - PARAMETER_STRING_NULL_CHECK(timestamp_str); - PARAMETER_STRING_NULL_CHECK(sign_method); - - /* partner_id */ - memset(temp, 0, sizeof(temp)); - HAL_GetPartnerID(temp); - if (strlen(temp)) { - HAL_Snprintf(partner_id, strlen(partner_id), ",partner_id=%s", temp); - } else { - strcpy(partner_id, ""); - } - - /* clientId */ - HAL_Snprintf(client_id, - CLIENT_ID_LEN, - "%s|securemode=%d,timestamp=%s,signmethod=%s,gw=0%s|", - device_cloud_id, - secure_mode, - timestamp_str, - sign_method, - partner_id); - log_info("client_id %s", client_id); -} - -int iotx_gateway_subscribe_unsubscribe_topic(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name, - const char* topic_fmt, - const char* params, - int is_subscribe) -{ - int ret = 0; - int yiled_count = 0; - char topic[GATEWAY_TOPIC_LEN_MAX] = {0}; - - PARAMETER_GATEWAY_CHECK(gateway, FAIL_RETURN); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic_fmt, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(params, FAIL_RETURN); - - /* topic */ - ret = HAL_Snprintf(topic, - GATEWAY_TOPIC_LEN_MAX, - topic_fmt, - product_key, - device_name, - params); - if (ret < 0) { - return FAIL_RETURN; - } - - if (is_subscribe) { - /* subscribe */ - #ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_t msg = {0}; - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_SUBSCRIBE; - msg.QoS = IOTX_MESSAGE_QOS0; - msg.URI = topic; - msg.URI_length = strlen(msg.URI); - msg.payload = NULL; - msg.payload_length = 0; - msg.response_handler = _response_handle; - msg.response_pcontext = gateway; - msg.content_type = IOTX_MESSAGE_CONTENT_TYPE_JSON; - msg.message_type = IOTX_MESSAGE_CONFIRMABLE; - - IOT_Cloud_Connection_Send_Message(gateway->mqtt, &msg); - - ret = 1; - #else /* SUBDEV_VIA_CLOUD_CONN */ - ret = IOT_MQTT_Subscribe(gateway->mqtt, - topic, - IOTX_MQTT_QOS0, - (iotx_mqtt_event_handle_func_fpt)iotx_gateway_event_handle, - gateway); - #endif /* SUBDEV_VIA_CLOUD_CONN */ - } else { - /* unsubscribe */ - #ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_t msg = {0}; - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_UNSUBSCRIBE; - msg.URI = topic; - msg.URI_length = strlen(msg.URI); - msg.payload = NULL; - msg.payload_length = 0; - msg.response_handler = _response_handle; - msg.response_pcontext = gateway; - msg.content_type = IOTX_MESSAGE_CONTENT_TYPE_JSON; - msg.message_type = IOTX_MESSAGE_CONFIRMABLE; - - if (SUCCESS_RETURN == IOT_Cloud_Connection_Send_Message(gateway->mqtt, &msg)) { - ret = -4; /* special value */ - } - #else /* SUBDEV_VIA_CLOUD_CONN */ - ret = IOT_MQTT_Unsubscribe(gateway->mqtt, topic); - #endif /* SUBDEV_VIA_CLOUD_CONN */ - } - -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(gateway->gateway_data.lock_sync_enter); - HAL_MutexLock(gateway->gateway_data.lock_sync); -#endif - gateway->gateway_data.sync_status = ret; -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(gateway->gateway_data.lock_sync); -#endif - - while (ret == gateway->gateway_data.sync_status) { - if (yiled_count > IOT_GATEWAY_YIELD_MAX_COUNT) { - log_info("yiled max count, time out"); -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(gateway->gateway_data.lock_sync_enter); -#endif - return FAIL_RETURN; - } - - IOT_Gateway_Yield(gateway, 200); - yiled_count++; - } -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(gateway->gateway_data.lock_sync_enter); -#endif - - if (0 == gateway->gateway_data.sync_status) { - log_info("subscribe or unsubscribe [%s] successfully", topic); - } else { - log_info("subscribe or unsubscribe [%s] error!", topic); - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - -int iotx_gateway_subscribe_unsubscribe_default(iotx_gateway_pt gateway, - int is_subscribe) -{ - iotx_device_info_pt pdevice_info = iotx_device_info_get(); - - PARAMETER_GATEWAY_CHECK(gateway, FAIL_RETURN); - - /* register_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_SUB_FMT, - "register_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* unregister_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_SUB_FMT, - "unregister_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* topo_add_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_TOPO_FMT, - "add_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* topo_delete_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_TOPO_FMT, - "delete_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* topo_get_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_TOPO_FMT, - "get_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* config_get_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_CONFIG_FMT, - "get_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* list_found_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_LIST_FOUND_FMT, - "found_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* login_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_COMBINE_FMT, - "login_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* logout_reply */ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SESSION_COMBINE_FMT, - "logout_reply", - is_subscribe)){ - return FAIL_RETURN; - } - - /* RRPC request*/ - if (FAIL_RETURN == iotx_gateway_subscribe_unsubscribe_topic(gateway, - pdevice_info->product_key, - pdevice_info->device_name, - TOPIC_SYS_RRPC_FMT, - "request", - is_subscribe)){ - return FAIL_RETURN; - } - - return SUCCESS_RETURN; -} - -iotx_subdevice_session_pt iotx_subdevice_find_session(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name) -{ - iotx_subdevice_session_pt session = NULL; - - PARAMETER_GATEWAY_CHECK(gateway, NULL); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - - session = gateway->session_list; - - /* session is exist */ - while(session) { - if (0 == strncmp(session->product_key, product_key, strlen(product_key)) && - 0 == strncmp(session->device_name, device_name, strlen(device_name))) { - return session; - } - session = session->next; - } - - return NULL; -} - - -iotx_subdevice_session_pt iotx_subdevice_add_session(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name, - const char* device_cloud_secret, - const char* sign, - const char* timestamp, - const char* client_id, - iotx_subdev_sign_method_types_t sign_method_type, - iotx_subdev_clean_session_types_t clean_session_type) -{ - iotx_subdevice_session_pt session = NULL; - - PARAMETER_GATEWAY_CHECK(gateway, NULL); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, NULL); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, NULL); - - /* create a new subdev session */ - MALLOC_MEMORY_WITH_RESULT(session, sizeof(iotx_subdevice_session_t), NULL); - - /* add session to list */ - session->next = gateway->session_list; - gateway->session_list = session; - -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexLock(session->lock_generic); -#endif - strncpy(session->product_key, product_key, strlen(product_key)); - strncpy(session->device_name, device_name, strlen(device_name)); - if (device_cloud_secret) - strncpy(session->device_cloud_secret, device_cloud_secret, strlen(device_cloud_secret)); - if (timestamp) - strncpy(session->timestamp, timestamp, strlen(timestamp)); - if (sign) - strncpy(session->sign, sign, strlen(sign)); - if (client_id) - strncpy(session->client_id, client_id, strlen(client_id)); - session->sign_method = sign_method_type; - session->clean_session = clean_session_type; - session->dynamic_register = 0; - iotx_gateway_splice_device_cloud_id(session->device_cloud_id, product_key, device_name); -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(session->lock_generic); - HAL_MutexLock(session->lock_status); -#endif - session->session_status = IOTX_SUBDEVICE_SEESION_STATUS_INIT; -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexUnlock(session->lock_status); -#endif - - return session; -} - -int iotx_subdevice_remove_session(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name) -{ - iotx_subdevice_session_pt cur_session = NULL; - iotx_subdevice_session_pt pre_session = NULL; - - PARAMETER_GATEWAY_CHECK(gateway, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(product_key, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(device_name, FAIL_RETURN); - - pre_session = cur_session = gateway->session_list; - - if (NULL == cur_session) { - log_err("session list is empty"); - return SUCCESS_RETURN; - } - - /* session is exist */ - while(cur_session) { - if (0 == strncmp(cur_session->product_key, product_key, strlen(product_key)) && - 0 == strncmp(cur_session->device_name, device_name, strlen(device_name)) ) { - if (cur_session == gateway->session_list) { - gateway->session_list = cur_session->next; - } else { - pre_session->next = cur_session->next; - } - #ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - HAL_MutexDestroy(cur_session->lock_generic); - HAL_MutexDestroy(cur_session->lock_status); - #endif - LITE_free(cur_session); - return SUCCESS_RETURN; - } - pre_session = cur_session; - cur_session = cur_session->next; - } - - return FAIL_RETURN; -} - - -int iotx_gateway_publish_sync(iotx_gateway_t* gateway, - iotx_mqtt_qos_t qos, - const char* topic, - const char* packet, - uint32_t message_id, - iotx_common_reply_data_pt reply_data, - iotx_gateway_publish_t publish_type) -{ -#ifdef SUBDEV_VIA_CLOUD_CONN - iotx_cloud_connection_msg_t msg; -#else - iotx_mqtt_topic_info_t topic_msg; -#endif - - int yiled_count = 0; - - PARAMETER_GATEWAY_CHECK(gateway, FAIL_RETURN); - - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(topic, FAIL_RETURN); - PARAMETER_STRING_NULL_CHECK_WITH_RESULT(packet, FAIL_RETURN); - -#ifdef SUBDEV_VIA_CLOUD_CONN - memset(&msg, 0x0, sizeof(iotx_cloud_connection_msg_t)); - msg.type = IOTX_CLOUD_CONNECTION_MESSAGE_TYPE_PUBLISH; - msg.QoS = (iotx_message_qos_t)qos; - msg.URI = (char*)topic; - msg.URI_length = strlen(msg.URI); - msg.payload = (char*)packet; - msg.payload_length = strlen(packet); - msg.content_type = IOTX_MESSAGE_CONTENT_TYPE_JSON; - msg.message_type = IOTX_MESSAGE_CONFIRMABLE; - msg.response_handler = _response_handle; - msg.response_pcontext = gateway; - if (FAIL_RETURN == IOT_Cloud_Connection_Send_Message(gateway->mqtt, &msg)) { - return FAIL_RETURN; - } - -#else - memset(&topic_msg, 0x0, sizeof(iotx_mqtt_topic_info_t)); - topic_msg.qos = qos; - topic_msg.retain = 0; - topic_msg.dup = 0; - topic_msg.payload = (void *)packet; - topic_msg.payload_len = strlen(packet); - topic_msg.packet_id = 0; - - if (IOT_MQTT_Publish(gateway->mqtt, topic, &topic_msg) < 0) { - log_err("publish failed\n"); - return FAIL_RETURN; - } -#endif - - log_info("iotx_gateway_publish_sync topic [%s]\n", topic); - - /* sync id */ - reply_data->id = message_id; - - /* wait for response */ - while (message_id == reply_data->id) { - if (yiled_count > IOT_GATEWAY_YIELD_MAX_COUNT) { - log_info("yiled max count, time out"); - return FAIL_RETURN; - } - - IOT_Gateway_Yield(gateway, 200); - yiled_count++; - } - - if (0 == reply_data->id) { - if (200 == reply_data->code) { - log_info("%s successfully", topic); - } else { - log_info("%s error!code:%d", topic, reply_data->code); - return (~reply_data->code + 1); - } - } else { - log_info("%s time out!", topic); - return ERROR_REPLY_TIMEOUT; - } - - return SUCCESS_RETURN; -} - - -int iotx_subdevice_set_session_status(iotx_subdevice_session_pt session, iotx_subdevice_session_status_t status) -{ - PARAMETER_NULL_CHECK_WITH_RESULT(session, FAIL_RETURN); - - session->session_status = status; - - return SUCCESS_RETURN; -} - -iotx_subdevice_session_status_t iotx_subdevice_get_session_status(iotx_subdevice_session_pt session) -{ - PARAMETER_NULL_CHECK_WITH_RESULT(session, IOTX_SUBDEVICE_SEESION_STATUS_MAX); - - return session->session_status; -} - -int iotx_subdevice_set_session_dynamic_register(iotx_subdevice_session_pt session) -{ - PARAMETER_NULL_CHECK_WITH_RESULT(session, FAIL_RETURN); - - session->dynamic_register = 1; - - return SUCCESS_RETURN; -} - -int iotx_subdevice_get_session_dynamic_register(iotx_subdevice_session_pt session) -{ - PARAMETER_NULL_CHECK_WITH_RESULT(session, FAIL_RETURN); - - return session->dynamic_register; -} - - diff --git a/iotkit-embedded/src/subdev/iotx_subdev_common.h b/iotkit-embedded/src/subdev/iotx_subdev_common.h deleted file mode 100644 index 49b42ac..0000000 --- a/iotkit-embedded/src/subdev/iotx_subdev_common.h +++ /dev/null @@ -1,325 +0,0 @@ - -#ifndef SRC_SUBDEVICE_CMP_UTIL_H_ -#define SRC_SUBDEVICE_CMP_UTIL_H_ - - -/* Subdevice seesion status */ -typedef enum IOTX_SUBDEVICE_SESSION_STATUS_CODES { - /* Initial */ - IOTX_SUBDEVICE_SEESION_STATUS_INIT, - - /* Register */ - IOTX_SUBDEVICE_SEESION_STATUS_REGISTER, - - /* Login */ - IOTX_SUBDEVICE_SEESION_STATUS_LOGIN, - - /* Logout */ - IOTX_SUBDEVICE_SEESION_STATUS_LOGOUT, - - /* Enable */ - IOTX_SUBDEVICE_SEESION_STATUS_ENABLE, - - /* Disalbe */ - IOTX_SUBDEVICE_SEESION_STATUS_DISABLE, - - /* Unregister */ - IOTX_SUBDEVICE_SEESION_STATUS_UNREGISTER, - - /* Maximum number of seesion status type */ - IOTX_SUBDEVICE_SEESION_STATUS_MAX -}iotx_subdevice_session_status_t; - -/* The structure of subdevice session */ -typedef struct iotx_subdevice_session_st{ - char device_cloud_id[DEVICE_ID_LEN]; - char device_cloud_secret[DEVICE_SECRET_LEN]; - char product_key[PRODUCT_KEY_LEN]; - char device_name[DEVICE_NAME_LEN]; - char timestamp[20]; - char sign[41]; - char client_id[IOT_SUBDEVICE_CLIENT_ID_LEN]; - iotx_subdev_sign_method_types_t sign_method; /* HmacSha1, HmacMd5 */ - iotx_subdev_clean_session_types_t clean_session; /* ture, false */ - iotx_subdevice_session_status_t session_status; - rrpc_request_callback rrpc_callback; -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - void* lock_generic; - void* lock_status; -#endif - int dynamic_register; - struct iotx_subdevice_session_st* next; -} iotx_subdevice_session_t, *iotx_subdevice_session_pt; - - -/* The structure of common reply data */ -typedef struct iotx_common_reply_data_st{ - uint32_t id; - uint32_t code; - iotx_subdevice_session_pt session; /* subdevice session */ -}iotx_common_reply_data_t,*iotx_common_reply_data_pt; - - -/* The structure of gateway data */ -typedef struct iotx_gateway_data_st { - uint32_t sync_status; - iotx_common_reply_data_t login_reply; - iotx_common_reply_data_t logout_reply; - iotx_common_reply_data_t topo_add_reply; - iotx_common_reply_data_t topo_delete_reply; - iotx_common_reply_data_t topo_get_reply; - iotx_common_reply_data_t config_get_reply; - iotx_common_reply_data_t list_found_reply; - iotx_common_reply_data_t register_reply; - iotx_common_reply_data_t unregister_reply; - char register_message[REPLY_MESSAGE_LEN_MAX]; - char topo_get_message[REPLY_MESSAGE_LEN_MAX]; - char config_get_message[REPLY_MESSAGE_LEN_MAX]; - rrpc_request_callback rrpc_callback; -#ifdef IOT_GATEWAY_SUPPORT_MULTI_THREAD - void* lock_sync; - void* lock_sync_enter; -#endif -} iotx_gateway_data_t, *iotx_gateway_data_pt; - - -/* The structure of gateway context */ -typedef struct iotx_gateway_st { - void *mqtt; - iotx_subdevice_session_pt session_list; - iotx_gateway_data_t gateway_data; - /* If there is another user want to handle the MQTT event, - * must set the event_handler and event pcontext */ - void* event_pcontext; - iotx_subdev_event_handle_func_fpt event_handler; - int is_construct; -} iotx_gateway_t, *iotx_gateway_pt; - -extern iotx_gateway_pt g_gateway_subdevice_t; - -#define MALLOC_MEMORY(buffer, length) \ - do { \ - if (buffer) \ - LITE_free(buffer); \ - (buffer) = (void*)LITE_malloc(length); \ - if (NULL == (buffer)) { \ - log_err("Not enough memory"); \ - return; \ - } \ - memset((buffer), 0x0, (length)); \ - } while(0) - -#define MALLOC_MEMORY_WITH_RESULT(buffer, length, result) \ - do { \ - if (buffer) \ - LITE_free(buffer); \ - (buffer) = (void*)LITE_malloc(length); \ - if (NULL == (buffer)) { \ - log_err("Not enough memory"); \ - return (result); \ - } \ - memset((buffer), 0x0, (length)); \ - } while(0) - -#define MALLOC_MEMORY_WITH_FREE(buffer, length, free_buffer) \ - do { \ - if (buffer) \ - LITE_free(buffer); \ - (buffer) = (void*)LITE_malloc(length); \ - if (NULL == (buffer)) { \ - log_err("Not enough memory"); \ - LITE_free(free_buffer); \ - return; \ - } \ - memset((buffer), 0x0, (length)); \ - } while(0) - -#define MALLOC_MEMORY_WITH_FREE_AND_RESULT(buffer, length, free_buffer, result) \ - do { \ - if (buffer) \ - LITE_free(buffer); \ - (buffer) = (void*)LITE_malloc(length); \ - if (NULL == (buffer)) { \ - log_err("Not enough memory"); \ - LITE_free(free_buffer); \ - return (result); \ - } \ - memset((buffer), 0x0, (length)); \ - } while(0) - -#define PARAMETER_NULL_CHECK(param) \ - do { \ - if ((param) == NULL) { \ - log_info("param error"); \ - return; \ - } \ - } while(0) - -#define PARAMETER_NULL_CHECK_WITH_RESULT(param, result) \ - do { \ - if ((param) == NULL) { \ - log_info("param error"); \ - return (result); \ - } \ - } while(0) - -#define PARAMETER_STRING_NULL_CHECK(ptr) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, (ptr)); \ - return; \ - } \ - if (0 == strlen((ptr))) { \ - log_err("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return; \ - } \ - } while(0) - -#define PARAMETER_STRING_NULL_CHECK_WITH_RESULT(ptr, result) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, (ptr)); \ - return (result); \ - } \ - if (0 == strlen((ptr))) { \ - log_err("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return (result); \ - } \ - } while(0) - -#define PARAMETER_GATEWAY_CHECK(gateway_t, result) \ - do { \ - if ((gateway_t) == NULL) { \ - log_info("param error"); \ - return (result); \ - } \ - if ((gateway_t) != g_gateway_subdevice_t) { \ - log_info("param error"); \ - return (result); \ - } \ - if ((gateway_t)->mqtt == NULL) { \ - log_info("param error"); \ - return (result); \ - } \ - } while(0) - -typedef enum IOTX_GATEWAY_PUBLISH_TYPE { - IOTX_GATEWAY_PUBLISH_REGISTER, - IOTX_GATEWAY_PUBLISH_UNREGISTER, - IOTX_GATEWAY_PUBLISH_TOPO_ADD, - IOTX_GATEWAY_PUBLISH_TOPO_DELETE, - IOTX_GATEWAY_PUBLISH_TOPO_GET, - IOTX_GATEWAY_PUBLISH_CONFIG_GET, - IOTX_GATEWAY_PUBLISH_LIST_FOUND, - IOTX_GATEWAY_PUBLISH_LOGIN, - IOTX_GATEWAY_PUBLISH_LOGOUT, - - IOTX_GATEWAY_PUBLISH_MAX -}iotx_gateway_publish_t; - -iotx_subdevice_session_pt iotx_subdevice_find_session(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name); - -iotx_subdevice_session_pt iotx_subdevice_add_session(iotx_gateway_pt gateway, - const char * product_key, - const char* device_name, - const char* device_cloud_secret, - const char* sign, - const char* timestamp, - const char* client_id, - iotx_subdev_sign_method_types_t sign_method_type, - iotx_subdev_clean_session_types_t clean_session_type); - -int iotx_subdevice_remove_session(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name); - -int iotx_gateway_subscribe_unsubscribe_topic(iotx_gateway_pt gateway, - const char* product_key, - const char* device_name, - const char* topic_fmt, - const char* params, - int is_subscribe); - -int iotx_gateway_subscribe_unsubscribe_default(iotx_gateway_pt gateway, - int is_subscribe); - -/* topo/delete register unregister*/ -char *iotx_gateway_splice_common_packet(const char *product_key, - const char* device_name, - const char* method, - uint32_t* msg_id); - - -char *iotx_gateway_splice_topo_get_packet(uint32_t* msg_id); - -char *iotx_gateway_splice_config_get_packet(uint32_t* msg_id); - - -char *iotx_gateway_splice_topo_add_packet(const char *product_key, - const char* device_name, - const char* clientId, - const char* timestamp, - const char* sign_method, - const char* sign, - const char* method, - uint32_t* msg_id); - - -char *iotx_gateway_splice_login_packet(const char *product_key, - const char* device_name, - const char* clientId, - const char* timestamp, - const char* sign_method, - const char* sign, - const char* cleanSession, - uint32_t* msg_id); - -char *iotx_gateway_splice_logout_packet(const char *product_key, - const char* device_name, - uint32_t* msg_id); - - -int iotx_gateway_calc_sign(const char* prodect_key, - const char* device_name, - const char* device_secret, - char* hmac_sigbuf, - const int hmac_buflen, - iotx_subdev_sign_method_types_t sign_method, - const char *client_id, - const char *timestamp_str); - -void iotx_subdevice_calc_client_id(char* client_id, - const char* product_key, - const char* device_name); - -void iotx_gateway_calc_client_id(char* client_id, - const char* device_cloud_id, - const char* timestamp_str, - const char* sign_method); - -int iotx_gateway_publish_sync(iotx_gateway_t* gateway, - iotx_mqtt_qos_t qos, - const char* topic, - const char* packet, - uint32_t message_id, - iotx_common_reply_data_pt reply_data, - iotx_gateway_publish_t publish_type); - -int iotx_subdevice_set_session_status(iotx_subdevice_session_pt session, - iotx_subdevice_session_status_t status); - -iotx_subdevice_session_status_t iotx_subdevice_get_session_status(iotx_subdevice_session_pt session); - - -int iotx_subdevice_set_session_dynamic_register(iotx_subdevice_session_pt session); - -int iotx_subdevice_get_session_dynamic_register(iotx_subdevice_session_pt session); - -#ifdef SUBDEV_VIA_CLOUD_CONN -void _response_handle(void *pcontext, void *pconnection, iotx_cloud_connection_msg_rsp_pt msg); -#endif /* SUBDEV_VIA_CLOUD_CONN */ - - -#endif /* SRC_SUBDEVICE_CMP_UTIL_H_ */ diff --git a/iotkit-embedded/src/system/iot.mk b/iotkit-embedded/src/system/iot.mk deleted file mode 100644 index 1230ed7..0000000 --- a/iotkit-embedded/src/system/iot.mk +++ /dev/null @@ -1,5 +0,0 @@ -LIBA_TARGET := libiot_system.a -HDR_REFS := src - -PKG_SOURCE := iotkit-system.git -PKG_UPSTREAM := git@gitlab.alibaba-inc.com:iot-middleware/iotkit-system.git diff --git a/iotkit-embedded/src/system/iotkit-system/class_interface.h b/iotkit-embedded/src/system/iotkit-system/class_interface.h deleted file mode 100644 index 5bef20f..0000000 --- a/iotkit-embedded/src/system/iotkit-system/class_interface.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __CLASS_INTERFACE_H__ -#define __CLASS_INTERFACE_H__ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -/* base-class define */ -/* abstract class */ -typedef struct { - size_t _size; - const char* _class_name; - void* (*ctor)(void* _self, va_list* params); - void* (*dtor)(void* _self); -} abstract_class_t; - - -/* new & delete */ -extern void* new_object(const void* _class, ...); -extern void delete_object(void* _class); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CLASS_INTERFACE_H__ */ \ No newline at end of file diff --git a/iotkit-embedded/src/system/iotkit-system/guider_internal.h b/iotkit-embedded/src/system/iotkit-system/guider_internal.h deleted file mode 100644 index f20424d..0000000 --- a/iotkit-embedded/src/system/iotkit-system/guider_internal.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __GUIDER_INTERNAL_H__ -#define __GUIDER_INTERNAL_H__ - -#include -#include -#include -#include - -#include "iot_import.h" - -#include "lite-log.h" -#include "lite-utils.h" -#include "utils_md5.h" -#include "utils_base64.h" -#include "utils_hmac.h" -#include "utils_httpc.h" -#include "lite-system.h" - -#define GUIDER_IOT_ID_LEN (256) -#define GUIDER_IOT_TOKEN_LEN (512) -#define GUIDER_DEFAULT_TS_STR "2524608000000" - -#define CONN_SECMODE_LEN (32) - -#define GUIDER_SIGN_LEN (256) - -#define GUIDER_TS_LEN (16) -#define GUIDER_URL_LEN (256) - -#define GUIDER_DEVCODE_LEN (256) -#define GUIDER_URLENCODE_LEN (256) - -#define GUIDER_DIRECT_DOMAIN_CN "iot-as-mqtt.cn-shanghai.aliyuncs.com" -#define GUIDER_DIRECT_DOMAIN_SG "iot-as-mqtt.ap-southeast-1.aliyuncs.com" -#define GUIDER_DIRECT_DOMAIN_JP "iot-as-mqtt.ap-northeast-1.aliyuncs.com" -#define GUIDER_DIRECT_DOMAIN_US "iot-as-mqtt.us-west-1.aliyuncs.com" -#define GUIDER_DIRECT_DOMAIN_GER "iot-as-mqtt.eu-central-1.aliyuncs.com" - -#define SHA_METHOD "hmacsha1" -#define MD5_METHOD "hmacmd5" - -/* By default we use hmac-sha1 algorithm for hmac in PK/DN/DS case */ -#ifndef USING_SHA1_IN_HMAC -#define USING_SHA1_IN_HMAC (1) -#endif /* USING_SHA1_IN_HMAC */ - -typedef enum _SECURE_MODE { - MODE_TLS_GUIDER = -1, - MODE_TCP_GUIDER_PLAIN = 0, - MODE_TCP_GUIDER_ID2_ENCRYPT = 1, - MODE_TLS_DIRECT = 2, - MODE_TCP_DIRECT_PLAIN = 3, - MODE_TCP_DIRECT_ID2_ENCRYPT = 4, - MODE_TLS_GUIDER_ID2_ENCRYPT = 5, - MODE_TLS_DIRECT_ID2_ENCRYPT = 7, - MODE_ITLS_DNS_ID2 = 8, -} SECURE_MODE; - -extern const char *secmode_str[]; - -SECURE_MODE _secure_mode_num(void); -void _ident_partner(char *buf, int len); -void _ident_module(char *buf, int len); -int _fill_conn_string(char *dst, int len, const char *fmt, ...); -void guider_print_dev_guider_info(iotx_device_info_pt dev, - char *partner_id, - char *module_id, - char *guider_url, - int secure_mode, - char *time_stamp, - char *guider_sign, - char *id2, - char *dev_code); -void guider_print_conn_info(iotx_conn_info_pt conn); - -#ifndef MQTT_DIRECT -int _http_response(char *payload, - const int payload_len, - const char *request_string, - const char *url, - const int port_num, - const char *pkey); -#endif - -#endif /* __GUIDER_INTERNAL_H__ */ diff --git a/iotkit-embedded/src/system/iotkit-system/lite-system.h b/iotkit-embedded/src/system/iotkit-system/lite-system.h deleted file mode 100644 index 43c3e19..0000000 --- a/iotkit-embedded/src/system/iotkit-system/lite-system.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _IOTX_AUTH_H_ -#define _IOTX_AUTH_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -#include "iot_import.h" -#include "iot_export.h" - -#define MQTT_SDK_VERSION "2.0" - - -int iotx_guider_authenticate(void); -#ifdef MQTT_ID2_AUTH -/* func name: iotx_guider_id2_authenticate - * description: used for id2 authentication - * intput : - * output : - * return : int - * 0 success - * -1 error - */ -int iotx_guider_id2_authenticate(void); -#endif - -int iotx_device_info_init(void); - -int iotx_device_info_set( - const char *product_key, - const char *device_name, - const char *device_secret); - -iotx_device_info_pt iotx_device_info_get(void); -iotx_conn_info_pt iotx_conn_info_get(void); - - -#include - - -#define MIDREPORT_PAYLOAD_LEN (62 + PID_STRLEN_MAX + MID_STRLEN_MAX + 32 +1) -#define MIDREPORT_REQID_LEN (PRODUCT_KEY_LEN + DEVICE_NAME_LEN + 6) - -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); - - -const char *iotx_ca_get(void); - -#if defined(__cplusplus) -} -#endif -#endif diff --git a/iotkit-embedded/src/system/iotkit-system/sdk-impl_internal.h b/iotkit-embedded/src/system/iotkit-system/sdk-impl_internal.h deleted file mode 100644 index 6df38be..0000000 --- a/iotkit-embedded/src/system/iotkit-system/sdk-impl_internal.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef __SDK_IMPL_INTERNAL__ -#define __SDK_IMPL_INTERNAL__ -#if defined(__cplusplus) -extern "C" { -#endif - -#include "iot_import.h" -#include "iot_export.h" - -#include "lite-log.h" -#include "lite-utils.h" -#include "lite-system.h" - -#define POINTER_SANITY_CHECK(ptr, err) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, ptr); \ - return (err); \ - } \ - } while(0) - -#define STRING_PTR_SANITY_CHECK(ptr, err) \ - do { \ - if (NULL == (ptr)) { \ - log_err("Invalid argument, %s = %p", #ptr, (ptr)); \ - return (err); \ - } \ - if (0 == strlen((ptr))) { \ - log_err("Invalid argument, %s = '%s'", #ptr, (ptr)); \ - return (err); \ - } \ - } while(0) - -#if defined(__cplusplus) -} -#endif -#endif /* __SDK_IMPL_INTERNAL__ */ diff --git a/iotkit-embedded/src/system/iotkit-system/src/class_interface.c b/iotkit-embedded/src/system/iotkit-system/src/class_interface.c deleted file mode 100644 index ede7c43..0000000 --- a/iotkit-embedded/src/system/iotkit-system/src/class_interface.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include "class_interface.h" -#include "lite-utils.h" - - -void* new_object(const void* _class, ...) -{ - const abstract_class_t* ab_class = _class; - - void* p = LITE_calloc(1, ab_class->_size); - - if (p == NULL) return NULL; - - *(const abstract_class_t**)p = ab_class; - - if (ab_class->ctor) { - va_list params; - - va_start(params, _class); - p = ab_class->ctor(p, ¶ms); - va_end(params); - } - - printf("%s %s @%p\n", ab_class->_class_name, "constructed", p); - - return p; -} - -void delete_object(void* _object) -{ - const abstract_class_t** ab_class = _object; - - if (_object && *ab_class && (*ab_class)->dtor) { - _object = (*ab_class)->dtor(_object); - - printf("%s %s @%p\n", (*ab_class)->_class_name, "destructed", _object); - - LITE_free(_object); - } -} \ No newline at end of file diff --git a/iotkit-embedded/src/system/iotkit-system/src/guider.c b/iotkit-embedded/src/system/iotkit-system/src/guider.c deleted file mode 100644 index 3622cc3..0000000 --- a/iotkit-embedded/src/system/iotkit-system/src/guider.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "guider_internal.h" -#include "utils_epoch_time.h" - -#ifndef CONFIG_GUIDER_AUTH_TIMEOUT - #define CONFIG_GUIDER_AUTH_TIMEOUT (10 * 1000) -#endif - -const char *secmode_str[] = { - "TCP + Guider + Plain", - "TCP + Guider + ID2-Crypto", - "TLS + Direct", - "TCP + Direct + Plain", - "TCP + Direct + ID2-Crypto", - "TLS + Guider + ID2-Authenticate", - "", - "TLS + Direct + ID2-Crypto", - "ITLS + Direct + ID2-Authenticate" -}; - - -/* Domain type could be modified in runtime, dafault value 0 is shanghai demain. */ -int g_domain_type = 0; - -/* Set up Domain */ -void IOT_SetupDomain(int domain_type) -{ - g_domain_type = domain_type; -} - -/* Keep this function, as iotx_cmp_api.c may invoke it */ -void guider_set_domain_type(int domain_type) -{ - -} - -char* guider_get_domain() -{ - if (0 == g_domain_type) - return GUIDER_DIRECT_DOMAIN_CN; - - else if (1 == g_domain_type) - return GUIDER_DIRECT_DOMAIN_SG; - - else if (2 == g_domain_type) - return GUIDER_DIRECT_DOMAIN_JP; - - else if (3 == g_domain_type) - return GUIDER_DIRECT_DOMAIN_US; - - else if (4 == g_domain_type) - return GUIDER_DIRECT_DOMAIN_GER; - - return NULL; -} - - -static int _calc_hmac_signature( - char *hmac_sigbuf, - const int hmac_buflen, - const char *timestamp_str) -{ - char signature[64]; - char hmac_source[512]; - int rc = -1; - iotx_device_info_pt dev; - - dev = iotx_device_info_get(); - LITE_ASSERT(dev); - - memset(signature, 0, sizeof(signature)); - memset(hmac_source, 0, sizeof(hmac_source)); - rc = HAL_Snprintf(hmac_source, - sizeof(hmac_source), - "clientId%s" "deviceName%s" "productKey%s" "timestamp%s", - dev->device_id, - dev->device_name, - dev->product_key, - timestamp_str); - LITE_ASSERT(rc < sizeof(hmac_source)); - -#if USING_SHA1_IN_HMAC - utils_hmac_sha1(hmac_source, strlen(hmac_source), - signature, - dev->device_secret, - strlen(dev->device_secret)); -#else - utils_hmac_md5(hmac_source, strlen(hmac_source), - signature, - dev->device_secret, - strlen(dev->device_secret)); -#endif - - memcpy(hmac_sigbuf, signature, hmac_buflen); - return 0; -} - -#ifndef MQTT_DIRECT -int _http_response(char *payload, - const int payload_len, - const char *request_string, - const char *url, - const int port_num, - const char *pkey - ) -{ -#define HTTP_POST_MAX_LEN (1024) -#define HTTP_RESP_MAX_LEN (1024) - - int len = 0; - int ret = -1; - char *requ_payload = NULL; - char *resp_payload = NULL; - - httpclient_t httpc; - httpclient_data_t httpc_data; - - memset(&httpc, 0, sizeof(httpclient_t)); - memset(&httpc_data, 0, sizeof(httpclient_data_t)); - - httpc.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n"; - - requ_payload = (char *)LITE_malloc(HTTP_POST_MAX_LEN); - if (NULL == requ_payload) { - log_err("Allocate HTTP request buf failed!"); - return ERROR_MALLOC; - } - memset(requ_payload, 0, HTTP_POST_MAX_LEN); - - len = HAL_Snprintf(requ_payload, - HTTP_POST_MAX_LEN, - "%s", - request_string); - LITE_ASSERT(len < HTTP_POST_MAX_LEN); - log_debug("requ_payload: \r\n\r\n%s\r\n", requ_payload); - - resp_payload = (char *)LITE_malloc(HTTP_RESP_MAX_LEN); - if (!resp_payload) { - goto RETURN; - } - LITE_ASSERT(resp_payload); - memset(resp_payload, 0, HTTP_RESP_MAX_LEN); - - httpc_data.post_content_type = "application/x-www-form-urlencoded;charset=utf-8"; - httpc_data.post_buf = requ_payload; - httpc_data.post_buf_len = strlen(requ_payload); - httpc_data.response_buf = resp_payload; - httpc_data.response_buf_len = HTTP_RESP_MAX_LEN; - - ret = httpclient_common(&httpc, - url, - port_num, - pkey, - HTTPCLIENT_POST, - CONFIG_GUIDER_AUTH_TIMEOUT, - &httpc_data); - if (ret != 0) { - goto RETURN; - } - - memcpy(payload, httpc_data.response_buf, payload_len); - log_debug("PAYLOAD: %s", payload); - -RETURN: - if (requ_payload) { - LITE_free(requ_payload); - requ_payload = NULL; - } - if (resp_payload) { - LITE_free(resp_payload); - resp_payload = NULL; - } - - return 0; -} - -#endif /* #ifndef MQTT_DIRECT */ - -void _ident_partner(char *buf, int len) -{ - char tmp[PID_STRLEN_MAX] = {0}; - - memset(tmp, 0, sizeof(tmp)); - HAL_GetPartnerID(tmp); - if (strlen(tmp)) { - HAL_Snprintf(buf, len, ",partner_id=%s", tmp); - } else { - strcpy(buf, ""); - } - - return; -} - -void _ident_module(char *buf, int len) -{ - char tmp[MID_STRLEN_MAX] = {0}; - - memset(tmp, 0, sizeof(tmp)); - HAL_GetModuleID(tmp); - if (strlen(tmp)) { - HAL_Snprintf(buf, len, ",module_id=%s", tmp); - } else { - strcpy(buf, ""); - } - - return; -} - -int _fill_conn_string(char *dst, int len, const char *fmt, ...) -{ - int rc = -1; - va_list ap; - char *ptr = NULL; - - va_start(ap, fmt); - rc = HAL_Vsnprintf(dst, len, fmt, ap); - va_end(ap); - LITE_ASSERT(rc <= len); - - ptr = strstr(dst, "||"); - if (ptr) { - *ptr = '\0'; - } - - /* log_debug("dst(%d) = %s", rc, dst); */ - return 0; -} - -void guider_print_conn_info(iotx_conn_info_pt conn) -{ - log_debug("%s", "-----------------------------------------"); - log_debug("%16s : %-s", "Host", conn->host_name); - log_debug("%16s : %d", "Port", conn->port); - /*log_debug("%16s : %-s", "UserName", conn->username); - log_debug("%16s : %-s", "PassWord", conn->password);*/ /* remove */ - log_debug("%16s : %-s", "ClientID", conn->client_id); - if (conn->pub_key) { - log_debug("%16s : %p ('%.16s ...')", "TLS PubKey", conn->pub_key, conn->pub_key); - } - - log_debug("%s", "-----------------------------------------"); -} - -void guider_print_dev_guider_info(iotx_device_info_pt dev, - char *partner_id, - char *module_id, - char *guider_url, - int secure_mode, - char *time_stamp, - char *guider_sign, - char *id2, - char *dev_code) -{ - log_debug("%s", "...................................................."); - log_debug("%20s : %-s", "ProductKey", dev->product_key); - log_debug("%20s : %-s", "DeviceName", dev->device_name); - log_debug("%20s : %-s", "DeviceID", dev->device_id); - /*log_debug("%20s : %-s", "DeviceSecret", dev->device_secret);*/ /* remove */ - log_debug("%s", "...................................................."); - log_debug("%20s : %-s", "PartnerID Buf", partner_id); - log_debug("%20s : %-s", "ModuleID Buf", module_id); - log_debug("%20s : %s", "Guider URL", guider_url); - if (secure_mode > 0) { - log_debug("%20s : %d (%s)", "Guider SecMode", secure_mode, secmode_str[secure_mode]); - } - log_debug("%20s : %s", "Guider Timestamp", time_stamp); - log_debug("%s", "...................................................."); - /*log_debug("%20s : %s", "Guider Sign", guider_sign);*/ /* remove */ - if (id2 != NULL) { - log_debug("%20s : %s", "Guider ID2", id2); - log_debug("%20s : %s", "Guider DeviceCode", dev_code); - } - log_debug("%s", "...................................................."); - - return; -} - -/* multiRegion */ -static void guider_get_url(char *buf, int len) -{ -#ifdef MQTT_DIRECT - HAL_Snprintf(buf, len, "%s", ""); -#else - - HAL_Snprintf(buf, len, "%s", "http://"); - - if (0 == g_domain_type) { /*shanghai*/ - #if defined(ON_PRE) - strcat(buf, "iot-auth-pre.cn-shanghai.aliyuncs.com"); - #elif defined(ON_DAILY) - strcat(buf, "iot-auth.alibaba.net"); - #else - strcat(buf, "iot-auth.cn-shanghai.aliyuncs.com"); - #endif - } - - else if (1 == g_domain_type){ /*southeast*/ - #if defined(ON_PRE) - strcat(buf, "iot-auth-pre.ap-southeast-1.aliyuncs.com"); - #elif defined(ON_DAILY) - strcat(buf, "iot-auth.alibaba.net"); //////////// TODO - #else - strcat(buf, "iot-auth.ap-southeast-1.aliyuncs.com"); - #endif - } - - else if (2 == g_domain_type) - { - #if defined(ON_PRE) - strcat(buf, "iot-auth-pre.ap-northeast-1.aliyuncs.com"); //////////// TODO - #elif defined(ON_DAILY) - strcat(buf, "iot-auth.alibaba.net"); //////////// TODO - #else - strcat(buf, "iot-auth.ap-northeast-1.aliyuncs.com"); //////////// TODO - #endif - } - - else if (3 == g_domain_type) - { - #if defined(ON_PRE) - strcat(buf, "iot-auth-pre.us-west-1.aliyuncs.com"); //////////// TODO - #elif defined(ON_DAILY) - strcat(buf, "iot-auth.alibaba.net"); //////////// TODO - #else - strcat(buf, "iot-auth.us-west-1.aliyuncs.com"); //////////// TODO - #endif - } - - else if (4 == g_domain_type) - { - #if defined(ON_PRE) - strcat(buf, "iot-auth-pre.eu-central-1.aliyuncs.com"); //////////// TODO - #elif defined(ON_DAILY) - strcat(buf, "iot-auth.alibaba.net"); //////////// TODO - #else - strcat(buf, "iot-auth.eu-central-1.aliyuncs.com"); //////////// TODO - #endif - } - - strcat(buf, "/auth/devicename"); - -#endif /* MQTT_DIRECT */ - - return; -} - -static void guider_get_timestamp_str(char *buf, int len) -{ - HAL_Snprintf(buf, len, "%s", GUIDER_DEFAULT_TS_STR); - - return; -} - -static SECURE_MODE guider_get_secure_mode(void) -{ - SECURE_MODE rc = MODE_TLS_GUIDER; - -#ifdef MQTT_DIRECT - -#ifdef IOTX_WITHOUT_TLS - rc = MODE_TCP_DIRECT_PLAIN; -#else - rc = MODE_TLS_DIRECT; -#endif /* IOTX_WITHOUT_TLS */ - -#else /* MQTT_DIRECT */ - -#ifdef IOTX_WITHOUT_TLS - rc = MODE_TCP_GUIDER_PLAIN; -#else - rc = MODE_TLS_GUIDER; -#endif /* IOTX_WITHOUT_TLS */ - -#endif /* MQTT_DIRECT */ - - return rc; -} - -#ifndef MQTT_DIRECT -static char *guider_set_auth_req_str(char sign[], char ts[]) -{ -#define AUTH_STRING_MAXLEN (1024) - - char *ret = NULL; - iotx_device_info_pt dev = NULL; - int rc = -1; - - dev = iotx_device_info_get(); - LITE_ASSERT(dev); - - ret = HAL_Malloc(AUTH_STRING_MAXLEN); - LITE_ASSERT(ret); - memset(ret, 0, AUTH_STRING_MAXLEN); - - rc = sprintf(ret, - "productKey=%s&" "deviceName=%s&" "signmethod=%s&" "sign=%s&" - "version=default&" "clientId=%s&" "timestamp=%s&" "resources=mqtt" - , dev->product_key - , dev->device_name -#if USING_SHA1_IN_HMAC - , SHA_METHOD -#else - , MD5_METHOD -#endif - , sign - , dev->device_id - , ts); - LITE_ASSERT(rc < AUTH_STRING_MAXLEN); - - return ret; -} - -static int guider_get_iotId_iotToken( - const char *guider_addr, - const char *request_string, - char *iot_id, - char *iot_token, - char *host, - uint16_t *pport) -{ - char iotx_payload[1024] = {0}; - int iotx_port = 443; - int ret = -1; - iotx_conn_info_pt usr = iotx_conn_info_get(); - int ret_code = 0; - const char *pvalue; - char port_str[6]; - - LITE_ASSERT(usr); - -#ifdef IOTX_WITHOUT_TLS - iotx_port = 80; -#endif - -#if defined(TEST_OTA_PRE) - iotx_port = 80; -#endif - - /* - { - "code": 200, - "data": { - "iotId":"030VCbn30334364bb36997f44cMYTBAR", - "iotToken":"e96d15a4d4734a73b13040b1878009bc", - "resources": { - "mqtt": { - "host":"iot-as-mqtt.cn-shanghai.aliyuncs.com", - "port":1883 - } - } - }, - "message":"success" - } - */ - _http_response(iotx_payload, - sizeof(iotx_payload), - request_string, - guider_addr, - iotx_port, -#if defined(TEST_OTA_PRE) - NULL -#elif defined(MQTT_ID2_AUTH) && defined(TEST_ID2_PRE) - NULL -#else - iotx_ca_get() -#endif - ); - log_debug("http response: \r\n\r\n%s\r\n", iotx_payload); - - pvalue = LITE_json_value_of("code", iotx_payload); - if (!pvalue) { - goto do_exit; - } - - ret_code = atoi(pvalue); - LITE_free(pvalue); - pvalue = NULL; - - if (200 != ret_code) { - log_err("++++"); - log_err("ret_code = %d (!= 200), abort!", ret_code); - log_err("++++"); - goto do_exit; - } - - pvalue = LITE_json_value_of("data.iotId", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(iot_id, pvalue); - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of("data.iotToken", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(iot_token, pvalue); - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of("data.resources.mqtt.host", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(host, pvalue); - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of("data.resources.mqtt.port", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(port_str, pvalue); - LITE_free(pvalue); - pvalue = NULL; - *pport = atoi(port_str); - - log_debug("%10s: %s", "iotId", iot_id); - log_debug("%10s: %s", "iotToken", iot_token); - log_debug("%10s: %s", "Host", host); - log_debug("%10s: %d", "Port", *pport); - - ret = 0; - -do_exit: - if (pvalue) { - LITE_free(pvalue); - pvalue = NULL; - } - - return ret; -} -#endif /* MQTT_DIRECT */ - -int iotx_guider_authenticate(void) -{ - char partner_id[PID_STRLEN_MAX + 16] = {0}; - char module_id[MID_STRLEN_MAX + 16] = {0}; - char guider_url[GUIDER_URL_LEN] = {0}; - SECURE_MODE secure_mode = MODE_TLS_GUIDER; - char guider_sign[GUIDER_SIGN_LEN] = {0}; - char timestamp_str[GUIDER_TS_LEN] = {0}; - - iotx_device_info_pt dev = iotx_device_info_get(); - iotx_conn_info_pt conn = iotx_conn_info_get(); - char *req_str = NULL; - int gw = 0; - int ext = 0; - - LITE_ASSERT(dev); - LITE_ASSERT(conn); - - _ident_partner(partner_id, sizeof(partner_id)); - _ident_module(module_id, sizeof(module_id)); - guider_get_url(guider_url, sizeof(guider_url)); - secure_mode = guider_get_secure_mode(); - guider_get_timestamp_str(timestamp_str, sizeof(timestamp_str)); - _calc_hmac_signature(guider_sign, sizeof(guider_sign), timestamp_str); - - guider_print_dev_guider_info(dev, partner_id, module_id, guider_url, secure_mode, - timestamp_str, guider_sign, NULL, NULL); - -#ifndef MQTT_DIRECT - char iotx_conn_host[HOST_ADDRESS_LEN + 1] = {0}; - uint16_t iotx_conn_port = 1883; - char iotx_id[GUIDER_IOT_ID_LEN + 1] = {0}; - char iotx_token[GUIDER_IOT_TOKEN_LEN + 1] = {0}; - - - req_str = guider_set_auth_req_str(guider_sign, timestamp_str); - LITE_ASSERT(req_str); - log_debug("req_str = '%s'", req_str); - - if (0 != guider_get_iotId_iotToken(guider_url, - req_str, - iotx_id, - iotx_token, - iotx_conn_host, - &iotx_conn_port)) { - if (req_str) { - HAL_Free(req_str); - } - - log_err("_iotId_iotToken_http() failed"); - return -1; - } -#endif - - /* Start Filling Connection Information */ - conn->pub_key = iotx_ca_get(); - -#ifdef MQTT_DIRECT -#if defined (ON_DAILY) /* daily*/ - conn->port = 1883; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "10.125.0.27"); -#elif defined (ON_PRE) /* pre */ - conn->port = 80; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "100.67.80.75"); -#else /* online */ - conn->port = 1883; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "%s.%s", - dev->product_key, - guider_get_domain()); -#endif - _fill_conn_string(conn->username, sizeof(conn->username), - "%s&%s", - dev->device_name, - dev->product_key); - _fill_conn_string(conn->password, sizeof(conn->password), - "%s", - guider_sign); - -#else /* MQTT_DIRECT */ - - conn->port = iotx_conn_port; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "%s", - iotx_conn_host); - _fill_conn_string(conn->username, sizeof(conn->username), "%s", iotx_id); - _fill_conn_string(conn->password, sizeof(conn->password), "%s", iotx_token); - -#endif /* MQTT_DIRECT */ - -#ifdef GATEWAY_SUPPORT - gw = 1; -#endif - -#ifdef RRPC_NEW - ext = 1; -#endif - - _fill_conn_string(conn->client_id, sizeof(conn->client_id), - "%s" - "|securemode=%d" -#if USING_SHA1_IN_HMAC - ",timestamp=%s,signmethod=" SHA_METHOD ",gw=%d" ",ext=%d" -#else - ",timestamp=%s,signmethod=" MD5_METHOD ",gw=%d" ",ext=%d" -#endif - "%s" - "%s" - "|" - , dev->device_id - , secure_mode - , timestamp_str - , gw - , ext - , partner_id - , module_id - ); - - guider_print_conn_info(conn); - - if (req_str) { - HAL_Free(req_str); - } - - return 0; - -} - diff --git a/iotkit-embedded/src/system/iotkit-system/src/id2_guider.c b/iotkit-embedded/src/system/iotkit-system/src/id2_guider.c deleted file mode 100644 index 02e204e..0000000 --- a/iotkit-embedded/src/system/iotkit-system/src/id2_guider.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifdef MQTT_ID2_AUTH -#include "guider_internal.h" -#include "utils_epoch_time.h" -#include "tfs.h" - -#ifndef MQTT_DIRECT -static int _is_non_symbol(char c) -{ - int c_int = (int)c; - - if (c == '\0') { - return 1; - } - return (c_int >= 48 && c_int <= 57) || (c_int >= 65 && c_int <= 90) || (c_int >= 97 && c_int <= 122); -} - -static int _url_encode(const char *input, char *output) -{ - if (input == NULL || output == NULL) { - log_err("_url_encode: input param error!"); - return -1; - } - - char encoded[4] = {0}; - char c; - - while (*input) { - c = *input; - - if (c < 0) { - input++; - } else if (_is_non_symbol(c)) { - *output++ = *input++; - } else { - HAL_Snprintf(encoded, 4, "%%%02x", c); - *output++ = encoded[0]; - *output++ = encoded[1]; - *output++ = encoded[2]; - input++; - } - } - - *output++ = 0; - - return 0; -} -#endif /* #ifndef MQTT_DIRECT */ - -static int _calc_id2_signature( - char *id2_sigbuf, - const int sig_buflen, - char *timestamp_str, - char **id2_str, - char **device_code_str) -{ - int rc = -1; - uint8_t id2[TFS_ID2_LEN + 1] = {0}; - uint32_t id2_len = TFS_ID2_LEN + 1; - uint8_t dev_code[GUIDER_DEVCODE_LEN] = {0}; - uint32_t dev_code_len = GUIDER_DEVCODE_LEN; - uint32_t sign_len = GUIDER_DEVCODE_LEN; -#ifndef MQTT_DIRECT - char url_encode_buf[GUIDER_URLENCODE_LEN] = {0}; -#endif - iotx_device_info_pt dev = NULL; - char *digest_str = NULL; - - dev = iotx_device_info_get(); - LITE_ASSERT(dev); - - /* Get timestamp */ - log_debug("timestamp_str: %s", timestamp_str); - - /* Get Device Code */ - rc = tfs_id2_get_timestamp_auth_code((uint8_t *)timestamp_str, - NULL, 0, dev_code, &dev_code_len); - - LITE_ASSERT(!rc); - *device_code_str = LITE_strdup((const char *)dev_code); - - /* Get ID2 */ - rc = tfs_get_ID2(id2, &id2_len); - LITE_ASSERT(rc >= 0); - *id2_str = LITE_strdup((const char *)id2); - - /* Get Signature */ - digest_str = LITE_format_string("clientId%s" - "id2%s" "productKey%s" "timestamp%s", - dev->device_id, - *id2_str, - dev->product_key, - timestamp_str); - rc = tfs_id2_get_timestamp_auth_code((uint8_t *)timestamp_str, - (uint8_t *)digest_str, strlen(digest_str), - (uint8_t *)id2_sigbuf, &sign_len); - - LITE_ASSERT(!rc); - LITE_ASSERT(sign_len <= sig_buflen); - LITE_free(digest_str); - -#ifndef MQTT_DIRECT - /* Get URL-Encoded Device Code */ - _url_encode((const char *)*device_code_str, url_encode_buf); - LITE_free(*device_code_str); - *device_code_str = LITE_strdup(url_encode_buf); - - /* Get URL-Encoded Signature */ - _url_encode((const char *)id2_sigbuf, url_encode_buf); - memset(id2_sigbuf, 0, sig_buflen); - strncpy(id2_sigbuf, url_encode_buf, sig_buflen); -#endif - - return 0; -} - -static void id2_guider_get_timestamp_str(char *buf, int len) -{ - uint64_t ret = 0; - int retry = 0; - - do { - ret = utils_get_epoch_time_from_ntp(buf, len); - } while (ret == 0 && ++retry < 10); - - if (retry > 1) { - log_err("utils_get_epoch_time_from_ntp() retry = %d.", retry); - } - - if (ret == 0) { - log_err("utils_get_epoch_time_from_ntp() failed!"); - } - - return; -} - -static void id2_guider_get_url(char *buf, int len) -{ -#ifdef MQTT_DIRECT - HAL_Snprintf(buf, len, "%s", ""); -#else - - HAL_Snprintf(buf, len, "%s", "http://"); - -#if defined(TEST_ID2_DAILY) - strcat(buf, "iot-auth.alibaba.net"); -#elif defined(TEST_OTA_PRE) - strcat(buf, "iot-auth-pre.cn-shanghai.aliyuncs.com"); -#elif defined(TEST_ID2_PRE) - strcat(buf, "iot-auth-pre.cn-shanghai.aliyuncs.com"); -#elif defined(TEST_MQTT_DAILY) - strcat(buf, "iot-auth.alibaba.net"); -#else - strcat(buf, "iot-auth.cn-shanghai.aliyuncs.com"); -#endif - - strcat(buf, "/auth/id2"); - -#endif /* MQTT_DIRECT */ - - return; -} - -static SECURE_MODE id2_guider_get_secure_mode(void) -{ - SECURE_MODE rc = MODE_TLS_GUIDER; - -#ifdef MQTT_DIRECT - -#if defined(IOTX_WITHOUT_TLS) && defined(IOTX_WITHOUT_ITLS) - rc = MODE_TCP_DIRECT_ID2_ENCRYPT; -#elif !defined(IOTX_WITHOUT_TLS) -#ifndef MQTT_ID2_CRYPTO - rc = MODE_TLS_DIRECT_ID2_ENCRYPT; -#endif -#else - rc = MODE_ITLS_DNS_ID2; -#endif /* IOTX_WITHOUT_TLS */ - -#else /* MQTT_DIRECT */ - -#ifdef IOTX_WITHOUT_TLS - rc = MODE_TCP_GUIDER_PLAIN; -#else -#ifdef MQTT_ID2_CRYPTO - rc = MODE_TCP_GUIDER_ID2_ENCRYPT; -#else - rc = MODE_TLS_GUIDER; -#endif -#endif /* IOTX_WITHOUT_TLS */ - -#endif /* MQTT_DIRECT */ - - return rc; -} - -#ifndef MQTT_DIRECT -static char *id2_guider_set_auth_req_str(char sign[], char ts[], char id2[] -#ifdef MQTT_ID2_CRYPTO - , char dev_code[] -#endif - ) -{ -#define AUTH_STRING_MAXLEN (1024) - - char *ret = NULL; - iotx_device_info_pt dev = NULL; - int rc = -1; - - dev = iotx_device_info_get(); - LITE_ASSERT(dev); - - ret = HAL_Malloc(AUTH_STRING_MAXLEN); - LITE_ASSERT(ret); - memset(ret, 0, AUTH_STRING_MAXLEN); - - rc = sprintf(ret, - "id2=%s&" "sign=%s&" -#ifdef MQTT_ID2_CRYPTO - "deviceCode=%s&" -#endif - "productKey=%s&" - "timestamp=%s&" "version=default&" "clientId=%s&" "resources=mqtt,codec", - id2, sign, -#ifdef MQTT_ID2_CRYPTO - dev_code, -#endif - dev->product_key, - ts, dev->device_id); - LITE_ASSERT(rc < AUTH_STRING_MAXLEN); - - return ret; -} - -static int id2_guider_get_iotId_iotToken( - const char *guider_addr, - const char *request_string, - char *iot_id, - char *iot_token, - char *host, - uint16_t *pport) -{ - char iotx_payload[1024] = {0}; - int iotx_port = 443; - int ret = -1; - iotx_conn_info_pt usr = iotx_conn_info_get(); - int ret_code = 0; - uint8_t *b64_decode = NULL; - uint8_t *id2_decrypt = NULL; - int id2_rc = -1; - uint32_t src_len = 0; - uint32_t dst_len = 0; - uint32_t dec_len = 512; - int cipher_data = 0; - const char *pvalue; - char port_str[6]; - - LITE_ASSERT(usr); - -#ifdef IOTX_WITHOUT_TLS - iotx_port = 80; -#endif - -#if defined(TEST_OTA_PRE) - iotx_port = 80; -#endif - -#if defined(TEST_ID2_PRE) - iotx_port = 80; -#endif - - /* - { - "code": 200, - "data": { - "iotId":"030VCbn30334364bb36997f44cMYTBAR", - "iotToken":"e96d15a4d4734a73b13040b1878009bc", - "resources": { - "mqtt": { - "host":"iot-as-mqtt.cn-shanghai.aliyuncs.com", - "port":1883 - } - } - }, - "message":"success" - } - */ - _http_response(iotx_payload, - sizeof(iotx_payload), - request_string, - guider_addr, - iotx_port, -#if defined(TEST_OTA_PRE) - NULL -#elif defined(TEST_ID2_PRE) - NULL -#else - iotx_ca_get() -#endif - ); - log_debug("http response: \r\n\r\n%s\r\n", iotx_payload); - - pvalue = LITE_json_value_of("code", iotx_payload); - if (!pvalue) { - goto do_exit; - } - - ret_code = atoi(pvalue); - LITE_free(pvalue); - pvalue = NULL; - - if (200 != ret_code) { - log_err("++++"); - log_err("ret_code = %d (!= 200), abort!", ret_code); - log_err("++++"); - goto do_exit; - } - - pvalue = LITE_json_value_of("data.iotId", iotx_payload); - if (NULL == pvalue) { - cipher_data = 1; - log_debug("'data.iotId' NOT found, cipher_data = %d", cipher_data); - } else { - LITE_free(pvalue); - pvalue = NULL; - cipher_data = 0; - log_debug("'data.iotId' already found, cipher_data = %d", cipher_data); - } - - if (cipher_data) { - pvalue = LITE_json_value_of("data", iotx_payload); - if (NULL == pvalue) { - log_err("'data' section not found in HTTP resp payload!"); - goto do_exit; - } - src_len = (uint32_t)strlen(pvalue); - b64_decode = LITE_malloc(src_len); - if (!b64_decode) { - log_err("allocate memory for b64_decode failed"); - goto do_exit; - } - id2_rc = utils_base64decode((const uint8_t *)pvalue, - src_len, - src_len, - b64_decode, - &dst_len); - log_debug("rc = utils_base64decode() = %d, %u Bytes => %u Bytes", id2_rc, src_len, dst_len); - if (id2_rc) { - goto do_exit; - } - LITE_free(pvalue); - pvalue = NULL; - - id2_decrypt = LITE_malloc(dst_len); - if (!id2_decrypt) { - log_err("allocate memory for id2_decrypt failed"); - goto do_exit; - } - - id2_rc = tfs_id2_decrypt((const uint8_t *)b64_decode, - dst_len, - id2_decrypt, - &dec_len); - /* remove */ - /*log_debug("rc = tfs_id2_decrypt() = %d, %u Bytes => %u Bytes", id2_rc, dst_len, dec_len);*/ - if (id2_rc != 0) { - log_err("decrypt cipher text with ID2 key error!"); - goto do_exit; - } - - /* remove */ - /*log_debug("id2_decrypt = %s", id2_decrypt);*/ - - sprintf(iotx_payload, "{\"data\":"); - strcat(iotx_payload, (const char *)id2_decrypt); - strcat(iotx_payload, "}"); - /* remove */ - /*log_debug("iotx_payload = %s", iotx_payload);*/ - } - - - pvalue = LITE_json_value_of("data.iotId", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(iot_id, pvalue); - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of("data.iotToken", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(iot_token, pvalue); - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of("data.resources.mqtt.host", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(host, pvalue); - LITE_free(pvalue); - pvalue = NULL; - - pvalue = LITE_json_value_of("data.resources.mqtt.port", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(port_str, pvalue); - LITE_free(pvalue); - pvalue = NULL; - *pport = atoi(port_str); - - pvalue = LITE_json_value_of("data.resources.codec.key", iotx_payload); - if (NULL == pvalue) { - goto do_exit; - } - strcpy(usr->aeskey_str, pvalue); - LITE_free(pvalue); - - src_len = (uint32_t)strlen(usr->aeskey_str); - id2_rc = utils_base64decode((const uint8_t *)usr->aeskey_str, - src_len, - src_len, - usr->aeskey_hex, - &dst_len); - log_debug("rc = utils_base64decode() = %d, %u Bytes => %u Bytes", id2_rc, src_len, dst_len); - LITE_ASSERT(!id2_rc); - HEXDUMP_DEBUG(usr->aeskey_hex, dst_len); - - log_debug("%10s: %s", "iotId", iot_id); - - /* remove */ - /*log_debug("%10s: %s", "iotToken", iot_token); - log_debug("%10s: %s", "Host", host); - log_debug("%10s: %d", "Port", *pport); - log_debug("%10s: %s", "AES Key", usr->aeskey_str);*/ - - ret = 0; - -do_exit: - if (pvalue) { - LITE_free(pvalue); - pvalue = NULL; - } - if (b64_decode) { - LITE_free(b64_decode); - b64_decode = NULL; - } - if (id2_decrypt) { - LITE_free(id2_decrypt); - id2_decrypt = NULL; - } - - return ret; -} -#endif /* MQTT_DIRECT */ - -extern char* guider_get_domain(); -int iotx_guider_id2_authenticate(void) -{ - char partner_id[PID_STRLEN_MAX + 16] = {0}; - char module_id[MID_STRLEN_MAX + 16] = {0}; - char guider_url[GUIDER_URL_LEN] = {0}; - SECURE_MODE secure_mode = MODE_TLS_GUIDER; - char guider_sign[GUIDER_SIGN_LEN] = {0}; - char time_stamp_str[GUIDER_TS_LEN] = {0}; - char *id2 = NULL; - char *device_code = NULL; - - iotx_device_info_pt dev = iotx_device_info_get(); - iotx_conn_info_pt conn = iotx_conn_info_get(); - char *req_str = NULL; - int gw = 0; - int ext = 0; - - LITE_ASSERT(dev); - LITE_ASSERT(conn); - - id2_guider_get_timestamp_str(time_stamp_str, sizeof(time_stamp_str)); - _ident_partner(partner_id, sizeof(partner_id)); - _ident_module(module_id, sizeof(module_id)); - id2_guider_get_url(guider_url, sizeof(guider_url)); - secure_mode = id2_guider_get_secure_mode(); - - /* get ID2 Signature, deviceCode/ID2 fetched meanwhile */ - _calc_id2_signature(guider_sign, - sizeof(guider_sign), - time_stamp_str, - &id2, - &device_code); - - guider_print_dev_guider_info(dev, partner_id, module_id, guider_url, secure_mode, - time_stamp_str, guider_sign, - id2, device_code); - -#ifndef MQTT_DIRECT - char iotx_conn_host[HOST_ADDRESS_LEN + 1] = {0}; - uint16_t iotx_conn_port = 1883; - char iotx_id[GUIDER_IOT_ID_LEN + 1] = {0}; - char iotx_token[GUIDER_IOT_TOKEN_LEN + 1] = {0}; - - req_str = id2_guider_set_auth_req_str(guider_sign, time_stamp_str, - id2 -#ifdef MQTT_ID2_CRYPTO - , device_code -#endif - ); - - LITE_ASSERT(req_str); - log_debug("req_str = '%s'", req_str); - - if (0 != id2_guider_get_iotId_iotToken(guider_url, - req_str, - iotx_id, - iotx_token, - iotx_conn_host, - &iotx_conn_port)) { - if (req_str) { - HAL_Free(req_str); - } - - log_err("_iotId_iotToken_http() failed"); - LITE_free(id2); - LITE_free(device_code); - return -1; - } -#endif - - /* Start Filling Connection Information */ - conn->pub_key = iotx_ca_get(); - -#ifdef MQTT_DIRECT - -#if defined(TEST_ID2_DAILY) - conn->port = 1885; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "%s", - "10.125.0.27"); -#elif defined(TEST_ID2_PRE) - conn->port = 80; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "%s", - "106.15.166.168"); -#else - conn->port = 1883; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "%s.%s", - dev->product_key, - "itls.cn-shanghai.aliyuncs.com"); -#endif - - _fill_conn_string(conn->username, sizeof(conn->username), -#if defined(IOTX_WITHOUT_TLS) && defined(IOTX_WITHOUT_ITLS) - "%s&%s&%s", - id2, - device_code, -#else - "%s&%s", -#if !defined(IOTX_TEST) - id2, -#else - dev->device_name, -#endif -#endif - dev->product_key); - _fill_conn_string(conn->password, sizeof(conn->password), - "%s", - guider_sign); - -#else /* MQTT_DIRECT */ - - conn->port = iotx_conn_port; - _fill_conn_string(conn->host_name, sizeof(conn->host_name), - "%s", - iotx_conn_host); - _fill_conn_string(conn->username, sizeof(conn->username), "%s", iotx_id); - _fill_conn_string(conn->password, sizeof(conn->password), "%s", iotx_token); - -#endif /* MQTT_DIRECT */ - -#ifdef GATEWAY_SUPPORT - gw = 1; -#endif - -#ifdef RRPC_NEW - ext = 1; -#endif - - _fill_conn_string(conn->client_id, sizeof(conn->client_id), - "%s" - "|securemode=%d" -#if USING_SHA1_IN_HMAC - ",timestamp=%s,signmethod=" SHA_METHOD ",gw=%d, ext=%d" -#else - ",timestamp=%s,signmethod=" MD5_METHOD ",gw=%d, ext=%d" -#endif - "%s" -#ifndef IOTX_WITHOUT_ITLS - ",authtype=id2" -#endif - "|" - , dev->device_id - , secure_mode - , time_stamp_str - , gw - , ext - , partner_id); - - guider_print_conn_info(conn); - - if (req_str) { - HAL_Free(req_str); - } - - LITE_free(id2); - LITE_free(device_code); - - return 0; -} -#endif - diff --git a/iotkit-embedded/src/system/iotkit-system/src/iotx_device.c b/iotkit-embedded/src/system/iotkit-system/src/iotx_device.c deleted file mode 100644 index a0f7886..0000000 --- a/iotkit-embedded/src/system/iotkit-system/src/iotx_device.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include - -#include "lite-log.h" -#include "lite-system.h" - -static iotx_conn_info_t iotx_conn_info; -static iotx_device_info_t iotx_device_info; -static int iotx_devinfo_inited = 0; - -int iotx_device_info_init(void) -{ - if (iotx_devinfo_inited) { - log_debug("device_info already created, return!"); - return 0; - } - - memset(&iotx_device_info, 0x0, sizeof(iotx_device_info_t)); - memset(&iotx_conn_info, 0x0, sizeof(iotx_conn_info_t)); - iotx_devinfo_inited = 1; - - log_info("device_info created successfully!"); - return SUCCESS_RETURN; -} - -int iotx_device_info_set( - const char *product_key, - const char *device_name, - const char *device_secret) -{ - int ret; - log_debug("start to set device info!"); - - memset(&iotx_device_info, 0x0, sizeof(iotx_device_info)); - strncpy(iotx_device_info.product_key, product_key, PRODUCT_KEY_LEN); - strncpy(iotx_device_info.device_name, device_name, DEVICE_NAME_LEN); - strncpy(iotx_device_info.device_secret, device_secret, DEVICE_SECRET_LEN); - - /* construct device-id(@product_key+@device_name) */ - ret = HAL_Snprintf(iotx_device_info.device_id, DEVICE_ID_LEN, "%s.%s", product_key, device_name); - if ((ret < 0) || (ret >= DEVICE_ID_LEN)) { - log_err("set device info failed"); - return FAIL_RETURN; - } - - log_debug("device_info set successfully!"); - return SUCCESS_RETURN; -} - -iotx_device_info_pt iotx_device_info_get(void) -{ - return &iotx_device_info; -} - -iotx_conn_info_pt iotx_conn_info_get(void) -{ - return &iotx_conn_info; -} - diff --git a/iotkit-embedded/src/system/iotkit-system/src/report.c b/iotkit-embedded/src/system/iotkit-system/src/report.c deleted file mode 100644 index fad2690..0000000 --- a/iotkit-embedded/src/system/iotkit-system/src/report.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include "lite-system.h" -#include "iot_import.h" -#include "iot_export.h" - -#include "lite-utils.h" - -int iotx_midreport_reqid(char *requestId, char *product_key, char *device_name) -{ - int ret; - /* requestId = pk+devicename+mid */ - ret = HAL_Snprintf(requestId, - MIDREPORT_REQID_LEN, - "%s_%s_mid", - product_key, - device_name); - return ret; -} - -int iotx_midreport_payload(char *msg, char *requestId, char *mid, char *pid) -{ - int ret; - /*topic's json data: {"id":"requestId" ,"params":{"_sys_device_mid":mid,"_sys_device_pid":pid }}*/ - ret = HAL_Snprintf(msg, - MIDREPORT_PAYLOAD_LEN, - "{\"id\":\"%s\",\"params\":{\"_sys_device_mid\":\"%s\",\"_sys_device_pid\":\"%s\"}}", - requestId, - mid, - pid); - return ret; -} - -int iotx_midreport_topic(char *topic_name, char *topic_head, char *product_key, char *device_name) -{ - int ret; - /* reported topic name: "/sys/${productKey}/${deviceName}/thing/status/update" */ - ret = HAL_Snprintf(topic_name, - IOTX_URI_MAX_LEN, - "%s/sys/%s/%s/thing/status/update", - topic_head, - product_key, - device_name); - return ret; -} - - diff --git a/iotkit-embedded/src/system/iotkit-system/src/sdk-impl.c b/iotkit-embedded/src/system/iotkit-system/src/sdk-impl.c deleted file mode 100644 index ad9a71f..0000000 --- a/iotkit-embedded/src/system/iotkit-system/src/sdk-impl.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "sdk-impl_internal.h" -#ifdef MQTT_ID2_AUTH -#include "id2_crypto.h" -#endif - -void IOT_OpenLog(const char *ident) -{ - const char *mod = ident; - - if (NULL == mod) { - mod = "---"; - } - - LITE_openlog(mod); -} - -void IOT_CloseLog(void) -{ - LITE_closelog(); -} - -void IOT_SetLogLevel(IOT_LogLevel level) -{ - LOGLEVEL lvl = (LOGLEVEL)level; - - if (lvl > LOG_DEBUG_LEVEL) { - log_err("Invalid input level: %d out of [%d, %d]", level, - LOG_EMERG_LEVEL, - LOG_DEBUG_LEVEL); - return; - } - - LITE_set_loglevel(lvl); -} - -void IOT_DumpMemoryStats(IOT_LogLevel level) -{ - LOGLEVEL lvl = (LOGLEVEL)level; - - if (lvl > LOG_DEBUG_LEVEL) { - lvl = LOG_DEBUG_LEVEL; - log_warning("Invalid input level, using default: %d => %d", level, lvl); - } - - LITE_dump_malloc_free_stats(lvl); -} - -#if defined(MQTT_COMM_ENABLED) -int IOT_SetupConnInfo(const char *product_key, - const char *device_name, - const char *device_secret, - void **info_ptr) -{ - int rc = -1; - - if (!info_ptr) { - log_err("Invalid argument, info_ptr = %p", info_ptr); - return -1; - } - - STRING_PTR_SANITY_CHECK(product_key, -1); - STRING_PTR_SANITY_CHECK(device_name, -1); - STRING_PTR_SANITY_CHECK(device_secret, -1); - - iotx_device_info_init(); - iotx_device_info_set(product_key, device_name, device_secret); - - rc = iotx_guider_authenticate(); - if (rc == 0) { - *info_ptr = (void *)iotx_conn_info_get(); - return 0; - } else { - *info_ptr = NULL; - return -1; - } -} - -#ifdef MQTT_ID2_AUTH -int IOT_SetupConnInfoSecure(const char *product_key, - const char *device_name, - const char *device_secret, - void **info_ptr) -{ - int rc; - - STRING_PTR_SANITY_CHECK(product_key, -1); - STRING_PTR_SANITY_CHECK(device_name, -1); - STRING_PTR_SANITY_CHECK(device_secret, -1); - POINTER_SANITY_CHECK(info_ptr, -1); - iotx_device_info_init(); - iotx_device_info_set(product_key, device_name, device_secret); - - rc = iotx_guider_id2_authenticate(); - if (rc == 0) { - *info_ptr = (void *)iotx_conn_info_get(); - } else { - *info_ptr = NULL; - } - - return rc; -} -#endif /* #ifdef MQTT_ID2_AUTH */ -#endif /* #if defined(MQTT_COMM_ENABLED) */ - diff --git a/iotkit-embedded/src/tfs/id2_crypto.c b/iotkit-embedded/src/tfs/id2_crypto.c deleted file mode 100644 index f9480a7..0000000 --- a/iotkit-embedded/src/tfs/id2_crypto.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#ifdef MQTT_ID2_AUTH - - -#include -#include -#include "iot_export.h" -#include "sdk-impl_internal.h" -#include "tfs.h" -#include "utils_hmac.h" - -#define HASH_SHA1_LEN (20) -#define HMAC_MD5_LEN (16) -#define MQTT_MAX_TOPIC_LEN (64) -#define MQTT_MS(A, OFFSET) ((A << (sizeof(A) - (OFFSET))*8) >> (sizeof(A) - 1) * 8) - -void writeUint16(unsigned char **pptr, unsigned short anUint) -{ - if (!pptr) { - return; - } - - **pptr = MQTT_MS(anUint, 2); - (*pptr)++; - **pptr = MQTT_MS(anUint, 1); - (*pptr)++; -} - -/** - * Writes an integer as 4 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 writeUint32(unsigned char **pptr, unsigned int anUint) -{ - if (!pptr) { - return; - } - - **pptr = MQTT_MS(anUint, 4); - (*pptr)++; - **pptr = MQTT_MS(anUint, 3); - (*pptr)++; - **pptr = MQTT_MS(anUint, 2); - (*pptr)++; - **pptr = MQTT_MS(anUint, 1); - (*pptr)++; -} - -typedef struct _MQTT_ReplayFender { - uint32_t sequence; - uint16_t hmac_len; -#ifdef HASH_SHA1 - char hmac_str[HASH_SHA1_LEN * 2]; -#else - char hmac_str[HMAC_MD5_LEN * 2]; -#endif -} __attribute__((packed)) MQTT_ReplayFender; - -static int _fill_replay_fender( - MQTT_ReplayFender *f, - const char *topic, - uint16_t msg_id, - int enc_payloadlen) -{ - char hmac_source[MQTT_MAX_TOPIC_LEN + 32] = {0}; - int hmac_srclen = 0; - iotx_conn_info_pt conn; - - if (!f || !topic) { - return -1; - } - - if (!(conn = iotx_conn_info_get())) { - return -1; - } - - uint8_t *ptr = (uint8_t *) & (f->sequence); - writeUint32(&ptr, (uint32_t)msg_id); - ptr = (uint8_t *) & (f->hmac_len); - writeUint16(&ptr, HMAC_MD5_LEN * 2); - - HAL_Snprintf((char *)hmac_source, sizeof(hmac_source), - "%s%d%d", - topic, msg_id, enc_payloadlen); - hmac_srclen = strlen(hmac_source); - log_debug("hmac_source(%d) = '%s'", hmac_srclen, hmac_source); - - memset(f->hmac_str, 0, sizeof(f->hmac_str)); -#ifdef HASH_SHA1 - uint8_t sha1_hexbuf[HASH_SHA1_LEN] = {0}; - - utils_sha1(hmac_source, hmac_srclen, sha1_hexbuf); - LITE_hexbuf_convert(sha1_hexbuf, f->hmac_str, HASH_SHA1_LEN, 0); - log_debug("sha1_str(%d) = '%s'", HASH_SHA1_LEN * 2, f->hmac_str); -#else - utils_hmac_md5((const char *)hmac_source, - hmac_srclen, - f->hmac_str, - (const char *)conn->aeskey_hex, - (int)sizeof(conn->aeskey_hex)); - - HEXDUMP_DEBUG(f->hmac_str, sizeof(f->hmac_str)); - /* _to_lower(f->hmac_str, sizeof(f->hmac_str)); */ - HEXDUMP_DEBUG(f->hmac_str, sizeof(f->hmac_str)); -#endif - - return 0; -} - -int iotx_mqtt_id2_payload_encrypt(char *topic, iotx_mqtt_topic_info_pt topic_msg) -{ - MQTT_ReplayFender fender; - int ret = -1; - int out_buf_len = 0; - uint8_t *out_buf = NULL; - uint8_t iv[16] = {0}; - int enc_len = 0; - iotx_conn_info_pt conn; - - if (!topic || !topic_msg) { - return -1; - } - - if (!(conn = iotx_conn_info_get())) { - return -1; - } - - out_buf_len = (topic_msg->payload_len / 16) * 16; - if (topic_msg->payload_len % 16 != 0) { - out_buf_len += 16; - } - - /* get fender (fender is between mqtt header and mqtt message) */ - memset(&fender, 0, sizeof(MQTT_ReplayFender)); - _fill_replay_fender(&fender, - topic, - topic_msg->packet_id, - out_buf_len); - - out_buf_len += sizeof(MQTT_ReplayFender); - out_buf = (uint8_t *)LITE_malloc(out_buf_len + 1); - memset(out_buf, 0, out_buf_len + 1); - memcpy(out_buf, &fender, sizeof(MQTT_ReplayFender)); - - /* encode MQTT message */ - ret = tfs_aes128_cbc_enc(conn->aeskey_hex, - iv, - topic_msg->payload_len, - (const uint8_t *)topic_msg->payload, - &enc_len, - out_buf + sizeof(MQTT_ReplayFender), - TFS_AES_ZERO_PADDING); - log_debug("rc = tfs_aes128_cbc_enc() = %d, enc_len = %d", ret, enc_len); - - if (ret != 0) { - log_err("tfs_aes128_cbc_enc error!"); - ret = -1; - goto exit; - } - memset((void *)topic_msg->payload, 0, topic_msg->payload_len); - memcpy((void *)topic_msg->payload, out_buf, out_buf_len); - topic_msg->payload_len = out_buf_len; - - HEXDUMP_DEBUG(topic_msg->payload, topic_msg->payload_len); - -exit: - LITE_free(out_buf); - - return ret; -} - -int iotx_mqtt_id2_payload_decrypt(iotx_mqtt_topic_info_pt topic_msg) -{ - int ret = -1; - uint8_t iv[16] = {0}; - int32_t dec_len = 0; - int offset = sizeof(MQTT_ReplayFender); - uint8_t *dec_out = NULL; - iotx_conn_info_pt conn = NULL; - - conn = iotx_conn_info_get(); - if (!conn) { - return -1; - } - dec_out = LITE_malloc(topic_msg->payload_len); - if (!dec_out) { - return -1; - } - - memset(dec_out, 0, topic_msg->payload_len); - ret = tfs_aes128_cbc_dec(conn->aeskey_hex, - iv, - topic_msg->payload_len - offset, - (const uint8_t *)topic_msg->payload + offset, - &dec_len, - dec_out, - TFS_AES_ZERO_PADDING); - log_debug("rc = tfs_aes128_cbc_dec() = %d, dec_len = %d", ret, dec_len); - - if (ret != 0) { - log_err("tfs_aes128_cbc_dec error!"); - LITE_free(dec_out); - return -1; - } - - memset((void *)topic_msg->payload, 0, topic_msg->payload_len); - memcpy((void *)topic_msg->payload, dec_out, dec_len); - topic_msg->payload_len = dec_len; - - log_debug("ID2 decrypt publish[%d]: %s", topic_msg->payload_len, topic_msg->payload); - LITE_free(dec_out); - - return ret; -} -#endif - diff --git a/iotkit-embedded/src/tfs/id2_crypto.h b/iotkit-embedded/src/tfs/id2_crypto.h deleted file mode 100644 index fdd0ea0..0000000 --- a/iotkit-embedded/src/tfs/id2_crypto.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _ID2_CRYPTO_H_ -#define _ID2_CRYPTO_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -int iotx_mqtt_id2_payload_encrypt(char *topic, iotx_mqtt_topic_info_pt topic_msg); -int iotx_mqtt_id2_payload_decrypt(iotx_mqtt_topic_info_pt topic_msg); - -#if defined(__cplusplus) -} -#endif -#endif diff --git a/iotkit-embedded/src/tfs/iot.mk b/iotkit-embedded/src/tfs/iot.mk deleted file mode 100644 index 6d8f06b..0000000 --- a/iotkit-embedded/src/tfs/iot.mk +++ /dev/null @@ -1,2 +0,0 @@ -LIBA_TARGET := libiot_tfs.a -HDR_REFS := src diff --git a/iotkit-embedded/src/tfs/platform/pal_platform_base64.c b/iotkit-embedded/src/tfs/platform/pal_platform_base64.c deleted file mode 100644 index 0d0b202..0000000 --- a/iotkit-embedded/src/tfs/platform/pal_platform_base64.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2015 YunOS Project. All rights reserved. - */ - -#include "utils_base64.h" - -void pal_base64_encode(const unsigned char *src, int len, - unsigned char *dst, int *out_len) -{ - utils_base64encode(src, (uint32_t)len, (uint32_t)len * 5, dst, (uint32_t *)out_len); - return; -} - diff --git a/iotkit-embedded/src/tfs/platform/pal_platform_log.c b/iotkit-embedded/src/tfs/platform/pal_platform_log.c deleted file mode 100644 index 4609fb4..0000000 --- a/iotkit-embedded/src/tfs/platform/pal_platform_log.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2015 YunOS Project. All rights reserved. - */ - -#include -#include - -void pal_log(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); -} - diff --git a/iotkit-embedded/src/tfs/platform/pal_platform_md5.c b/iotkit-embedded/src/tfs/platform/pal_platform_md5.c deleted file mode 100644 index 63c706f..0000000 --- a/iotkit-embedded/src/tfs/platform/pal_platform_md5.c +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (C) 2015 YunOS Project. All rights reserved. - */ - -#include "utils_md5.h" - -void pal_md5_sum(const uint8_t *addr, const int len, uint8_t *mac) -{ - utils_md5(addr, (size_t)len, mac); - return; -} diff --git a/iotkit-embedded/src/tfs/platform/pal_platform_memory.c b/iotkit-embedded/src/tfs/platform/pal_platform_memory.c deleted file mode 100644 index a6c1d45..0000000 --- a/iotkit-embedded/src/tfs/platform/pal_platform_memory.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2015 YunOS Project. All rights reserved. - */ - -#include "lite-utils.h" - -void* pal_memory_malloc(size_t size) -{ - return LITE_malloc((int)size); -} - -void pal_memory_free(void* ptr) -{ - LITE_free(ptr); - return; -} diff --git a/iotkit-embedded/src/tfs/platform/pal_platform_random.c b/iotkit-embedded/src/tfs/platform/pal_platform_random.c deleted file mode 100644 index ba52ccc..0000000 --- a/iotkit-embedded/src/tfs/platform/pal_platform_random.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 YunOS Project. All rights reserved. - */ - -#include -#include "utils_timer.h" - -int pal_get_random() -{ - static int flag = 0; - - /* srand must be called only once! */ - if (flag == 0) { - srand((unsigned int)utils_time_get_ms()); - flag = 1; - } - - return rand(); -} - diff --git a/iotkit-embedded/src/tfs/platform/pal_platform_sha256.c b/iotkit-embedded/src/tfs/platform/pal_platform_sha256.c deleted file mode 100644 index 5b6e2b7..0000000 --- a/iotkit-embedded/src/tfs/platform/pal_platform_sha256.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2015 YunOS Project. All rights reserved. - */ - -#include "utils_sha256.h" - -int pal_sha256_sum(const uint8_t *addr, const int len, uint8_t *mac, uint32_t *mac_len) -{ - utils_sha256(addr, (size_t)len, mac); - *mac_len = 32; - return 0; -} diff --git a/iotkit-embedded/src/tfs/security.h b/iotkit-embedded/src/tfs/security.h deleted file mode 100644 index 688edd3..0000000 --- a/iotkit-embedded/src/tfs/security.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef __SECURITY_H__ -#define __SECURITY_H__ - -#if defined(__cplusplus) -extern "C" { -#endif -#include -#include -#include -#include - -#include "lite-log.h" -#include "lite-utils.h" - -#include "tfs/tfs.h" - -int unittest_tfs(uint64_t timestamp); - -#if defined(__cplusplus) -} -#endif -#endif /* __SECURITY_H__ */ - diff --git a/iotkit-embedded/src/tfs/tfs_demo.c b/iotkit-embedded/src/tfs/tfs_demo.c deleted file mode 100644 index ae21303..0000000 --- a/iotkit-embedded/src/tfs/tfs_demo.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include - -#include "tfs.h" -#include "iot_import.h" - -#define BUF_MAX 512 - -static void hexdump(const uint8_t *str, uint32_t len) -{ - int i; - for (i = 0; i < len; i++) { - HAL_Printf("%02X,", *str++); - if ((i + 1) % 32 == 0) { - HAL_Printf("\n"); - } - } - HAL_Printf("\n\n"); -} - -static int demo_tfs_get_ID2(void) -{ - int ret = 0; - uint32_t len = TFS_ID2_LEN + 1; - uint8_t id2[TFS_ID2_LEN + 1] = {0}; - - ret = tfs_get_ID2(id2, &len); - - HAL_Printf("tfs_get_ID2: ret = %d, the ID2(%d): %s\n\n", ret, len, id2); - return 0; -} - -static int demo_tfs_id2_decrypt(void) -{ - int ret = 0; - uint32_t enc_len = 128; - uint32_t dec_len = 0; - /* - * ciphertext: enc_data[]. - * plaintext: "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789". - */ - const uint8_t enc_data[128] = { 0x10, 0x6C, 0x75, 0xF6, 0x86, 0x51, 0xA7, 0x61, 0x88, 0x71, 0x64, 0x46, 0x17, 0x49, 0x9B, 0x97, - 0xF9, 0x27, 0x8B, 0x18, 0x89, 0xD9, 0x7A, 0x2E, 0xE1, 0x71, 0x96, 0xF7, 0x25, 0x88, 0x90, 0x55, - 0x58, 0x17, 0xC2, 0x78, 0xD5, 0x89, 0x76, 0x1F, 0x60, 0x84, 0xA7, 0xC7, 0xDC, 0x68, 0x0F, 0xE0, - 0xCA, 0xCA, 0x1E, 0x81, 0x7D, 0x7C, 0x53, 0x04, 0xD5, 0x5B, 0xD0, 0xF3, 0x85, 0xBC, 0x8C, 0x0B, - 0x39, 0xDE, 0x64, 0x81, 0x6E, 0x2E, 0xA5, 0xB5, 0x27, 0x05, 0x8A, 0x57, 0xC1, 0x2F, 0x28, 0x9F, - 0x47, 0xE4, 0x14, 0x28, 0xB3, 0x25, 0x82, 0x68, 0x1A, 0x6B, 0xCD, 0x95, 0xA8, 0x09, 0xF3, 0x0B, - 0xF8, 0x62, 0x77, 0x90, 0xDD, 0xB8, 0x7B, 0xE3, 0x48, 0x7E, 0xA7, 0xCC, 0xCE, 0xB6, 0x54, 0x68, - 0x52, 0xC4, 0x32, 0xF2, 0x47, 0x5D, 0xCD, 0xDC, 0x86, 0x8A, 0xE7, 0x16, 0xBD, 0x3D, 0x22, 0x32 - }; - uint8_t dec_out[128] = {0}; - - ret = tfs_id2_decrypt((uint8_t *)enc_data, enc_len, dec_out, &dec_len); - HAL_Printf("tfs_id2_decrypt: ret = %d, decrypt out(%d): %s\n\n", ret, dec_len, dec_out); - - return 0; -} - -static int demo_tfs_id2_get_challenge_auth_code(void) -{ - int ret = -1; - uint32_t len = BUF_MAX; - const char *challenge = "55B83408399FA660F05C82E4F25333DC"; - const char *extra = "abcd1234"; - uint8_t out_data[BUF_MAX] = {0}; - - memset(out_data, 0, BUF_MAX); - ret = tfs_id2_get_challenge_auth_code((const uint8_t *)challenge, NULL, 0, out_data, &len); - HAL_Printf("tfs_id2_get_challenge_auth_code: ret = %d, the auth_code(%d): %s\n\n", ret, len, out_data); - - len = BUF_MAX; - memset(out_data, 0, BUF_MAX); - ret = tfs_id2_get_challenge_auth_code((const uint8_t *)challenge, (uint8_t *)extra, strlen(extra), out_data, &len); - HAL_Printf("tfs_id2_get_challenge_auth_code: ret = %d, the auth_code(%d): %s\n\n", ret, len, out_data); - - return 0; -} - -static int demo_tfs_id2_get_timestamp_auth_code(uint64_t ts) -{ - int ret = -1; - uint32_t len = BUF_MAX; - uint8_t timestamp_str[20 + 1] = {0}; - const char *extra = "abcd1234"; - uint8_t out_data[BUF_MAX] = {0}; - - sprintf((char *)timestamp_str, "%" PRIu64, ts); - - memset(out_data, 0, BUF_MAX); - ret = tfs_id2_get_timestamp_auth_code(timestamp_str, NULL, 0, out_data, &len); - HAL_Printf("tfs_id2_get_timestamp_auth_code: ret = %d, the auth_code(%d): %s\n\n", ret, len, out_data); - - len = BUF_MAX; - memset(out_data, 0, BUF_MAX); - ret = tfs_id2_get_timestamp_auth_code(timestamp_str, (uint8_t *)extra, strlen(extra), out_data, &len); - HAL_Printf("tfs_id2_get_timestamp_auth_code: ret = %d, the auth_code(%d): %s\n\n", ret, len, out_data); - - return 0; -} - -static int demo_aes128_enc_dec(void) -{ - int ret = -1; - uint8_t iv_enc[16] = {0}; - uint8_t iv_dec[16] = {0}; - const uint8_t in[16] = "Hello World!"; - uint8_t enc_out[16]; - uint8_t dec_out[16] = {0}; - int32_t enc_len = 0; - int32_t dec_len = 0; - const uint8_t key[16] = "Demo-Test"; - - ret = tfs_aes128_cbc_enc(key, iv_enc, strlen((char *)in), in, &enc_len, enc_out, TFS_AES_ZERO_PADDING); - HAL_Printf("tfs_aes128_cbc_enc: ret = %d, enc_len = %d, encrypt out(%d):\n", ret, enc_len, 16); - hexdump(enc_out, 16); - - ret = tfs_aes128_cbc_dec(key, iv_dec, 16, enc_out, &dec_len, dec_out, TFS_AES_ZERO_PADDING); - HAL_Printf("tfs_aes128_cbc_dec: ret = %d, dec_len = %d, decrypt out(%d): %s\n", ret, dec_len, 16, (char *)dec_out); - - return 0; -} - -void tfs_demo(uint64_t timestamp) -{ - HAL_Printf(">>>>>>func: demo_tfs_get_ID2 <<<<<<\n"); - demo_tfs_get_ID2(); - - HAL_Printf(">>>>>>func: demo_tfs_id2_decrypt <<<<<<\n"); - demo_tfs_id2_decrypt(); - - HAL_Printf(">>>>>>func: demo_tfs_id2_get_challenge_auth_code <<<<<<\n"); - demo_tfs_id2_get_challenge_auth_code(); - - HAL_Printf(">>>>>>func: demo_tfs_id2_get_timestamp_auth_code <<<<<<\n"); - demo_tfs_id2_get_timestamp_auth_code(timestamp); - - HAL_Printf(">>>>>>func: demo_aes128_enc_dec <<<<<<\n"); - demo_aes128_enc_dec(); -} diff --git a/iotkit-embedded/src/tfs/tfs_uttest.c b/iotkit-embedded/src/tfs/tfs_uttest.c deleted file mode 100644 index 4f4291c..0000000 --- a/iotkit-embedded/src/tfs/tfs_uttest.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "security.h" - -extern void tfs_demo(uint64_t ts); - -int unittest_tfs(uint64_t timestamp) -{ - tfs_demo(timestamp); - return 0; -} diff --git a/iotkit-embedded/src/tls/iot.mk b/iotkit-embedded/src/tls/iot.mk deleted file mode 100644 index 685d0fd..0000000 --- a/iotkit-embedded/src/tls/iot.mk +++ /dev/null @@ -1,6 +0,0 @@ -LIBA_TARGET := libiot_tls.a -CFLAGS := $(filter-out -ansi,$(CFLAGS)) - -LIB_HEADERS := $(wildcard $(TOP_DIR)/$(MODULE_NAME)/mbedtls-in-iotkit/include/mbedtls/*.h) - -PKG_SOURCE := mbedtls-in-iotkit.git diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/.gitignore b/iotkit-embedded/src/tls/mbedtls-in-iotkit/.gitignore deleted file mode 100644 index b76e849..0000000 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -CMakeCache.txt -CMakeFiles -CTestTestfile.cmake -cmake_install.cmake -Testing -Coverage -*.gcno -*.gcda - -# generated by scripts/memory.sh -massif-* - -# MSVC files generated by CMake: -/*.sln -/*.vcxproj -/*.filters - -# MSVC build artifacts: -*.exe -*.pdb -*.ilk -*.lib - -# CMake generates *.dir/ folders for in-tree builds (used by MSVC projects), ignore all of those: -*.dir/ -*.d diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/.travis.yml b/iotkit-embedded/src/tls/mbedtls-in-iotkit/.travis.yml deleted file mode 100644 index fa01e5a..0000000 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: c -compiler: -- clang -- gcc -sudo: false -cache: ccache -script: -- tests/scripts/recursion.pl library/*.c -- tests/scripts/check-generated-files.sh -- tests/scripts/check-doxy-blocks.pl -- tests/scripts/check-names.sh -- tests/scripts/doxygen.sh -- cmake -D CMAKE_BUILD_TYPE:String="Check" . -- make -- make test -- programs/test/selftest -- OSSL_NO_DTLS=1 tests/compat.sh -- tests/ssl-opt.sh -e '\(DTLS\|SCSV\).*openssl' -- tests/scripts/test-ref-configs.pl -- tests/scripts/curves.pl -- tests/scripts/key-exchanges.pl -after_failure: -- tests/scripts/travis-log-failure.sh -env: - global: - secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k=" - -addons: - apt: - packages: - - doxygen - - graphviz - coverity_scan: - project: - name: "ARMmbed/mbedtls" - notification_email: p.j.bakker@polarssl.org - build_command_prepend: - build_command: make - branch_pattern: coverity_scan diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/CMakeLists.txt b/iotkit-embedded/src/tls/mbedtls-in-iotkit/CMakeLists.txt deleted file mode 100644 index 3c19fe0..0000000 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(library) - diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/net.h b/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/net.h deleted file mode 100644 index 774559b..0000000 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/include/mbedtls/net.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * \file net.h - * - * \brief Deprecated header file that includes mbedtls/net_sockets.h - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - * - * \deprecated Superseded by mbedtls/net_sockets.h - */ - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/CMakeLists.txt b/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/CMakeLists.txt deleted file mode 100644 index 459fec1..0000000 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(iot_mbedtls OBJECT ${C_SOURCES}) - diff --git a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/debug.c b/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/debug.c deleted file mode 100644 index f9229b3..0000000 --- a/iotkit-embedded/src/tls/mbedtls-in-iotkit/library/debug.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Debugging routines - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_DEBUG_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#define mbedtls_time_t time_t -#define mbedtls_snprintf snprintf -#endif - -#include "mbedtls/debug.h" - -#include -#include -#include - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define DEBUG_BUF_SIZE 512 - -static int debug_threshold = 0; - -void mbedtls_debug_set_threshold( int threshold ) -{ - debug_threshold = threshold; -} - -/* - * All calls to f_dbg must be made via this function - */ -static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *str ) -{ - /* - * If in a threaded environment, we need a thread identifier. - * Since there is no portable way to get one, use the address of the ssl - * context instead, as it shouldn't be shared between threads. - */ -#if defined(MBEDTLS_THREADING_C) - char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ - mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); - ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); -#else - ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); -#endif -} - -void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ... ) -{ - va_list argp; - char str[DEBUG_BUF_SIZE]; - int ret; - - if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) - return; - - va_start( argp, format ); -#if defined(_WIN32) -#if defined(_TRUNCATE) - ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); -#else - ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); - if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) - { - str[DEBUG_BUF_SIZE-1] = '\0'; - ret = -1; - } -#endif -#else - ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); -#endif - va_end( argp ); - - if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) - { - str[ret] = '\n'; - str[ret + 1] = '\0'; - } - - debug_send_line( ssl, level, file, line, str ); -} - -void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ) -{ - char str[DEBUG_BUF_SIZE]; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - /* - * With non-blocking I/O and examples that just retry immediately, - * the logs would be quickly flooded with WANT_READ, so ignore that. - * Don't ignore WANT_WRITE however, since is is usually rare. - */ - if( ret == MBEDTLS_ERR_SSL_WANT_READ ) - return; - - mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", - text, ret, -ret ); - - debug_send_line( ssl, level, file, line, str ); -} - -void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len ) -{ - char str[DEBUG_BUF_SIZE]; - char txt[17]; - size_t i, idx = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", - text, (unsigned int) len ); - - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - memset( txt, 0, sizeof( txt ) ); - for( i = 0; i < len; i++ ) - { - if( i >= 4096 ) - break; - - if( i % 16 == 0 ) - { - if( i > 0 ) - { - mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - memset( txt, 0, sizeof( txt ) ); - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", - (unsigned int) i ); - - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", - (unsigned int) buf[i] ); - txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; - } - - if( len > 0 ) - { - for( /* i = i */; i % 16 != 0; i++ ) - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); - debug_send_line( ssl, level, file, line, str ); - } -} - -#if defined(MBEDTLS_ECP_C) -void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X ) -{ - char str[DEBUG_BUF_SIZE]; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); - mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); - - mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); - mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_BIGNUM_C) -void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X ) -{ - char str[DEBUG_BUF_SIZE]; - int j, k, zeros = 1; - size_t i, n, idx = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold ) - return; - - for( n = X->n - 1; n > 0; n-- ) - if( X->p[n] != 0 ) - break; - - for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) - if( ( ( X->p[n] >> j ) & 1 ) != 0 ) - break; - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", - text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); - - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - for( i = n + 1, j = 0; i > 0; i-- ) - { - if( zeros && X->p[i - 1] == 0 ) - continue; - - for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) - { - if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) - continue; - else - zeros = 0; - - if( j % 16 == 0 ) - { - if( j > 0 ) - { - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); - debug_send_line( ssl, level, file, line, str ); - idx = 0; - } - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) - ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); - - j++; - } - - } - - if( zeros == 1 ) - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); - debug_send_line( ssl, level, file, line, str ); -} -#endif /* MBEDTLS_BIGNUM_C */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_pk_context *pk ) -{ - size_t i; - mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; - char name[16]; - - memset( items, 0, sizeof( items ) ); - - if( mbedtls_pk_debug( pk, items ) != 0 ) - { - debug_send_line( ssl, level, file, line, - "invalid PK context\n" ); - return; - } - - for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) - { - if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) - return; - - mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); - name[sizeof( name ) - 1] = '\0'; - - if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) - mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); - else -#if defined(MBEDTLS_ECP_C) - if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) - mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); - else -#endif - debug_send_line( ssl, level, file, line, - "should not happen\n" ); - } -} - -static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text ) -{ - char str[DEBUG_BUF_SIZE]; - const char *start, *cur; - - start = text; - for( cur = text; *cur != '\0'; cur++ ) - { - if( *cur == '\n' ) - { - size_t len = cur - start + 1; - if( len > DEBUG_BUF_SIZE - 1 ) - len = DEBUG_BUF_SIZE - 1; - - memcpy( str, start, len ); - str[len] = '\0'; - - debug_send_line( ssl, level, file, line, str ); - - start = cur + 1; - } - } -} - -void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt ) -{ - char str[DEBUG_BUF_SIZE]; - int i = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold ) - return; - - while( crt != NULL ) - { - char buf[1024]; - - mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); - debug_send_line( ssl, level, file, line, str ); - - mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); - debug_print_line_by_line( ssl, level, file, line, buf ); - - debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); - - crt = crt->next; - } -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#endif /* MBEDTLS_DEBUG_C */ diff --git a/iotkit-embedded/src/utils/CMakeLists.txt b/iotkit-embedded/src/utils/CMakeLists.txt deleted file mode 100644 index 92a3816..0000000 --- a/iotkit-embedded/src/utils/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(digest) -add_subdirectory(misc) diff --git a/iotkit-embedded/src/utils/digest/CMakeLists.txt b/iotkit-embedded/src/utils/digest/CMakeLists.txt deleted file mode 100644 index 00ffdbd..0000000 --- a/iotkit-embedded/src/utils/digest/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(utils_digest OBJECT ${C_SOURCES}) - diff --git a/iotkit-embedded/src/utils/digest/utils_base64.h b/iotkit-embedded/src/utils/digest/utils_base64.h deleted file mode 100644 index f70944f..0000000 --- a/iotkit-embedded/src/utils/digest/utils_base64.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _IOTX_COMMON_BASE64_H_ -#define _IOTX_COMMON_BASE64_H_ - -#include "iot_import.h" -#include "iot_export.h" - -iotx_err_t utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax, - uint8_t *encodedData, uint32_t *outputLength); -iotx_err_t utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax, - uint8_t *decodedData, uint32_t *outputLength); - -#endif diff --git a/iotkit-embedded/src/utils/digest/utils_hmac.c b/iotkit-embedded/src/utils/digest/utils_hmac.c deleted file mode 100644 index 375c8a9..0000000 --- a/iotkit-embedded/src/utils/digest/utils_hmac.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include "lite-log.h" -#include "utils_md5.h" -#include "utils_sha1.h" -#include "utils_hmac.h" - -#define KEY_IOPAD_SIZE 64 - -#define MD5_DIGEST_SIZE 16 -#define SHA1_DIGEST_SIZE 20 - -void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len) -{ - if((NULL == msg) || (NULL == digest) || (NULL == key)) { - log_err("parameter is Null,failed!"); - return; - } - - if(key_len > KEY_IOPAD_SIZE) { - log_err("key_len > size(%d) of array",KEY_IOPAD_SIZE); - return; - } - - iot_md5_context context; - unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ - unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ - unsigned char out[MD5_DIGEST_SIZE]; - int i; - - /* 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 < 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, 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, 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]); - } -} - -void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len) -{ - if((NULL == msg) || (NULL == digest) || (NULL == key)) { - log_err("parameter is Null,failed!"); - return; - } - - if(key_len > KEY_IOPAD_SIZE) { - log_err("key_len > size(%d) of array",KEY_IOPAD_SIZE); - return; - } - - iot_sha1_context context; - unsigned char k_ipad[KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ - unsigned char k_opad[KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ - unsigned char out[SHA1_DIGEST_SIZE]; - int i; - - /* 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 < 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, 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, 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]); - } -} - diff --git a/iotkit-embedded/src/utils/digest/utils_hmac.h b/iotkit-embedded/src/utils/digest/utils_hmac.h deleted file mode 100644 index 692eb7e..0000000 --- a/iotkit-embedded/src/utils/digest/utils_hmac.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#ifndef _IOTX_COMMON_HMAC_H_ -#define _IOTX_COMMON_HMAC_H_ - -#include - -void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len); - -void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len); - -#endif - diff --git a/iotkit-embedded/src/utils/digest/utils_sha1.c b/iotkit-embedded/src/utils/digest/utils_sha1.c deleted file mode 100644 index f0e0659..0000000 --- a/iotkit-embedded/src/utils/digest/utils_sha1.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - -#include -#include -#include "iot_import.h" -#include "lite-log.h" -#include "utils_sha1.h" - -/* Implementation that should never be optimized out by the compiler */ -static void utils_sha1_zeroize(void *v, size_t n) -{ - volatile unsigned char *p = v; - while (n--) { - *p++ = 0; - } -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef IOT_SHA1_GET_UINT32_BE -#define IOT_SHA1_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 IOT_SHA1_PUT_UINT32_BE -#define IOT_SHA1_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; - - IOT_SHA1_GET_UINT32_BE(W[ 0], data, 0); - IOT_SHA1_GET_UINT32_BE(W[ 1], data, 4); - IOT_SHA1_GET_UINT32_BE(W[ 2], data, 8); - IOT_SHA1_GET_UINT32_BE(W[ 3], data, 12); - IOT_SHA1_GET_UINT32_BE(W[ 4], data, 16); - IOT_SHA1_GET_UINT32_BE(W[ 5], data, 20); - IOT_SHA1_GET_UINT32_BE(W[ 6], data, 24); - IOT_SHA1_GET_UINT32_BE(W[ 7], data, 28); - IOT_SHA1_GET_UINT32_BE(W[ 8], data, 32); - IOT_SHA1_GET_UINT32_BE(W[ 9], data, 36); - IOT_SHA1_GET_UINT32_BE(W[10], data, 40); - IOT_SHA1_GET_UINT32_BE(W[11], data, 44); - IOT_SHA1_GET_UINT32_BE(W[12], data, 48); - IOT_SHA1_GET_UINT32_BE(W[13], data, 52); - IOT_SHA1_GET_UINT32_BE(W[14], data, 56); - IOT_SHA1_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, size_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_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 iot_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); - - IOT_SHA1_PUT_UINT32_BE(high, msglen, 0); - IOT_SHA1_PUT_UINT32_BE(low, msglen, 4); - - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - - utils_sha1_update(ctx, iot_sha1_padding, padn); - utils_sha1_update(ctx, msglen, 8); - - IOT_SHA1_PUT_UINT32_BE(ctx->state[0], output, 0); - IOT_SHA1_PUT_UINT32_BE(ctx->state[1], output, 4); - IOT_SHA1_PUT_UINT32_BE(ctx->state[2], output, 8); - IOT_SHA1_PUT_UINT32_BE(ctx->state[3], output, 12); - IOT_SHA1_PUT_UINT32_BE(ctx->state[4], output, 16); -} - - -/* - * output = SHA-1( input buffer ) - */ -void utils_sha1(const unsigned char *input, size_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); -} - diff --git a/iotkit-embedded/src/utils/digest/utils_sha256.c b/iotkit-embedded/src/utils/digest/utils_sha256.c deleted file mode 100644 index 25c64de..0000000 --- a/iotkit-embedded/src/utils/digest/utils_sha256.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * utils_sha256.c - * - * Created on: 2018��1��17�� - * Author: wb-jn347227 - */ -#include -#include -#include "iot_import.h" -#include "lite-log.h" -#include "utils_sha256.h" -/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ -#define R(b,x) ((x) >> (b)) -/* 32-bit Rotate-right (used in SHA-256): */ -#define _S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) - -/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -/* Four of six logical functions used in SHA-256: */ -#define Sigma0_256(x) (_S32(2, (x)) ^ _S32(13, (x)) ^ _S32(22, (x))) -#define Sigma1_256(x) (_S32(6, (x)) ^ _S32(11, (x)) ^ _S32(25, (x))) -#define sigma0_256(x) (_S32(7, (x)) ^ _S32(18, (x)) ^ R(3 , (x))) -#define sigma1_256(x) (_S32(17, (x)) ^ _S32(19, (x)) ^ R(10, (x))) - -/* Hash constant words K for SHA-256: */ -const static uint32_t K256[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, - 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, - 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, - 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, - 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, - 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, - 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, - 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, - 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; -/* Initial hash value H for SHA-256: */ -const static uint32_t sha256_initial_hash_value[8] = { - 0x6a09e667UL, - 0xbb67ae85UL, - 0x3c6ef372UL, - 0xa54ff53aUL, - 0x510e527fUL, - 0x9b05688cUL, - 0x1f83d9abUL, - 0x5be0cd19UL -}; - -static uint8_t is_little_endian() -{ - static uint32_t _endian_x_ = 1; - return ((const uint8_t *)(& _endian_x_))[0]; -} -static uint8_t is_big_endian() -{ - return !is_little_endian(); -} -//reverse byte order -static uint32_t reverse_32bit(uint32_t data) -{ - data = (data >> 16) | (data << 16); - return ((data & 0xff00ff00UL) >> 8) | ((data & 0x00ff00ffUL) << 8); -} - -//host byte order to big endian -uint32_t os_htobe32(uint32_t data) -{ - if (is_big_endian()) { - return data; - } - return reverse_32bit(data); -} -//big endian to host byte order -uint32_t os_be32toh(uint32_t data) -{ - return os_htobe32(data); -} -static inline uint64_t reverse_64bit(uint64_t data) -{ - data = (data >> 32) | (data << 32); - data = ((data & 0xff00ff00ff00ff00ULL) >> 8) | ((data & 0x00ff00ff00ff00ffULL) << 8); - - return ((data & 0xffff0000ffff0000ULL) >> 16) | ((data & 0x0000ffff0000ffffULL) << 16); -} - -//host to big endian -uint64_t os_htobe64(uint64_t data) -{ - if (is_big_endian()) { - return data; - } - - return reverse_64bit(data); -} -static void utils_sha256_zeroize(void *v, size_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_clone(iot_sha256_context *dst, - const iot_sha256_context *src) -{ - *dst = *src; -} -void utils_sha256_starts(iot_sha256_context *ctx) -{ - if (NULL == ctx) { - return; - } - memcpy(ctx->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); - memset(ctx->buffer, 0, SHA256_BLOCK_LENGTH); - ctx->bitcount = 0; -} -void utils_sha256_process(iot_sha256_context *ctx, const uint32_t *data) -{ - uint32_t a, b, c, d, e, f, g, h, s0, s1; - uint32_t T1, T2, *W256; - int j; - - W256 = (uint32_t *) ctx->buffer; - - /* Initialize registers with the prev. intermediate value */ - 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]; - - j = 0; - - do { - /* Copy data while converting to host byte order */ - W256[j] = os_htobe32(*data++); - - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; - - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W256[(j + 1) & 0x0f]; - s0 = sigma0_256(s0); - s1 = W256[(j + 14) & 0x0f]; - s1 = sigma1_256(s1); - - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j & 0x0f] += s1 + W256[(j + 9) & 0x0f] + s0); - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 64); - - /* Compute the current intermediate hash value */ - 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; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} -void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, size_t ilen) -{ - unsigned int freespace, usedspace; - - if (ilen == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - if (ctx == (iot_sha256_context *) 0 || input == (unsigned char *) 0) { - return; - } - - usedspace = (ctx->bitcount >> 3) % SHA256_BLOCK_LENGTH; - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = SHA256_BLOCK_LENGTH - usedspace; - - if (ilen >= freespace) { - /* Fill the buffer completely and process it */ - memcpy(&ctx->buffer[usedspace], input, freespace); - ctx->bitcount += freespace << 3; - ilen -= freespace; - input += freespace; - utils_sha256_process(ctx, (uint32_t *) ctx->buffer); - } else { - /* The buffer is not yet full */ - memcpy(&ctx->buffer[usedspace], input, ilen); - ctx->bitcount += ilen << 3; - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (ilen >= SHA256_BLOCK_LENGTH) { - /* Process as many complete blocks as we can */ - utils_sha256_process(ctx, (uint32_t *) input); - ctx->bitcount += SHA256_BLOCK_LENGTH << 3; - ilen -= SHA256_BLOCK_LENGTH; - input += SHA256_BLOCK_LENGTH; - } - if (ilen > 0) { - /* There's left-overs, so save 'em */ - memcpy(ctx->buffer, input, ilen); - ctx->bitcount += ilen << 3; - } - /* Clean up: */ - usedspace = freespace = 0; -} -void utils_sha256_finish(iot_sha256_context *ctx, unsigned char output[32]) -{ - // int icount = 0; - uint32_t *d = (uint32_t *) output; - unsigned int usedspace; - - /* Sanity check: */ - if (ctx == (iot_sha256_context *) 0) { - return; - } - - /* If no digest buffer is passed, we don't bother doing this: */ - if (output != (unsigned char *) 0) { - usedspace = (ctx->bitcount >> 3) % SHA256_BLOCK_LENGTH; - ctx->bitcount = os_htobe64(ctx->bitcount); - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - ctx->buffer[usedspace++] = 0x80; - - if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - memset(&ctx->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA256_BLOCK_LENGTH) { - memset(&ctx->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ - utils_sha256_process(ctx, (uint32_t *) ctx->buffer); - - /* And set-up for the last transform: */ - memset(ctx->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); - } - } else { - /* Set-up for the last transform: */ - memset(ctx->buffer, 0, SHA256_SHORT_BLOCK_LENGTH); - - /* Begin padding with a 1 bit: */ - *ctx->buffer = 0x80; - } - /* Set the bit count: */ - u_retLen tmp; - tmp.lint = ctx->bitcount; - memcpy(&ctx->buffer[SHA256_SHORT_BLOCK_LENGTH], tmp.sptr, 8); - - - /* Final transform: */ - utils_sha256_process(ctx, (uint32_t *) ctx->buffer); - - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - ctx->state[j] = os_be32toh(ctx->state[j]); - *d++ = ctx->state[j]; - } - } - } - - /* Clean up state data: */ - memset(ctx, 0, sizeof(iot_sha256_context)); - usedspace = 0; -} -void utils_sha256(const unsigned char *input, size_t ilen, unsigned char 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); -} diff --git a/iotkit-embedded/src/utils/iot.mk b/iotkit-embedded/src/utils/iot.mk deleted file mode 100644 index 7148200..0000000 --- a/iotkit-embedded/src/utils/iot.mk +++ /dev/null @@ -1,5 +0,0 @@ -LIBA_TARGET := libiot_utils.a -HDR_REFS := src - -LIB_SRCS := $(wildcard $(TOP_DIR)/$(MODULE_NAME)/*/*.c) -LIB_SRCS += $(wildcard $(PACKAGE_DIR)/LITE-utils/*.c) diff --git a/iotkit-embedded/src/utils/misc/CMakeLists.txt b/iotkit-embedded/src/utils/misc/CMakeLists.txt deleted file mode 100644 index 8020a1c..0000000 --- a/iotkit-embedded/src/utils/misc/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -file(GLOB C_SOURCES "*.c") -add_library(utils_misc OBJECT ${C_SOURCES}) - diff --git a/iotkit-embedded/src/utils/misc/utils_epoch_time.c b/iotkit-embedded/src/utils/misc/utils_epoch_time.c deleted file mode 100644 index ab26806..0000000 --- a/iotkit-embedded/src/utils/misc/utils_epoch_time.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include "utils_epoch_time.h" -#include "lite-log.h" - -#define HTTP_RESP_CONTENT_LEN (64) -#define ALIYUN_NTP_SERVER "ntp%d.aliyun.com" -#define ALIYUN_NTP_PORT (123) - -#define LI 0 -#define VN 3 -#define MODE 3 -#define STRATUM 0 -#define POLL 4 -#define PREC -6 - -#define JAN_1970 0x83aa7e80 /* 2208988800 1970 - 1900 in seconds */ - -/* How to multiply by 4294.967296 quickly (and not quite exactly) - * without using floating point or greater than 32-bit integers. - * If you want to fix the last 12 microseconds of error, add in - * (2911*(x))>>28) - */ -#define NTPFRAC(x) (4294 * (x) + ((1981 * (x)) >> 11)) - -/* The reverse of the above, needed if we want to set our microsecond - * clock (via settimeofday) based on the incoming time in NTP format. - * Basically exact. - */ -#define USEC(x) (((x) >> 12) - 759 * ((((x) >> 10) + 32768) >> 16)) - -/* Converts NTP delay and dispersion, apparently in seconds scaled - * by 65536, to microseconds. RFC1305 states this time is in seconds, - * doesn't mention the scaling. - * Should somehow be the same as 1000000 * x / 65536 - */ -#define sec2u(x) ((x) * 15.2587890625) - -struct timeval_t { - uint32_t tv_sec; - uint32_t tv_usec; -}; - -struct ntptime_t { - uint32_t coarse; - uint32_t fine; -}; - -struct ntp_packet_t { - int li; - int vn; - int mode; - int stratum; - int poll; - int prec; - int delay; - int disp; - int refid; -}; - -/** - * implement of htonl and ntohl - */ -#define BigLittleSwap(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \ - (((uint32_t)(A) & 0x00ff0000) >> 8) | \ - (((uint32_t)(A) & 0x0000ff00) << 8) | \ - (((uint32_t)(A) & 0x000000ff) << 24)) - -/* return 1 if big endian */ -static int _check_endian(void) -{ - union { - uint32_t i; - uint8_t c[4]; - } u; - - u.i = 0x12345678; - return (0x12 == u.c[0]); -} - -static uint32_t _htonl(uint32_t h) -{ - return _check_endian() ? h : BigLittleSwap(h); -} - -static uint32_t _ntohl(uint32_t n) -{ - return _check_endian() ? n : BigLittleSwap(n); -} - -static int _get_packet(unsigned char *packet, int *len) -{ - uint32_t data[12]; - struct timeval_t now = {0, 0}; - - if (*len < 48) { - log_err("packet buf too short!\n"); - return -1; - } - - memset(packet, 0, *len); - - data[0] = _htonl((LI << 30) | (VN << 27) | (MODE << 24) | - (STRATUM << 16) | (POLL << 8) | (PREC & 0xff)); - data[1] = _htonl(1 << 16); /* Root Delay (seconds) */ - data[2] = _htonl(1 << 16); /* Root Dispersion (seconds) */ - data[10] = _htonl(now.tv_sec + JAN_1970); /* Transmit Timestamp coarse */ - data[11] = _htonl(NTPFRAC(now.tv_usec)); /* Transmit Timestamp fine */ - - memcpy(packet, data, 48); - *len = 48; - - return 0; -} - -static void _rfc1305_parse_timeval(unsigned char *read_buf, struct timeval_t *tv) -{ -/* straight out of RFC-1305 Appendix A */ - struct ntp_packet_t ntp_packet; - struct ntptime_t xmttime; -#ifdef NTP_DEBUG - struct ntptime_t reftime, orgtime, rectime; -#endif - memset(&ntp_packet, 0, sizeof(struct ntp_packet_t)); - -#define Data(i) _ntohl(((unsigned int *)read_buf)[i]) - ntp_packet.li = Data(0) >> 30 & 0x03; - ntp_packet.vn = Data(0) >> 27 & 0x07; - ntp_packet.mode = Data(0) >> 24 & 0x07; - ntp_packet.stratum = Data(0) >> 16 & 0xff; - ntp_packet.poll = Data(0) >> 8 & 0xff; - ntp_packet.prec = Data(0) & 0xff; - if (ntp_packet.prec & 0x80) ntp_packet.prec |= 0xffffff00; - ntp_packet.delay = Data(1); - ntp_packet.disp = Data(2); - ntp_packet.refid = Data(3); - -#ifdef NTP_DEBUG - reftime.coarse = Data(4); - reftime.fine = Data(5); - orgtime.coarse = Data(6); - orgtime.fine = Data(7); - rectime.coarse = Data(8); - rectime.fine = Data(9); -#endif - xmttime.coarse = Data(10); - xmttime.fine = Data(11); -#undef Data - -#ifdef NTP_DEBUG - log_debug("LI=%d VN=%d Mode=%d Stratum=%d Poll=%d Precision=%d\n", - ntp_packet.li, ntp_packet.vn, ntp_packet.mode, - ntp_packet.stratum, ntp_packet.poll, ntp_packet.prec); - log_debug("Delay=%.1f Dispersion=%.1f Refid=%u.%u.%u.%u\n", - sec2u(ntp_packet.delay), sec2u(ntp_packet.disp), - ntp_packet.refid >> 24 & 0xff, ntp_packet.refid >> 16 & 0xff, - ntp_packet.refid >> 8 & 0xff, ntp_packet.refid & 0xff); - log_debug("Reference %u.%.6u\n", reftime.coarse - JAN_1970, USEC(reftime.fine)); - log_debug("Originate %u.%.6u\n", orgtime.coarse - JAN_1970, USEC(orgtime.fine)); - log_debug("Receive %u.%.6u\n", rectime.coarse - JAN_1970, USEC(rectime.fine)); - log_debug("Transmit %u.%.6u\n", xmttime.coarse - JAN_1970, USEC(xmttime.fine)); -#endif - - tv->tv_sec = xmttime.coarse - JAN_1970; - tv->tv_usec = USEC(xmttime.fine); -} - -static uint64_t _get_timestamp_from_ntp(const char *host) -{ - long fd; /* socket */ - int ret = -1; - uint64_t retval = 0; - struct timeval_t tv; - unsigned char write_buf[48] = {0}; - int write_len = sizeof(write_buf); - unsigned char read_buf[1500] = {0}; - - fd = (long)HAL_UDP_create((char *)host, ALIYUN_NTP_PORT); - if (fd < 0) { - log_err("udp create error!"); - return 0; - } - - ret = _get_packet(write_buf, &write_len); - if (ret < 0) { - log_err("get_packet error!"); - goto do_exit; - } - - ret = HAL_UDP_write((void *)fd, write_buf, write_len); - if (ret < 0) { - log_err("udp write error!"); - goto do_exit; - } - - ret = HAL_UDP_readTimeout((void *)fd, read_buf, sizeof(read_buf), 3000); - if (ret < 0) { - log_err("udp read error!"); - goto do_exit; - } - _rfc1305_parse_timeval(read_buf, &tv); - retval = ((uint64_t)tv.tv_sec) * 1000 + tv.tv_usec / 1000; - -do_exit: - HAL_UDP_close((void *)fd); - return retval; -} - -uint64_t utils_get_epoch_time_from_ntp(char copy[], int len) -{ - char ntp_server[20] = {0}; - int ntp_server_index = 1; - uint64_t time_in_ms = 0; - - for (ntp_server_index = 1; ntp_server_index <= 7; ntp_server_index ++) { - HAL_Snprintf(ntp_server, 20, ALIYUN_NTP_SERVER, ntp_server_index); - time_in_ms = _get_timestamp_from_ntp(ntp_server); - if (time_in_ms > 0) { - HAL_Snprintf(copy, len, "%lu", time_in_ms); - break; - } - } - - return time_in_ms; -} diff --git a/iotkit-embedded/src/utils/misc/utils_epoch_time.h b/iotkit-embedded/src/utils/misc/utils_epoch_time.h deleted file mode 100644 index e438db1..0000000 --- a/iotkit-embedded/src/utils/misc/utils_epoch_time.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#ifndef _UTILS_EPOCH_TIME_H_ -#define _UTILS_EPOCH_TIME_H_ -#ifdef __cplusplus -extern "C" { -#endif - -#include "iot_import.h" - -/** - * @brief Get epoch time from the Aliyun NTP(ntp%d.aliyun.com). - * The type of the epoch time is millisecond. - * - * @param none - * - * @return 0, failed to get epoch time; OTHERS, the actual value of epoch time - */ -uint64_t utils_get_epoch_time_from_ntp(char copy[], int len); - -#ifdef __cplusplus -extern "C" { -#endif -#endif /* _ALIOT_EPOCH_TIME_H_ */ diff --git a/iotkit-embedded/src/utils/misc/utils_httpc.c b/iotkit-embedded/src/utils/misc/utils_httpc.c deleted file mode 100644 index 000d9c1..0000000 --- a/iotkit-embedded/src/utils/misc/utils_httpc.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include -#include -#include - -#include "iot_import.h" -#include "utils_timer.h" -#include "lite-log.h" -#include "utils_httpc.h" - -#define HTTPCLIENT_MIN(x,y) (((x)<(y))?(x):(y)) -#define HTTPCLIENT_MAX(x,y) (((x)>(y))?(x):(y)) - -#define HTTPCLIENT_AUTHB_SIZE 128 - -#define HTTPCLIENT_CHUNK_SIZE 1024 /* read payload */ -#define HTTPCLIENT_RAED_HEAD_SIZE 32 /* read header */ -#define HTTPCLIENT_SEND_BUF_SIZE 1024 /* send */ - -#define HTTPCLIENT_MAX_HOST_LEN 128 -#define HTTPCLIENT_MAX_URL_LEN 1024 - -#define HTTP_RETRIEVE_MORE_DATA (1) /**< More data needs to be retrieved. */ - -#if defined(MBEDTLS_DEBUG_C) - #define DEBUG_LEVEL 2 -#endif - -static int httpclient_parse_host(const char *url, char *host, uint32_t maxhost_len); -static int httpclient_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, - uint32_t maxhost_len, int *port, char *path, uint32_t max_path_len); -static int httpclient_conn(httpclient_t *client); -static int httpclient_recv(httpclient_t *client, char *buf, int min_len, int max_len, int *p_read_len, - uint32_t timeout); -static int httpclient_retrieve_content(httpclient_t *client, char *data, int len, uint32_t timeout, - httpclient_data_t *client_data); -static int httpclient_response_parse(httpclient_t *client, char *data, int len, uint32_t timeout, - httpclient_data_t *client_data); - -static void httpclient_base64enc(char *out, const char *in) -{ - const char code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - int i = 0, x = 0, l = 0; - - for (; *in; in++) { - x = x << 8 | *in; - for (l += 8; l >= 6; l -= 6) { - out[i++] = code[(x >> (l - 6)) & 0x3f]; - } - } - if (l > 0) { - x <<= 6 - l; - out[i++] = code[x & 0x3f]; - } - for (; i % 4;) { - out[i++] = '='; - } - out[i] = '\0'; -} - -int httpclient_conn(httpclient_t *client) -{ - if (0 != client->net.connect(&client->net)) { - log_err("establish connection failed"); - return ERROR_HTTP_CONN; - } - - return SUCCESS_RETURN; -} - -int httpclient_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, uint32_t maxhost_len, - int *port, char *path, uint32_t max_path_len) -{ - char *scheme_ptr = (char *) url; - 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) { - log_err("Could not find host"); - return ERROR_HTTP_PARSE; /* URL is invalid */ - } - - if (max_scheme_len < host_ptr - scheme_ptr + 1) { - /* including NULL-terminating char */ - log_err("Scheme str is too small (%u >= %u)", max_scheme_len, (uint32_t)(host_ptr - scheme_ptr + 1)); - return ERROR_HTTP_PARSE; - } - memcpy(scheme, scheme_ptr, host_ptr - scheme_ptr); - scheme[host_ptr - scheme_ptr] = '\0'; - - host_ptr += 3; - - *port = 0; - - path_ptr = strchr(host_ptr, '/'); - if (NULL == path_ptr) { - log_err("invalid path"); - return -1; - } - - if (host_len == 0) { - host_len = path_ptr - host_ptr; - } - - if (maxhost_len < host_len + 1) { - /* including NULL-terminating char */ - log_err("Host str is too long (host_len(%d) >= max_len(%d))", host_len + 1, maxhost_len); - return ERROR_HTTP_PARSE; - } - 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); - } - - if (max_path_len < path_len + 1) { - /* including NULL-terminating char */ - log_err("Path str is too small (%d >= %d)", max_path_len, path_len + 1); - return ERROR_HTTP_PARSE; - } - memcpy(path, path_ptr, path_len); - path[path_len] = '\0'; - - return SUCCESS_RETURN; -} - -int httpclient_parse_host(const char *url, char *host, uint32_t maxhost_len) -{ - const char *host_ptr = (const char *) strstr(url, "://"); - uint32_t host_len = 0; - char *path_ptr; - - if (host_ptr == NULL) { - log_err("Could not find host"); - return ERROR_HTTP_PARSE; /* URL is invalid */ - } - host_ptr += 3; - - path_ptr = strchr(host_ptr, '/'); - if (host_len == 0) { - host_len = path_ptr - host_ptr; - } - - if (maxhost_len < host_len + 1) { - /* including NULL-terminating char */ - log_err("Host str is too small (%d >= %d)", maxhost_len, host_len + 1); - return ERROR_HTTP_PARSE; - } - memcpy(host, host_ptr, host_len); - host[host_len] = '\0'; - - return SUCCESS_RETURN; -} - -int httpclient_get_info(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) { - /* if (client->remote_port == HTTPS_PORT) */ - /* { */ - /* WRITE_IOT_ERROR_LOG("send buffer overflow"); */ - /* return ERROR_HTTP; */ - /* } */ - /* ret = httpclient_tcp_send_all(client->handle, send_buf, 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; -} - -void httpclient_set_custom_header(httpclient_t *client, char *header) -{ - client->header = header; -} - -int httpclient_basic_auth(httpclient_t *client, char *user, char *password) -{ - if ((strlen(user) + strlen(password)) >= HTTPCLIENT_AUTHB_SIZE) { - return ERROR_HTTP; - } - client->auth_user = user; - client->auth_password = password; - return SUCCESS_RETURN; -} - -int httpclient_send_auth(httpclient_t *client, char *send_buf, int *send_idx) -{ - char b_auth[(int)((HTTPCLIENT_AUTHB_SIZE + 3) * 4 / 3 + 1)]; - char base64buff[HTTPCLIENT_AUTHB_SIZE + 3]; - - httpclient_get_info(client, send_buf, send_idx, "Authorization: Basic ", 0); - sprintf(base64buff, "%s:%s", client->auth_user, client->auth_password); - log_debug("bAuth: %s", base64buff) ; - httpclient_base64enc(b_auth, base64buff); - b_auth[strlen(b_auth) + 1] = '\0'; - b_auth[strlen(b_auth)] = '\n'; - log_debug("b_auth:%s", b_auth) ; - httpclient_get_info(client, send_buf, send_idx, b_auth, 0); - return SUCCESS_RETURN; -} - -int httpclient_send_header(httpclient_t *client, const char *url, int method, httpclient_data_t *client_data) -{ - char scheme[8] = { 0 }; - char host[HTTPCLIENT_MAX_HOST_LEN] = { 0 }; - char path[HTTPCLIENT_MAX_URL_LEN] = { 0 }; - 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; - int port; - - /* First we need to parse the url (http[s]://host[:port][/[path]]) */ - /* int res = httpclient_parse_url(url, scheme, sizeof(scheme), host, sizeof(host), &(client->remote_port), path, sizeof(path)); */ - int res = httpclient_parse_url(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path)); - if (res != SUCCESS_RETURN) { - log_err("httpclient_parse_url returned %d", res); - return res; - } - - /* if (client->remote_port == 0) */ - /* { */ - if (strcmp(scheme, "http") == 0) { - /* client->remote_port = HTTP_PORT; */ - } else if (strcmp(scheme, "https") == 0) { - /* client->remote_port = HTTPS_PORT; */ - } - /* } */ - - /* 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 = httpclient_get_info(client, send_buf, &len, buf, strlen(buf)); - if (ret) { - log_err("Could not write request"); - return ERROR_HTTP_CONN; - } - - /* Send all headers */ - if (client->auth_user) { - httpclient_send_auth(client, send_buf, &len); /* send out Basic Auth header */ - } - - /* Add user header information */ - if (client->header) { - httpclient_get_info(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); - httpclient_get_info(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); - httpclient_get_info(client, send_buf, &len, buf, strlen(buf)); - } - } - - /* Close headers */ - httpclient_get_info(client, send_buf, &len, "\r\n", 0); - - log_multi_line(LOG_DEBUG_LEVEL, "REQUEST", "%s", send_buf, ">"); - - /* ret = httpclient_tcp_send_all(client->net.handle, send_buf, len); */ - ret = client->net.write(&client->net, send_buf, len, 5000); - if (ret > 0) { - log_debug("Written %d bytes", ret); - } else if (ret == 0) { - log_err("ret == 0,Connection was closed by server"); - return ERROR_HTTP_CLOSED; /* Connection was closed by server */ - } else { - log_err("Connection error (send returned %d)", ret); - return ERROR_HTTP_CONN; - } - - return SUCCESS_RETURN; -} - -int httpclient_send_userdata(httpclient_t *client, httpclient_data_t *client_data) -{ - int ret = 0; - - if (client_data->post_buf && client_data->post_buf_len) { - log_debug("client_data->post_buf: %s", client_data->post_buf); - { - /* 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); - if (ret > 0) { - log_debug("Written %d bytes", ret); - } else if (ret == 0) { - log_err("ret == 0,Connection was closed by server"); - return ERROR_HTTP_CLOSED; /* Connection was closed by server */ - } else { - log_err("Connection error (send returned %d)", ret); - return ERROR_HTTP_CONN; - } - } - } - - return SUCCESS_RETURN; -} - -/* 0 on success, err code on failure */ -int httpclient_recv(httpclient_t *client, char *buf, int min_len, 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)); - /* log_debug("Recv: | %s", buf); */ - - if (ret > 0) { - *p_read_len = ret; - } else if (ret == 0) { - /* timeout */ - return FAIL_RETURN; - } else if (-1 == ret) { - log_info("Connection closed."); - return ERROR_HTTP_CONN; - } else { - log_err("Connection error (recv returned %d)", ret); - return ERROR_HTTP_CONN; - } - log_info("%u bytes has been read", *p_read_len); - return 0; - - /* while (readLen <= min_len) { */ - /* buf[readLen] = '\0'; */ - /* if (readLen < min_len) { */ - /* //wait to read HTTP respond data */ - /* ret = client->net.read(&client->net, buf + readLen, min_len - readLen, utils_timer_remain(&timer)); */ - /* } else { */ - /* //read the rest data in TCP buffer (with little wait time) */ - /* ret = client->net.read(&client->net, buf + readLen, max_len - readLen, 100); */ - /* } */ - /* */ - /* if (ret > 0) { */ - /* readLen += ret; */ - /* } else if (ret == 0) { */ - /* //timeout */ - /* break; */ - /* } else if (-1 == ret) { */ - /* log_info("Connection closed. %u bytes be read", readLen); */ - /* break; */ - /* } else { */ - /* log_err("Connection error (recv returned %d)", ret); */ - /* return ERROR_HTTP_CONN; */ - /* } */ - /* } */ - /* */ - /* log_info("%u bytes be read", readLen); */ - /* *p_read_len = readLen; */ - /* return 0; */ -} - -int httpclient_retrieve_content(httpclient_t *client, char *data, int len, - uint32_t timeout_ms, httpclient_data_t *client_data) -{ - int count = 0; - int templen = 0; - int crlf_pos; - iotx_time_t timer; - - iotx_time_init(&timer); - utils_time_countdown_ms(&timer, timeout_ms); - - /* Receive data */ - log_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 */ - while (1) { - int ret, max_len; - if (count + len < client_data->response_buf_len - 1) { - memcpy(client_data->response_buf + count, data, len); - count += len; - client_data->response_buf[count] = '\0'; - } 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'; - return HTTP_RETRIEVE_MORE_DATA; - } - - /* try to read more header */ - max_len = HTTPCLIENT_MIN(HTTPCLIENT_RAED_HEAD_SIZE, client_data->response_buf_len - 1 - count); - ret = httpclient_recv(client, data, 1, max_len, &len, iotx_time_left(&timer)); - - /* Receive data */ - log_debug("data len: %d %d", len, count); - - if (ret == ERROR_HTTP_CONN) { - log_debug("ret == ERROR_HTTP_CONN"); - return ret; - } - - if (len == 0) { - /* read no more data */ - log_debug("no more len == 0"); - client_data->is_more = IOT_FALSE; - return SUCCESS_RETURN; - } - } - } - - while (1) { - uint32_t readLen = 0; - - if (client_data->is_chunked && client_data->retrieve_len <= 0) { - /* Read chunk header */ - int foundCrlf; - int n; - do { - foundCrlf = IOT_FALSE; - crlf_pos = 0; - data[len] = 0; - if (len >= 2) { - for (; crlf_pos < len - 2; crlf_pos++) { - if (data[crlf_pos] == '\r' && data[crlf_pos + 1] == '\n') { - foundCrlf = IOT_TRUE; - break; - } - } - } - if (!foundCrlf) { - /* Try to read more */ - if (len < HTTPCLIENT_CHUNK_SIZE) { - int new_trf_len, ret; - ret = httpclient_recv(client, - data + len, - 0, - HTTPCLIENT_CHUNK_SIZE - len - 1, - &new_trf_len, - iotx_time_left(&timer)); - len += new_trf_len; - if (ret == ERROR_HTTP_CONN) { - return ret; - } else { - continue; - } - } else { - return ERROR_HTTP; - } - } - } while (!foundCrlf); - data[crlf_pos] = '\0'; - - /* chunk length */ - /* n = sscanf(data, "%x", &readLen); */ - - readLen = strtoul(data, NULL, 16); - n = (0 == readLen) ? 0 : 1; - client_data->retrieve_len = readLen; - client_data->response_content_len += client_data->retrieve_len; - if (readLen == 0) { - /* Last chunk */ - client_data->is_more = IOT_FALSE; - log_debug("no more (last chunk)"); - } - - if (n != 1) { - log_err("Could not read chunk length"); - return ERROR_HTTP_UNRESOLVED_DNS; - } - - memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2)); /* Not need to move NULL-terminating char any more */ - len -= (crlf_pos + 2); - } else { - readLen = client_data->retrieve_len; - } - - log_debug("Total-Payload: %d Bytes; Read: %d Bytes", readLen, len); - - do { - templen = HTTPCLIENT_MIN(len, readLen); - if (count + templen < client_data->response_buf_len - 1) { - memcpy(client_data->response_buf + count, data, templen); - count += templen; - client_data->response_buf[count] = '\0'; - client_data->retrieve_len -= templen; - } 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; - } - - if (len > readLen) { - log_debug("memmove %d %d %d\n", readLen, len, client_data->retrieve_len); - memmove(data, &data[readLen], len - readLen); /* chunk case, read between two chunks */ - len -= readLen; - readLen = 0; - client_data->retrieve_len = 0; - } else { - readLen -= len; - } - - if (readLen) { - int ret; - int max_len = HTTPCLIENT_MIN(HTTPCLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count); - max_len = HTTPCLIENT_MIN(max_len, readLen); - ret = httpclient_recv(client, data, 1, max_len, &len, iotx_time_left(&timer)); - if (ret == ERROR_HTTP_CONN) { - return ret; - } - } - } while (readLen); - - if (client_data->is_chunked) { - if (len < 2) { - int new_trf_len, ret; - /* Read missing chars to find end of chunk */ - ret = httpclient_recv(client, data + len, 2 - len, HTTPCLIENT_CHUNK_SIZE - len - 1, &new_trf_len, - iotx_time_left(&timer)); - if (ret == ERROR_HTTP_CONN) { - return ret; - } - len += new_trf_len; - } - if ((data[0] != '\r') || (data[1] != '\n')) { - log_err("Format error, %s", data); /* after memmove, the beginning of next chunk */ - return ERROR_HTTP_UNRESOLVED_DNS; - } - memmove(data, &data[2], len - 2); /* remove the \r\n */ - len -= 2; - } else { - log_debug("no more (content-length)"); - client_data->is_more = IOT_FALSE; - break; - } - - } - - return SUCCESS_RETURN; -} - -int httpclient_response_parse(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; - - 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) - - [] */ - char *crlf_ptr = strstr(data, "\r\n"); - if (crlf_ptr == NULL) { - log_err("\r\n not found"); - return ERROR_HTTP_UNRESOLVED_DNS; - } - - crlf_pos = crlf_ptr - data; - data[crlf_pos] = '\0'; - - /* Parse HTTP response */ -#if 0 - if (sscanf(data, "HTTP/%*d.%*d %d %*[^\r\n]", &(client->response_code)) != 1) { - /* Cannot match string, error */ - log_err("Not a correct HTTP answer : %s\n", data); - return ERROR_HTTP_UNRESOLVED_DNS; - } -#endif - - client->response_code = atoi(data + 9); - - if ((client->response_code < 200) || (client->response_code >= 400)) { - /* Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers */ - log_warning("Response code %d", client->response_code); - } - - log_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 = httpclient_recv(client, data + len, 1, 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 if (NULL != (tmp_ptr = strstr(data, "Transfer-Encoding"))) { - int len_chunk = strlen("Chunked"); - char *chunk_value = data + strlen("Transfer-Encoding: "); - - if ((! memcmp(chunk_value, "Chunked", len_chunk)) - || (! memcmp(chunk_value, "chunked", len_chunk))) { - client_data->is_chunked = IOT_TRUE; - client_data->response_content_len = 0; - client_data->retrieve_len = 0; - } - } else { - log_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 httpclient_retrieve_content(client, data, len, iotx_time_left(&timer), client_data); -} - -int httpclient_connect(httpclient_t *client) -{ - int ret = ERROR_HTTP_CONN; - - client->net.handle = 0; - - ret = httpclient_conn(client); - /* if (0 == ret) */ - /* { */ - /* client->remote_port = HTTP_PORT; */ - /* } */ - - return ret; -} - -int httpclient_send_request(httpclient_t *client, const char *url, HTTPCLIENT_REQUEST_TYPE method, - httpclient_data_t *client_data) -{ - int ret = ERROR_HTTP_CONN; - - if (0 == client->net.handle) { - log_debug("not connection have been established"); - return ret; - } - - ret = httpclient_send_header(client, url, method, client_data); - if (ret != 0) { - log_err("httpclient_send_header is error,ret = %d", ret); - return ret; - } - - if (method == HTTPCLIENT_POST || method == HTTPCLIENT_PUT) { - ret = httpclient_send_userdata(client, client_data); - } - - 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_CHUNK_SIZE] = { 0 }; - iotx_time_t timer; - - iotx_time_init(&timer); - utils_time_countdown_ms(&timer, timeout_ms); - - if (0 == client->net.handle) { - log_debug("not connection have been established"); - return ret; - } - - if (client_data->is_more) { - client_data->response_buf[0] = '\0'; - ret = httpclient_retrieve_content(client, buf, reclen, iotx_time_left(&timer), client_data); - } else { - client_data->is_more = 1; - /* try to read header */ - ret = httpclient_recv(client, buf, 1, HTTPCLIENT_RAED_HEAD_SIZE, &reclen, iotx_time_left(&timer)); - if (ret != 0) { - return ret; - } - - buf[reclen] = '\0'; - - if (reclen) { - log_multi_line(LOG_DEBUG_LEVEL, "RESPONSE", "%s", buf, "<"); - ret = httpclient_response_parse(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; - log_debug("client disconnected"); -} - -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 = 0; - char host[HTTPCLIENT_MAX_HOST_LEN] = { 0 }; - - httpclient_parse_host(url, host, sizeof(host)); - log_debug("host: '%s', port: %d", host, port); - - if (0 == client->net.handle) { - /* Establish connection if no. */ -#ifndef IOTX_NET_INIT_WITH_PK_EXT - ret = iotx_net_init(&client->net, host, port, ca_crt); -#else - ret = iotx_net_init(&client->net, host, port, ca_crt, NULL); -#endif - if (0 != ret) { - return ret; - } - - ret = httpclient_connect(client); - if (0 != ret) { - log_err("httpclient_connect is error, ret = %d", ret); - httpclient_close(client); - return ret; - } - - ret = httpclient_send_request(client, url, method, client_data); - if (0 != ret) { - log_err("httpclient_send_request is error, ret = %d", ret); - httpclient_close(client); - 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) { - log_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. */ - log_info("close http channel"); - httpclient_close(client); - } - - return (ret >= 0) ? 0 : -1; -} - -int utils_get_response_code(httpclient_t *client) -{ - return client->response_code; -} - -int iotx_post(httpclient_t *client, - const char *url, - int port, - const char *ca_crt, - httpclient_data_t *client_data) -{ - /* return httpclient_common(client, url, port, ca_crt, HTTPCLIENT_POST, timeout_ms, client_data); */ - int ret = ERROR_HTTP; - char host[HTTPCLIENT_MAX_HOST_LEN] = { 0 }; - - httpclient_parse_host(url, host, sizeof(host)); - log_debug("host: '%s', port: %d", host, port); - - if (0 == client->net.handle) { - /* Establish connection if no. */ -#ifndef IOTX_NET_INIT_WITH_PK_EXT - ret = iotx_net_init(&client->net, host, port, ca_crt); -#else - ret = iotx_net_init(&client->net, host, port, ca_crt, NULL); -#endif - if (0 != ret) { - return ret; - } - - ret = httpclient_connect(client); - if (0 != ret) { - log_err("httpclient_connect is error, ret = %d", ret); - httpclient_close(client); - return ret; - } - } - - ret = httpclient_send_request(client, url, HTTPCLIENT_POST, client_data); - if (0 != ret) { - log_err("httpclient_send_request is error, ret = %d", ret); - httpclient_close(client); - return ret; - } - - return ret; -} - diff --git a/iotkit-embedded/src/utils/misc/utils_list.c b/iotkit-embedded/src/utils/misc/utils_list.c deleted file mode 100644 index 7f51125..0000000 --- a/iotkit-embedded/src/utils/misc/utils_list.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2009-2010 TJ Holowaychuk . - * - * 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. - */ - - - -#include "iot_import.h" -#include "lite-log.h" -#include "lite-utils_internal.h" -#include "utils_list.h" - - -/* - * Allocate a new list_t. NULL on failure. - */ -list_t *list_new(void) -{ - list_t *self; - self = LITE_malloc(sizeof(list_t)); - if (!self) { - return NULL; - } - self->head = NULL; - self->tail = NULL; - self->free = NULL; - self->match = NULL; - self->len = 0; - return self; -} - -/* - * Free the list. - */ -void list_destroy(list_t *self) -{ - unsigned int len = self->len; - list_node_t *next; - list_node_t *curr = self->head; - - while (len--) { - next = curr->next; - if (self->free) { - self->free(curr->val); - } - LITE_free(curr); - curr = next; - } - - LITE_free(self); -} - -/* - * Append the given node to the list - * and return the node, NULL on failure. - */ -list_node_t *list_rpush(list_t *self, list_node_t *node) -{ - if (!node) { - return NULL; - } - - if (self->len) { - node->prev = self->tail; - node->next = NULL; - self->tail->next = node; - self->tail = node; - } else { - self->head = self->tail = node; - node->prev = node->next = NULL; - } - - ++self->len; - return node; -} - -/* - * Return / detach the last node in the list, or NULL. - */ -list_node_t *list_rpop(list_t *self) -{ - list_node_t *node = NULL; - if (!self->len) { - return NULL; - } - - node = self->tail; - - if (--self->len) { - (self->tail = node->prev)->next = NULL; - } else { - self->tail = self->head = NULL; - } - - node->next = node->prev = NULL; - return node; -} - -/* - * Return / detach the first node in the list, or NULL. - */ -list_node_t *list_lpop(list_t *self) -{ - list_node_t *node = NULL; - if (!self->len) { - return NULL; - } - - node = self->head; - - if (--self->len) { - (self->head = node->next)->prev = NULL; - } else { - self->head = self->tail = NULL; - } - - node->next = node->prev = NULL; - return node; -} - -/* - * Prepend the given node to the list - * and return the node, NULL on failure. - */ -list_node_t *list_lpush(list_t *self, list_node_t *node) -{ - if (!node) { - return NULL; - } - - if (self->len) { - node->next = self->head; - node->prev = NULL; - self->head->prev = node; - self->head = node; - } else { - self->head = self->tail = node; - node->prev = node->next = NULL; - } - - ++self->len; - return node; -} - -/* - * Return the node associated to val or NULL. - */ -list_node_t *list_find(list_t *self, void *val) -{ - list_iterator_t *it; - list_node_t *node; - - if (NULL == (it = list_iterator_new(self, LIST_HEAD))) { - return NULL; - } - node = list_iterator_next(it); - while (node) { - if (self->match) { - if (self->match(val, node->val)) { - list_iterator_destroy(it); - return node; - } - } else { - if (val == node->val) { - list_iterator_destroy(it); - return node; - } - } - node = list_iterator_next(it); - } - - list_iterator_destroy(it); - return NULL; -} - -/* - * Return the node at the given index or NULL. - */ -list_node_t *list_at(list_t *self, int index) -{ - list_direction_t direction = LIST_HEAD; - - if (index < 0) { - direction = LIST_TAIL; - index = ~index; - } - - if ((unsigned) index < self->len) { - list_iterator_t *it; - list_node_t *node; - - if (NULL == (it = list_iterator_new(self, direction))) { - return NULL; - } - node = list_iterator_next(it); - - while (index--) { - node = list_iterator_next(it); - } - list_iterator_destroy(it); - return node; - } - - return NULL; -} - -/* - * Remove the given node from the list, freeing it and it's value. - */ -void list_remove(list_t *self, list_node_t *node) -{ - node->prev ? (node->prev->next = node->next) : (self->head = node->next); - - node->next ? (node->next->prev = node->prev) : (self->tail = node->prev); - - if (self->free) { - self->free(node->val); - } - - LITE_free(node); - --self->len; -} - -/* - * Allocate a new list_iterator_t. NULL on failure. - * Accepts a direction, which may be LIST_HEAD or LIST_TAIL. - */ -list_iterator_t *list_iterator_new(list_t *list, list_direction_t direction) -{ - list_node_t *node = direction == LIST_HEAD ? list->head : list->tail; - return list_iterator_new_from_node(node, direction); -} - -/* - * Allocate a new list_iterator_t with the given start - * node. NULL on failure. - */ -list_iterator_t *list_iterator_new_from_node(list_node_t *node, list_direction_t direction) -{ - list_iterator_t *self; - self = LITE_malloc(sizeof(list_iterator_t)); - if (!self) { - return NULL; - } - self->next = node; - self->direction = direction; - return self; -} - -/* - * Return the next list_node_t or NULL when no more - * nodes remain in the list. - */ -list_node_t *list_iterator_next(list_iterator_t *self) -{ - list_node_t *curr = self->next; - if (curr) { - self->next = self->direction == LIST_HEAD ? curr->next : curr->prev; - } - return curr; -} - -/* - * Free the list iterator. - */ -void list_iterator_destroy(list_iterator_t *self) -{ - LITE_free(self); - self = NULL; -} - -/* - * Allocates a new list_node_t. NULL on failure. - */ -list_node_t *list_node_new(void *val) -{ - list_node_t *self; - self = LITE_malloc(sizeof(list_node_t)); - if (!self) { - return NULL; - } - - self->prev = NULL; - self->next = NULL; - self->val = val; - return self; -} - diff --git a/iotkit-embedded/src/utils/misc/utils_list.h b/iotkit-embedded/src/utils/misc/utils_list.h deleted file mode 100644 index af7bed1..0000000 --- a/iotkit-embedded/src/utils/misc/utils_list.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2009-2010 TJ Holowaychuk . - * - * 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 _IOTX_COMMON_LIST_H -#define _IOTX_COMMON_LIST_H - -#include - -/* - * list_t iterator direction. - */ -typedef enum { - LIST_HEAD, - LIST_TAIL -} list_direction_t; - -/* - * list_t node struct. - */ -typedef struct list_node { - struct list_node *prev; - struct list_node *next; - void *val; -} list_node_t; - -/* - * list_t struct. - */ -typedef struct { - list_node_t *head; - list_node_t *tail; - unsigned int len; - void (*free)(void *val); - int (*match)(void *a, void *b); -} list_t; - -/* - * list_t iterator struct. - */ -typedef struct { - list_node_t *next; - list_direction_t direction; -} list_iterator_t; - -/* Node prototypes. */ -list_node_t *list_node_new(void *val); - -/* list_t prototypes. */ -list_t *list_new(void); - -list_node_t *list_rpush(list_t *self, list_node_t *node); - -list_node_t *list_lpush(list_t *self, list_node_t *node); - -list_node_t *list_find(list_t *self, void *val); - -list_node_t *list_at(list_t *self, int index); - -list_node_t *list_rpop(list_t *self); - -list_node_t *list_lpop(list_t *self); - -void list_remove(list_t *self, list_node_t *node); - -void list_destroy(list_t *self); - -/* list_t iterator prototypes. */ -list_iterator_t *list_iterator_new(list_t *list, list_direction_t direction); - -list_iterator_t *list_iterator_new_from_node(list_node_t *node, list_direction_t direction); - -list_node_t *list_iterator_next(list_iterator_t *self); - -void list_iterator_destroy(list_iterator_t *self); - -#endif - diff --git a/iotkit-embedded/src/utils/misc/utils_net.c b/iotkit-embedded/src/utils/misc/utils_net.c deleted file mode 100644 index a4d76fe..0000000 --- a/iotkit-embedded/src/utils/misc/utils_net.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "iot_import.h" -#include "utils_net.h" -#include "lite-log.h" - -/*** TCP connection ***/ -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 (0 == pNetwork->handle) { - return -1; - } - - HAL_TCP_Destroy(pNetwork->handle); - pNetwork->handle = 0; - return 0; -} - -static int connect_tcp(utils_network_pt pNetwork) -{ - if (NULL == pNetwork) { - log_err("network is null"); - return 1; - } - - pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port); - if (0 == pNetwork->handle) { - return -1; - } - - return 0; -} - -/*** SSL connection ***/ -#ifndef IOTX_WITHOUT_TLS -static int read_ssl(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms) -{ - if (NULL == pNetwork) { - log_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) { - log_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) { - log_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) -{ - if (NULL == pNetwork) { - log_err("network is null"); - return 1; - } - - if (0 != (pNetwork->handle = (intptr_t)HAL_SSL_Establish( - pNetwork->pHostAddress, - pNetwork->port, - pNetwork->ca_crt, - pNetwork->ca_crt_len + 1))) { - return 0; - } else { - /* TODO SHOLUD not remove this handle space */ - /* The space will be freed by calling disconnect_ssl() */ - /* utils_memory_free((void *)pNetwork->handle); */ - return -1; - } -} -#endif /* #ifndef IOTX_WITHOUT_TLS */ - -/*** iTLS connection ***/ -#ifndef IOTX_WITHOUT_ITLS -static int read_itls(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms) -{ - if (NULL == pNetwork) { - log_err("network is null"); - return -1; - } - - return HAL_iTLS_Read((uintptr_t)pNetwork->handle, buffer, len, timeout_ms); -} - -static int write_itls(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms) -{ - if (NULL == pNetwork) { - log_err("network is null"); - return -1; - } - - return HAL_iTLS_Write((uintptr_t)pNetwork->handle, buffer, len, timeout_ms); -} - -static int disconnect_itls(utils_network_pt pNetwork) -{ - if (NULL == pNetwork) { - log_err("network is null"); - return -1; - } - - HAL_iTLS_Destroy((uintptr_t)pNetwork->handle); - pNetwork->handle = 0; - - return 0; -} - -static int connect_itls(utils_network_pt pNetwork) -{ - if (NULL == pNetwork) { - log_err("network is null"); - return 1; - } - - if (0 != (pNetwork->handle = (intptr_t)HAL_iTLS_Establish( - pNetwork->pHostAddress, - pNetwork->port, - pNetwork->product_key))) { - return 0; - } else { - /* TODO SHOLUD not remove this handle space */ - /* The space will be freed by calling disconnect_ssl() */ - /* utils_memory_free((void *)pNetwork->handle); */ - return -1; - } -} -#endif /* #ifndef IOTX_WITHOUT_iTLS */ - -/****** network interface ******/ -int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms) -{ - int ret = 0; - - if (NULL == pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = read_tcp(pNetwork, buffer, len, timeout_ms); - } -#ifndef IOTX_WITHOUT_ITLS - else if (NULL == pNetwork->ca_crt && NULL != pNetwork->product_key) { - ret = read_itls(pNetwork, buffer, len, timeout_ms); - } -#endif -#ifndef IOTX_WITHOUT_TLS - else if (NULL != pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = read_ssl(pNetwork, buffer, len, timeout_ms); - } -#endif - else { - ret = -1; - log_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; - - if (NULL == pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = write_tcp(pNetwork, buffer, len, timeout_ms); - } -#ifndef IOTX_WITHOUT_ITLS - else if (NULL == pNetwork->ca_crt && NULL != pNetwork->product_key) { - ret = write_itls(pNetwork, buffer, len, timeout_ms); - } -#endif -#ifndef IOTX_WITHOUT_TLS - else if (NULL != pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = write_ssl(pNetwork, buffer, len, timeout_ms); - } -#endif - else { - ret = -1; - log_err("no method match!"); - } - - return ret; -} - -int iotx_net_disconnect(utils_network_pt pNetwork) -{ - int ret = 0; - - if (NULL == pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = disconnect_tcp(pNetwork); - } -#ifndef IOTX_WITHOUT_ITLS - else if (NULL == pNetwork->ca_crt && NULL != pNetwork->product_key) { - ret = disconnect_itls(pNetwork); - } -#endif -#ifndef IOTX_WITHOUT_TLS - else if (NULL != pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = disconnect_ssl(pNetwork); - } -#endif - else { - ret = -1; - log_err("no method match!"); - } - - return ret; -} - -int iotx_net_connect(utils_network_pt pNetwork) -{ - int ret = 0; - - if (NULL == pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = connect_tcp(pNetwork); - } -#ifndef IOTX_WITHOUT_ITLS - else if (NULL == pNetwork->ca_crt && NULL != pNetwork->product_key) { - ret = connect_itls(pNetwork); - } -#endif -#ifndef IOTX_WITHOUT_TLS - else if (NULL != pNetwork->ca_crt && NULL == pNetwork->product_key) { - ret = connect_ssl(pNetwork); - } -#endif - else { - ret = -1; - log_err("no method match!"); - } - - return ret; -} - -int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt, char *product_key) -{ - if (!pNetwork || !host) { - log_err("parameter error! pNetwork=%p, host = %p", pNetwork, host); - return -1; - } - pNetwork->pHostAddress = host; - pNetwork->port = port; - pNetwork->ca_crt = ca_crt; -#ifdef IOTX_WITHOUT_ITLS - pNetwork->product_key = NULL; -#else - pNetwork->product_key = product_key; -#endif - - 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; -} diff --git a/iotkit-embedded/src/utils/misc/utils_timer.h b/iotkit-embedded/src/utils/misc/utils_timer.h deleted file mode 100644 index 6d87ee0..0000000 --- a/iotkit-embedded/src/utils/misc/utils_timer.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014-2016 Alibaba Group. All rights reserved. - * License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - - - -#ifndef _IOTX_COMMON_TIMER_H_ -#define _IOTX_COMMON_TIMER_H_ - -#include "iot_import.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/iotkit-embedded/src/wifi_provision/dev_ap/awss_dev_ap.c b/iotkit-embedded/src/wifi_provision/dev_ap/awss_dev_ap.c new file mode 100644 index 0000000..efc4322 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/dev_ap/awss_dev_ap.c @@ -0,0 +1,290 @@ +/* + * 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 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; + int ret = -1; + + static char dev_ap_switchap_parsed = 0; + char topic[TOPIC_LEN_MAX] = {0}; + uint16_t msgid = -1; + int result = 0; + + 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) + goto DEV_AP_SWITCHAP_END; + dev_info = os_zalloc(AWSS_DEV_AP_SWITCHA_RSP_LEN); + if (dev_info == NULL) + 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) + goto DEV_AP_SWITCHAP_END; + + do { + produce_random(aes_random, sizeof(aes_random)); + dev_info[0] = '{'; + awss_build_dev_info(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'; + HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, 200, dev_info); + + 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 { + HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -1, "\"ssid error\""); + 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); + } else { + HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -4, "\"random len 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, "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 */ + } else { + HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -3, "\"passwd len error\""); + success = 0; + AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR); + } + + if (success && is_utf8(passwd, strlen(passwd)) == 0) { + HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -3 , "\"passwd content error\""); + success = 0; + AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR); + } + } while (0); + + 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"); + + 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/iotkit-embedded/src/wifi_provision/dev_ap/awss_dev_ap.h b/iotkit-embedded/src/wifi_provision/dev_ap/awss_dev_ap.h new file mode 100644 index 0000000..0250ca2 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/dev_ap/dev_ap_wrapper.h b/iotkit-embedded/src/wifi_provision/dev_ap/dev_ap_wrapper.h new file mode 100644 index 0000000..7f591f3 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/dev_ap/dev_ap_wrapper.h @@ -0,0 +1,56 @@ +#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 */ +p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); +int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); +int HAL_Aes128_Cbc_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t blockNum, + _OU_ void *dst); +/* 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); +int HAL_Awss_Close_Ap(); +/*************************************** dev-ap special hals ***************************************/ +int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide); diff --git a/iotkit-embedded/src/wifi_provision/frameworks/aplist/awss_aplist.c b/iotkit-embedded/src/wifi_provision/frameworks/aplist/awss_aplist.c new file mode 100644 index 0000000..e7a1a0c --- /dev/null +++ b/iotkit-embedded/src/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_trace("[%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/iotkit-embedded/src/wifi_provision/frameworks/aplist/awss_aplist.h b/iotkit-embedded/src/wifi_provision/frameworks/aplist/awss_aplist.h new file mode 100644 index 0000000..8ec3927 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/aws_lib.h b/iotkit-embedded/src/wifi_provision/frameworks/aws_lib.h new file mode 100644 index 0000000..a713a8b --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/awss.c b/iotkit-embedded/src/wifi_provision/frameworks/awss.c new file mode 100644 index 0000000..117df17 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/awss_main.c b/iotkit-embedded/src/wifi_provision/frameworks/awss_main.c new file mode 100644 index 0000000..e1fc1ac --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/awss_main.h b/iotkit-embedded/src/wifi_provision/frameworks/awss_main.h new file mode 100644 index 0000000..6175213 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/awss_smartconfig.h b/iotkit-embedded/src/wifi_provision/frameworks/awss_smartconfig.h new file mode 100644 index 0000000..13e0a7e --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c b/iotkit-embedded/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c new file mode 100644 index 0000000..07f4a9f --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h b/iotkit-embedded/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h new file mode 100644 index 0000000..bf329fb --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/statics/awss_statis.c b/iotkit-embedded/src/wifi_provision/frameworks/statics/awss_statis.c new file mode 100644 index 0000000..f3e364b --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/statics/awss_statis.h b/iotkit-embedded/src/wifi_provision/frameworks/statics/awss_statis.h new file mode 100644 index 0000000..19afd4d --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_aes_wrapper.c b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_aes_wrapper.c new file mode 100644 index 0000000..9aa7855 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_aes_wrapper.c @@ -0,0 +1,118 @@ +#include "wifi_provision_internal.h" + +#if defined(HAL_CRYPTO) +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include "infra_compat.h" +#if defined(INFRA_AES) +#include "infra_aes.h" +#endif + +#define AES_BLOCK_SIZE 16 + +#if defined(INFRA_AES) +typedef struct { + infra_aes_context ctx; + uint8_t iv[16]; + uint8_t key[16]; +} platform_aes_t; +#endif + +p_HAL_Aes128_t awss_Aes128_Init( + const uint8_t *key, + const uint8_t *iv) +{ +#if defined(INFRA_AES) + int ret = 0; + platform_aes_t *p_aes128 = NULL; + + if (!key || !iv) return p_aes128; + + p_aes128 = (platform_aes_t *)calloc(1, sizeof(platform_aes_t)); + if (!p_aes128) return p_aes128; + + infra_aes_init(&p_aes128->ctx); + + ret = infra_aes_setkey_dec(&p_aes128->ctx, key, 128); + + if (ret == 0) { + memcpy(p_aes128->iv, iv, 16); + memcpy(p_aes128->key, key, 16); + } else { + free(p_aes128); + p_aes128 = NULL; + } + + return (p_HAL_Aes128_t *)p_aes128; +#else + return (p_HAL_Aes128_t *)HAL_Aes128_Init(key, iv, HAL_AES_DECRYPTION); +#endif +} + +int awss_Aes128_Destroy(p_HAL_Aes128_t aes) +{ +#if defined(INFRA_AES) + if (!aes) return -1; + + infra_aes_free(&((platform_aes_t *)aes)->ctx); + free(aes); + + return 0; +#else + return HAL_Aes128_Destroy(aes); +#endif +} + +int awss_Aes128_Cbc_Decrypt( + p_HAL_Aes128_t aes, + const void *src, + size_t blockNum, + void *dst) +{ +#if defined(INFRA_AES) + int i = 0; + int ret = -1; + platform_aes_t *p_aes128 = (platform_aes_t *)aes; + + if (!aes || !src || !dst) return ret; + + for (i = 0; i < blockNum; ++i) { + ret = infra_aes_crypt_cbc(&p_aes128->ctx, INFRA_AES_DECRYPT, AES_BLOCK_SIZE, + p_aes128->iv, src, dst); + src += 16; + dst += 16; + } + + return ret; +#else + return HAL_Aes128_Cbc_Decrypt(aes, src, blockNum, dst); +#endif +} + +int awss_Aes128_Cfb_Decrypt( + p_HAL_Aes128_t aes, + const void *src, + size_t length, + void *dst) +{ +#if defined(INFRA_AES) + size_t offset = 0; + int ret = -1; + platform_aes_t *p_aes128 = (platform_aes_t *)aes; + + if (!aes || !src || !dst) return ret; + + ret = infra_aes_setkey_enc(&p_aes128->ctx, p_aes128->key, 128); + ret = infra_aes_crypt_cfb128(&p_aes128->ctx, INFRA_AES_DECRYPT, length, + &offset, p_aes128->iv, src, dst); + return ret; +#else + return HAL_Aes128_Cfb_Decrypt(aes, src, length, dst); +#endif +} + +#endif /* #if defined(HAL_CRYPTO) */ diff --git a/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_aes_wrapper.h b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_aes_wrapper.h new file mode 100644 index 0000000..d8bbe41 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_aes_wrapper.h @@ -0,0 +1,20 @@ + +#include "wifi_provision_internal.h" + +p_HAL_Aes128_t awss_Aes128_Init( + const uint8_t *key, + const uint8_t *iv); + +int awss_Aes128_Destroy(p_HAL_Aes128_t aes); + +int awss_Aes128_Cbc_Decrypt( + p_HAL_Aes128_t aes, + const void *src, + size_t blockNum, + void *dst); + +int awss_Aes128_Cfb_Decrypt( + p_HAL_Aes128_t aes, + const void *src, + size_t length, + void *dst); diff --git a/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_crypt.c b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_crypt.c new file mode 100644 index 0000000..3786c1b --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_crypt.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include "wifi_provision_internal.h" +#include "awss_aes_wrapper.h" +#include "infra_sha256.h" + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" +{ +#endif + +#ifndef SHA256_DIGEST_SIZE +#define SHA256_DIGEST_SIZE (32) +#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; + + utils_sha256(passwd_src, key_len, digest); + /* 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 = (p_aes128_t)awss_Aes128_Init(key, iv); + if (cbc) { /* AP */ + /* + * mobile-ap, dev-ap, router + */ + res = awss_Aes128_Cbc_Decrypt(aes, decoded, len / AES128_KEY_LEN / 2, plain); + } else { /* smartconfig */ + /* + * smartconfig/wps, zconfig + */ + res = awss_Aes128_Cfb_Decrypt(aes, decoded, len, plain); + } + awss_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/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_crypt.h b/iotkit-embedded/src/wifi_provision/frameworks/utils/awss_crypt.h new file mode 100644 index 0000000..8b80c27 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/utils/zconfig_utils.c b/iotkit-embedded/src/wifi_provision/frameworks/utils/zconfig_utils.c new file mode 100644 index 0000000..54b2ac6 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/utils/zconfig_utils.h b/iotkit-embedded/src/wifi_provision/frameworks/utils/zconfig_utils.h new file mode 100644 index 0000000..d738bb7 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/zconfig_lib.h b/iotkit-embedded/src/wifi_provision/frameworks/zconfig_lib.h new file mode 100644 index 0000000..32da0cf --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/zconfig_protocol.c b/iotkit-embedded/src/wifi_provision/frameworks/zconfig_protocol.c new file mode 100644 index 0000000..4128a60 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/zconfig_protocol.h b/iotkit-embedded/src/wifi_provision/frameworks/zconfig_protocol.h new file mode 100644 index 0000000..5702463 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/frameworks/zconfig_vendor_common.c b/iotkit-embedded/src/wifi_provision/frameworks/zconfig_vendor_common.c new file mode 100644 index 0000000..65bd3c7 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/frameworks/zconfig_vendor_common.c @@ -0,0 +1,573 @@ +/* + * 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"); + if (zconfig_data != NULL) { + void *tmp_mutex = zc_mutex; + memset(zconfig_data, 0, sizeof(struct zconfig_data)); + zc_mutex = tmp_mutex; + } + 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/iotkit-embedded/src/wifi_provision/ht40/awss_ht40.c b/iotkit-embedded/src/wifi_provision/ht40/awss_ht40.c new file mode 100644 index 0000000..3838690 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/ht40/awss_ht40.c @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include "wifi_provision_internal.h" +#ifdef AWSS_SUPPORT_HT40 + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" +{ +#endif + +/* Variable + * Qos: 2Byte + * auth offset: 36 44 52 56 + * group frame: 4e0 3e1~3e7 + */ +uint8_t ht40_hint_frame_cnt[64]; +uint8_t ht40_filter; +signed char ht40_rssi_low, ht40_rssi_high; +#define ht40_rssi_range (15) /* suggested by Fuzhibo */ +/* for ios: start frame interval is 20/100 ms */ +#define HIT_FRAME_PER_CHANNEL (2) + +#define IEEE80211_MIN_HDRLEN (24) + +uint32_t ht40_timestamp; +uint8_t ht40_channel[ZC_MAX_CHANNEL + 1]; +uint8_t ht40_channel_filter[ZC_MAX_CHANNEL + 1]; +uint8_t ht40_state; + +int ht40_init(void) +{ + ht40_state = 0; + ht40_filter = 0; + ht40_rssi_low = 0; + ht40_rssi_high = 0; + ht40_timestamp = 0; + memset(ht40_channel, 0, sizeof(ht40_channel)); + memset(ht40_channel_filter, 0, sizeof(ht40_channel_filter)); + memset(ht40_hint_frame_cnt, 0, sizeof(ht40_hint_frame_cnt)); + return 0; +} + +int ht40_lock_channel(uint8_t channel, uint8_t filter) +{ + if (channel < 1 || channel > 14) + return 0; + + if (!ht40_channel[channel]) { // replace when 0 + ht40_channel[channel] ++; + ht40_channel_filter[channel] = filter; + } else if (filter == ht40_channel_filter[channel]) { + ht40_channel[channel] ++; /* increase */ + } else { + ht40_channel[channel] --; /* decrease */ + } + + if (ht40_channel[channel] >= HIT_FRAME_PER_CHANNEL) + return 1; + + return 0; +} + +int ht40_scanning_hint_frame(uint8_t filter, signed char rssi, uint32_t length, uint8_t channel) +{ + uint8_t channel_locked = 0, next_loop = 0; + int hint_pos = -1; + int tods = 1; + int i, j, k; + + if (ht40_state != STATE_CHN_SCANNING) + return -1; + + /* range check, max: 0x4e0 + tkip + qos, min: 0x3e0 + open */ + if (length > START_FRAME + zconfig_fixed_offset[2][0] + 2 || + length <= GROUP_FRAME + zconfig_fixed_offset[0][0]) { + return -1; + } + + for (i = 1; i >= 0; i--) //Qos or not + for (j = 3; j >= 0; j--) //auth type, without open + for (k = 0; k < 8; k++) {//group frame + if (zconfig_hint_frame[k] + zconfig_fixed_offset[j][0] + i * 2 == length) { + hint_pos = i * 32 + j * 8 + k; +#if 1 + awss_trace("\r\nfilter:%x, rssi:%d, len:%d, Qos:%d, auth:%d, group:%d, %s\r\n", + filter, rssi, length, i, j, k, + next_loop ? "DUP" : ""); +#endif + if (!next_loop) { + channel_locked = ht40_lock_channel(channel, filter); + if (channel_locked) + zconfig_set_state(STATE_CHN_LOCKED_BY_BR, tods, channel); + next_loop = 1;/* don't enter this loop again */ + } + + ht40_hint_frame_cnt[hint_pos]++; + } + }//end of for + + if (channel_locked) { + ht40_rssi_high = rssi + ht40_rssi_range; + if (ht40_rssi_high > -1) + ht40_rssi_high = -1; + ht40_rssi_low = rssi - ht40_rssi_range; + if (ht40_rssi_low < -128) + ht40_rssi_low = -128; + + ht40_filter = filter; + + awss_trace("filter:%x, rssi range:[%d, %d]\r\n", + filter, ht40_rssi_low, ht40_rssi_high); + } + + return hint_pos; +} + +int ht40_get_qos_auth_group_info(uint32_t length) +{ + int count = 0, max_count = 0, max_count_pos = 0; + int continues = 0, max_continues = 0, max_continues_pos = 0, second_continues = 0; + int tods = 1; + int i, j, k; + + if (zc_state != STATE_CHN_LOCKED_BY_BR || + ht40_state != STATE_CHN_SCANNING) { + return 0; + } + + for (i = 1; i >= 0; i--) //Qos or not + for (j = 3; j >= 0; j--) //auth type + for (count = 0, continues = 0, k = 0; k < 8; k++) {//group frame + int pos = i * 32 + j * 8 + k; + + if (ht40_hint_frame_cnt[pos]) { + count += ht40_hint_frame_cnt[pos]; + if (count > max_count) {//NOTE: not >=, see continues + max_count = count; + max_count_pos = pos; + } + + continues += 1; + if (continues >= max_continues) { + second_continues = max_continues; + max_continues = continues; + max_continues_pos = pos; + } + } + } + + awss_debug("max_cont:%d, sec_cont:%d, max_count:%d, max_cont_pos:%d, max_count_pos:%d\r\n", + max_continues, second_continues, max_count, max_count_pos, max_continues_pos); + + if (max_continues > second_continues // not >= + && max_count_pos == max_continues_pos) { + uint8_t qos = max_count_pos / 32; + uint8_t auth = (max_count_pos % 32) / 8; + + zc_frame_offset = zconfig_fixed_offset[auth][0] + qos * 2; + length -= zc_frame_offset; + if (is_start_frame(length) || is_group_frame(length)) { + uint8_t group = get_group_index(length); + + zc_group_pos = group; + zc_cur_pos = group; + zc_score_uplimit = score_mid; + ht40_timestamp = os_get_time_ms(); + + ht40_state = STATE_RCV_IN_PROGRESS; + awss_debug("len:%d, qos:%d, auth:%d, group:%d, offset:%d\r\n", + length, qos, auth, group, zc_frame_offset); + } + } + + return 0; +} + +int awss_ieee80211_ht_ctrl_process(uint8_t *ht_ctrl, int len, int link_type, struct parser_res *res, signed char rssi) +{ + struct ht40_ctrl *ctrl = NULL; + /* + * when device try to connect current router (include adha and aha) + * skip the new packet. + */ + if (ht_ctrl == 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; + + /* + * just process ht ctrl + */ + if (link_type != AWSS_LINK_TYPE_HT40_CTRL) + return ALINK_INVALID; + + ctrl = (struct ht40_ctrl *)ht_ctrl; + res->u.ht_ctrl.rssi = rssi; + res->u.ht_ctrl.filter = ctrl->filter; + res->u.ht_ctrl.data_len = len; + + return ALINK_HT_CTRL; +} + +int awss_recv_callback_ht_ctrl(struct parser_res *res) +{ + uint8_t tods = 1, equal = 0, score = 0; + uint16_t pos = 0, index = 0, len = 0; + uint32_t now = os_get_time_ms(); + int pkg_type = PKG_INVALID; + int hint_pos = -1; + signed char rssi; + uint16_t length; + uint8_t channel; + uint8_t filter; + + rssi = res->u.ht_ctrl.rssi; + length = res->u.ht_ctrl.data_len; + filter = res->u.ht_ctrl.filter; + channel = res->channel; + if (length > IEEE80211_MIN_HDRLEN) { + length -= IEEE80211_MIN_HDRLEN; + len = length; + } else { + goto drop; + } + + hint_pos = ht40_scanning_hint_frame(filter, rssi, length, channel); + + if (hint_pos >= 0) { + ht40_get_qos_auth_group_info(length); + return PKG_GROUP_FRAME; + } + + if (ht40_state == STATE_RCV_IN_PROGRESS) { + if (rssi <= ht40_rssi_low && rssi >= ht40_rssi_high) + goto drop; + if (filter != ht40_filter) + goto drop; + 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 (now - ht40_timestamp > time_interval) { + awss_debug("\t\t\t\t\ttimestamp = %d, pos:%d, len:%x\r\n", + now - ht40_timestamp, pos, len); + goto drop; + } + + /* + * pos_unsync: 进入条件,任一条 + * case1: index rollback + * case2: index equal but len not equal + * case3: data frame & timeout + * 退出条件: + * case1: 进入条件同时也是退出条件 + * case2: 收到同步帧 + */ + if (pos < zc_cur_pos) { + awss_debug("drop: index rollback. prev:%d, cur:%d\n", zc_cur_pos, pos); + goto drop; + } + + if (pos == zc_cur_pos && len != pkg_len(zc_cur_pos)) { + awss_debug("drop: index equal, but len not. prev:%x, cur:%x\n", + pkg_len(pos), len); + pkg_score(pos)--; + goto drop; + } + + if (pos > zc_cur_pos + 4) { + awss_debug("drop: over range too much, prev:%d, cur:%d\n", + zc_cur_pos, pos); + goto drop; + } + + score = zc_score_uplimit - (pos - zc_cur_pos - 1); + zc_score_uplimit = score; + + awss_trace("ht40 %d+%d [%d] -- T %-3x\r\n", zc_group_pos, index, score, len); + /* + 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 + */ + equal = !package_cmp((uint8_t *)pkg(pos), NULL, NULL, tods, len); + + if (score > pkg_score(pos)) { + pkg_score(pos) = score; //update score first + if (!equal) { + zc_replace = 1; + package_save((uint8_t *)pkg(pos), NULL, NULL, tods, len); + } + } else if (score == pkg_score(pos)) {/* range check ? */ + if (equal) { + pkg_score(pos)++; + } else { + pkg_score(pos)--; + } + } else {//pkg_score(pos) > score + /* do nothing */ + } + + zc_cur_pos = pos; + 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; + if (!zconfig_get_ssid_passwd(tods)) { + /* we got it! */ + zconfig_set_state(STATE_RCV_DONE, tods, channel); + return PKG_END; + } + } + + ht40_timestamp = now; + return pkg_type; + + } else { + if (is_start_frame(len) || is_group_frame(len)) { + uint8_t group = get_group_index(len); + + if (!group || group == zc_group_pos + 8) { + zc_group_pos = group; + zc_score_uplimit = score_mid; + + if (zc_cur_pos + 1 == group) + pkg_score(zc_cur_pos) += 1; + + zc_cur_pos = group; + + awss_trace("%d+%d [%d] -- T %-3x\r\n", group, 0, zc_score_uplimit, len); + + //ignore PKG_GROUP_FRAME here + pkg_type = PKG_START_FRAME; + ht40_timestamp = now; + return pkg_type; + } + } + } + } + +drop: + return PKG_INVALID; +} +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif +#endif diff --git a/iotkit-embedded/src/wifi_provision/ht40/awss_ht40.h b/iotkit-embedded/src/wifi_provision/ht40/awss_ht40.h new file mode 100644 index 0000000..b4943d4 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/ht40/awss_ht40.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __AWSS_HT40_H__ +#define __AWSS_HT40_H__ + +#ifdef AWSS_SUPPORT_HT40 + +#include +#include "os.h" +#include "zconfig_ieee80211.h" +#include "zconfig_protocol.h" + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" +{ +#endif + +struct ht40_ctrl { + uint16_t length; + uint8_t filter; + signed char rssi; +}; + +int ht40_init(void); +int awss_ieee80211_ht_ctrl_process(uint8_t *ht_ctrl, int len, int link_type, + struct parser_res *res, signed char rssi); +int awss_recv_callback_ht_ctrl(struct parser_res *res); +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif +#endif +#endif + diff --git a/iotkit-embedded/src/wifi_provision/iot.mk b/iotkit-embedded/src/wifi_provision/iot.mk new file mode 100644 index 0000000..fbce0c3 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/iot.mk @@ -0,0 +1,12 @@ +LIBA_TARGET := libiot_awss.a + +LIB_SRCS_PATTERN := *.c + +$(call Append_Conditional, LIB_SRCS_PATTERN, smartconfig/*.c, AWSS_SUPPORT_SMARTCONFIG) +$(call Append_Conditional, LIB_SRCS_PATTERN, p2p/*.c, AWSS_SUPPORT_SMARTCONFIG_WPS) +$(call Append_Conditional, LIB_SRCS_PATTERN, zero_config/*.c, AWSS_SUPPORT_ZEROCONFIG) +$(call Append_Conditional, LIB_SRCS_PATTERN, phone_ap/*.c, AWSS_SUPPORT_AHA) +$(call Append_Conditional, LIB_SRCS_PATTERN, router_ap/*.c, AWSS_SUPPORT_ADHA) +$(call Append_Conditional, LIB_SRCS_PATTERN, dev_ap/*.c, AWSS_SUPPORT_DEV_AP) +$(call Append_Conditional, LIB_SRCS_PATTERN, frameworks/*.c, AWSS_FRAMEWORKS) +$(call Append_Conditional, LIB_SRCS_PATTERN, frameworks/*/*.c, AWSS_FRAMEWORKS) diff --git a/iotkit-embedded/src/wifi_provision/p2p/awss_wps.c b/iotkit-embedded/src/wifi_provision/p2p/awss_wps.c new file mode 100644 index 0000000..0f45129 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/p2p/awss_wps.c @@ -0,0 +1,391 @@ +/* + * 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: { + void *tmp_mutex = zc_mutex; + awss_warn("p2p encypt:%d not support\r\n", encrypt); + memset(zconfig_data, 0, sizeof(*zconfig_data)); + zc_mutex = tmp_mutex; + 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/iotkit-embedded/src/wifi_provision/p2p/awss_wps.h b/iotkit-embedded/src/wifi_provision/p2p/awss_wps.h new file mode 100644 index 0000000..0cb7fee --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/p2p/p2p_wrapper.h b/iotkit-embedded/src/wifi_provision/p2p/p2p_wrapper.h new file mode 100644 index 0000000..30f348b --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/p2p/p2p_wrapper.h @@ -0,0 +1,52 @@ +#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); +p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); +int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); +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/iotkit-embedded/src/wifi_provision/phone_ap/aha_wrapper.h b/iotkit-embedded/src/wifi_provision/phone_ap/aha_wrapper.h new file mode 100644 index 0000000..2524ab6 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/phone_ap/aha_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]); +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 */ +p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); +int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); +int HAL_Aes128_Cbc_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t blockNum, + _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); +int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb); diff --git a/iotkit-embedded/src/wifi_provision/phone_ap/awss_aha.c b/iotkit-embedded/src/wifi_provision/phone_ap/awss_aha.c new file mode 100644 index 0000000..44bacaf --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/phone_ap/awss_aha.h b/iotkit-embedded/src/wifi_provision/phone_ap/awss_aha.h new file mode 100644 index 0000000..3d92cf7 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/phone_ap/awss_wifimgr.c b/iotkit-embedded/src/wifi_provision/phone_ap/awss_wifimgr.c new file mode 100644 index 0000000..81dcf09 --- /dev/null +++ b/iotkit-embedded/src/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 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/iotkit-embedded/src/wifi_provision/phone_ap/awss_wifimgr.h b/iotkit-embedded/src/wifi_provision/phone_ap/awss_wifimgr.h new file mode 100644 index 0000000..19d4196 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/router_ap/awss_adha.c b/iotkit-embedded/src/wifi_provision/router_ap/awss_adha.c new file mode 100644 index 0000000..ae637f4 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/router_ap/awss_adha.h b/iotkit-embedded/src/wifi_provision/router_ap/awss_adha.h new file mode 100644 index 0000000..6873051 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/smartconfig/awss_smartconfig.c b/iotkit-embedded/src/wifi_provision/smartconfig/awss_smartconfig.c new file mode 100644 index 0000000..0cb4e33 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/smartconfig/awss_smartconfig.c @@ -0,0 +1,1211 @@ +#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) { + void *tmp_mutex = zc_mutex; + awss_trace("passwd err\r\n"); + memset(zconfig_data, 0, sizeof(*zconfig_data)); + zc_mutex = tmp_mutex; + awss_event_post(IOTX_AWSS_PASSWD_ERR); + AWSS_UPDATE_STATIS(AWSS_STATIS_SM_IDX, AWSS_STATIS_TYPE_PASSWD_ERR); + ret = -1; + goto exit; + } + } else { + void *tmp_mutex; + 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); + tmp_mutex = zc_mutex; + memset(zconfig_data, 0, sizeof(*zconfig_data)); + zc_mutex = tmp_mutex; + 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 (!(ieee80211[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/iotkit-embedded/src/wifi_provision/smartconfig/smartconfig_wrapper.h b/iotkit-embedded/src/wifi_provision/smartconfig/smartconfig_wrapper.h new file mode 100644 index 0000000..30f348b --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/smartconfig/smartconfig_wrapper.h @@ -0,0 +1,52 @@ +#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); +p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); +int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); +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/iotkit-embedded/src/wifi_provision/wifi_provision_api.h b/iotkit-embedded/src/wifi_provision/wifi_provision_api.h new file mode 100644 index 0000000..30bb95f --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/wifi_provision_api.h @@ -0,0 +1,85 @@ +/* + * 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 + +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. + */ +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. + */ +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 + */ +uint8_t awss_get_config_press(void); +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. + */ +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. + */ +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. + */ +int awss_stop_report_reset(void); + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif + +#endif diff --git a/iotkit-embedded/src/wifi_provision/wifi_provision_internal.h b/iotkit-embedded/src/wifi_provision/wifi_provision_internal.h new file mode 100644 index 0000000..4badb9b --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/wifi_provision_internal.h @@ -0,0 +1,83 @@ +#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 +#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/iotkit-embedded/src/wifi_provision/zero_config/awss_enrollee.c b/iotkit-embedded/src/wifi_provision/zero_config/awss_enrollee.c new file mode 100644 index 0000000..2cbb0e2 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/zero_config/awss_enrollee.h b/iotkit-embedded/src/wifi_provision/zero_config/awss_enrollee.h new file mode 100644 index 0000000..884da24 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/zero_config/awss_registrar.c b/iotkit-embedded/src/wifi_provision/zero_config/awss_registrar.c new file mode 100644 index 0000000..7e11dc9 --- /dev/null +++ b/iotkit-embedded/src/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/iotkit-embedded/src/wifi_provision/zero_config/zeroconfig_wrapper.h b/iotkit-embedded/src/wifi_provision/zero_config/zeroconfig_wrapper.h new file mode 100644 index 0000000..210a235 --- /dev/null +++ b/iotkit-embedded/src/wifi_provision/zero_config/zeroconfig_wrapper.h @@ -0,0 +1,67 @@ +#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); +p_HAL_Aes128_t HAL_Aes128_Init( + _IN_ const uint8_t *key, + _IN_ const uint8_t *iv, + _IN_ AES_DIR_t dir); + +int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes); +int HAL_Aes128_Cfb_Decrypt( + _IN_ p_HAL_Aes128_t aes, + _IN_ const void *src, + _IN_ size_t length, + _OU_ void *dst); +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/iotkit-embedded/tools/Config.in b/iotkit-embedded/tools/Config.in new file mode 100644 index 0000000..62d0e47 --- /dev/null +++ b/iotkit-embedded/tools/Config.in @@ -0,0 +1,17 @@ +mainmenu "Main Menu" +comment "Configure C-SDK for IoT Embedded Devices" + +source "tools/menu/Config.infra" +source "tools/menu/Config.dev_sign" +source "tools/menu/Config.mqtt" +source "tools/menu/Config.dynamic_register" +source "tools/menu/Config.dev_model" +source "tools/menu/Config.wrappers" +source "tools/menu/Config.atm" +source "tools/menu/Config.ota" +source "tools/menu/Config.coap" +source "tools/menu/Config.dev_reset" +source "tools/menu/Config.http" +source "tools/menu/Config.http2" +source "tools/menu/Config.wifi_provision" +source "tools/menu/Config.dev_bind" diff --git a/iotkit-embedded/tools/board/config.alios.esp8266 b/iotkit-embedded/tools/board/config.alios.esp8266 new file mode 100644 index 0000000..98acaf9 --- /dev/null +++ b/iotkit-embedded/tools/board/config.alios.esp8266 @@ -0,0 +1,19 @@ +CONFIG_ENV_CFLAGS += \ + -DBOARD_ESP8266 -u call_user_start \ + -fno-inline-functions \ + -ffunction-sections \ + -fdata-sections \ + -mlongcalls \ + -DESPOS_FOR_ESP8266 -Wl,-static \ + -DXT_USE_THREAD_SAFE_CLIB=0 \ + +CONFIG_ENV_CFLAGS += \ + -Os \ + -DCONFIG_MQTT_TX_MAXLEN=640 \ + -DCONFIG_MQTT_RX_MAXLEN=1200 \ + + +CONFIG_external_libs/mbedtls := +CONFIG_tests := + +CROSS_PREFIX := xtensa-lx106-elf- diff --git a/iotkit-embedded/tools/board/config.alios.mk3080 b/iotkit-embedded/tools/board/config.alios.mk3080 new file mode 100644 index 0000000..b0cb00d --- /dev/null +++ b/iotkit-embedded/tools/board/config.alios.mk3080 @@ -0,0 +1,15 @@ +CONFIG_ENV_CFLAGS += \ + -mcpu=cortex-m4 -march=armv7-m -mthumb \ + -mthumb-interwork -mlittle-endian \ + -fno-short-enums \ + -DCONFIG_PLATFORM_8711B -DM3 -w \ + +CONFIG_ENV_CFLAGS += \ + -Os \ + -DCONFIG_MQTT_TX_MAXLEN=640 \ + -DCONFIG_MQTT_RX_MAXLEN=1200 \ + +CONFIG_external_libs/mbedtls := +CONFIG_tests := + +CROSS_PREFIX := arm-none-eabi- diff --git a/iotkit-embedded/tools/board/config.ubuntu.x86 b/iotkit-embedded/tools/board/config.ubuntu.x86 new file mode 100644 index 0000000..eb30ce1 --- /dev/null +++ b/iotkit-embedded/tools/board/config.ubuntu.x86 @@ -0,0 +1,24 @@ +CONFIG_ENV_CFLAGS += \ + -Os -Wall \ + -g3 --coverage \ + -D_PLATFORM_IS_LINUX_ \ + -D__UBUNTU_SDK_DEMO__ \ + +CONFIG_ENV_CFLAGS += \ + -DWITH_MQTT_DYN_BUF=1 \ + -DWITH_MEM_STATS=0 \ + -DWITH_MEM_STATS_PER_MODULE=0 \ + -DWITH_MQTT_JSON_FLOW=1 \ + -DWITH_MQTT_ZIP_TOPIC=1 \ + -DWITH_MQTT_SUB_SHORTCUT=1 \ + -DSDK_TEAM_TEST \ + +CONFIG_ENV_CFLAGS += \ + -DCONFIG_MQTT_RX_MAXLEN=5000 \ + -DCONFIG_MBEDTLS_DEBUG_LEVEL=0 \ + + +CONFIG_ENV_CFLAGS += -rdynamic +CONFIG_ENV_CFLAGS += -Werror -Wno-unused + +CONFIG_ENV_LDFLAGS += -lpthread -lrt diff --git a/iotkit-embedded/tools/build-rules/_rules-complib.mk b/iotkit-embedded/tools/build-rules/_rules-complib.mk new file mode 100644 index 0000000..def6a77 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-complib.mk @@ -0,0 +1,55 @@ +.PHONY: comp-lib + +ifdef COMP_LIB +ifeq (dynamic,$(CONFIG_LIB_EXPORT)) +define Finalize_CompLib +( \ + $(CC) -shared -Os -o $(2)/lib$(3).so $(1) $(LDFLAGS); \ +) +endef +define Info_CompLib +( \ + EXIST_OBJS="$$(ls $(2) 2>/dev/null)"; \ +\ + echo -ne "\033[1;32m"; \ + printf "\r%-40s%s\n" "[AR] lib$(1).so" "<= "; \ + for i in $${EXIST_OBJS}; do \ + printf "%-40s%s\n" "" " $${i}"|$(SED) 's,$(LIBOBJ_TMPDIR)/,,g'; \ + done; \ + echo -ne "\033[0m"; \ +) +endef +else +define Finalize_CompLib +( \ + EXIST_OBJS="$$(ls $(1) 2>/dev/null)"; \ +\ + if [ "$${EXIST_OBJS}" != "" ]; then \ + $(AR) -rcs $(2)/lib$(3).a $${EXIST_OBJS}; \ + fi \ +) +endef +define Info_CompLib +( \ + EXIST_OBJS="$$(ls $(2) 2>/dev/null)"; \ +\ + echo -ne "\033[1;35m"; \ + printf "\r%-40s%s\n" "[AR] lib$(1).a" "<= "; \ + for i in $${EXIST_OBJS}; do \ + printf "%-40s%s\n" "" " $${i}"|$(SED) 's,$(LIBOBJ_TMPDIR)/,,g'; \ + done; \ + echo -ne "\033[0m"; \ +) +endef +endif # dynamic +endif # COMP_LIB + +comp-lib: toolchain +ifdef COMP_LIB + $(TOP_Q)+( \ + if [ -f $(STAMP_PRJ_CFG) ]; then true; else \ + $(call Build_CompLib,FORCE) \ + fi) +else + $(Q)true +endif diff --git a/iotkit-embedded/tools/build-rules/_rules-coverage.mk b/iotkit-embedded/tools/build-rules/_rules-coverage.mk new file mode 100644 index 0000000..e47cd14 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-coverage.mk @@ -0,0 +1,26 @@ +.PHONY: coverage lcov test + +ifneq (,$(COVERAGE_LIST)) +COVERAGE_PROGS := \( +COVERAGE_PROGS += $(COVERAGE_LIST) +COVERAGE_PROGS += \) +COVERAGE_CMD := $(RULE_DIR)/scripts/exe_coverage_progs.sh +endif + +ifeq (,$(COVERAGE_CMD)) +coverage lcov test: + @echo "COVERAGE_CMD not defined, skip" +else +coverage lcov test: +# +# SKIP --coverage existence in $(CFLAGS) checking for now +# + $(Q)$(MAKE) --no-print-directory WITH_LCOV=1 + + $(Q)OUTPUT_DIR=$(OUTPUT_DIR) bash <($(SED) '2iPROGS=$(COVERAGE_PROGS)' $(COVERAGE_CMD)) || true + + $(Q)CFLAGS=$(CFLAGS) \ + $(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") \ + bash $(RULE_DIR)/scripts/gen_lcov_report.sh + +endif diff --git a/iotkit-embedded/tools/build-rules/_rules-dist.mk b/iotkit-embedded/tools/build-rules/_rules-dist.mk new file mode 100644 index 0000000..1f7029f --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-dist.mk @@ -0,0 +1,51 @@ + +final-out: sub-mods +ifneq (1,$(WITH_LCOV)) +ifneq (,$(COMP_LIB_NAME)) + $(TOP_Q) \ + if [ ! -f $(SYSROOT_LIB)/lib$(COMP_LIB_NAME).a ] && \ + [ ! -f $(SYSROOT_LIB)/lib$(COMP_LIB_NAME).so ]; then \ + $(call Build_CompLib, FORCE) \ + fi; +endif + + $(TOP_Q) \ + if [ -f $(STAMP_PRJ_CFG) ]; then true; else \ + rm -rf $(FINAL_DIR); \ + mkdir -p $(DIST_DIR) $(FINAL_DIR); \ + for i in bin lib include; do \ + if [ -d $(OUTPUT_DIR)/usr/$${i} ]; then \ + cp -rf $(OUTPUT_DIR)/usr/$${i} $(FINAL_DIR); \ + fi; \ + done; \ + VDR_NAME=$$(grep -m 1 "VENDOR *:" $(CONFIG_TPL) 2>/dev/null|awk '{ print $$NF }'); \ + if [ "$$(ls $(IMPORT_DIR)/$${VDR_NAME}/$(PREBUILT_LIBDIR)/lib* 2>/dev/null)" != "" ]; then \ + cp -f $(IMPORT_DIR)/$${VDR_NAME}/$(PREBUILT_LIBDIR)/lib* $(FINAL_DIR)/lib; \ + fi; \ + fi + + $(TOP_Q) \ + if [ "$$(ls $(FINAL_DIR)/lib/*.a 2>/dev/null)" != "" ]; then \ + $(STRIP) $(STRIP_DBGOPT) $(FINAL_DIR)/lib/*.a 2>/dev/null || (echo "$(STRIP) $(FINAL_DIR)/lib/*.a failed!" || true); \ + fi + + $(TOP_Q) \ + if [ "$$(ls $(FINAL_DIR)/bin/ 2>/dev/null)" != "" ]; then \ + $(STRIP) $(FINAL_DIR)/bin/* 2>/dev/null || (echo "$(STRIP) $(FINAL_DIR)/bin/* failed!" || true); \ + fi + $(TOP_Q) \ + if [ "$$(ls $(FINAL_DIR)/lib/*.so 2>/dev/null)" != "" ]; then \ + $(STRIP) $(STRIP_DBGOPT) $(FINAL_DIR)/lib/*.so 2>/dev/null || (echo "$(STRIP) $(FINAL_DIR)/lib/*.so failed!" || true); \ + fi + +ifeq ($(strip $(HAS_POST_HOOK)), 1) + $(TOP_Q)+$(call $(POST_FINAL_OUT_HOOK)) +endif +ifneq (,$(filter all,$(strip $(MAKECMDGOALS)))) + $(TOP_Q)+$(call $(POST_FINAL_OUT_HOOK)) +endif + + $(TOP_Q)$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") \ + CFLAGS=$(CFLAGS) SED=$(SED) \ + bash $(RULE_DIR)/scripts/gen_rom_stats.sh +endif diff --git a/iotkit-embedded/tools/build-rules/_rules-flat.mk b/iotkit-embedded/tools/build-rules/_rules-flat.mk new file mode 100644 index 0000000..8967b55 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-flat.mk @@ -0,0 +1,148 @@ +ifneq ($(TOP_DIR),$(CURDIR)) +INTERNAL_INCLUDES += -I$(SYSROOT_INC) +INTERNAL_INCLUDES += $(foreach d, $(shell find $(SYSROOT_INC) -type d), -I$(d)) +INTERNAL_INCLUDES += -I$(TOP_DIR) +INTERNAL_INCLUDES += $(foreach d, $(shell find -L $(TOP_DIR)/$(EXPORT_DIR) -type d -not -path "*/.*" -not -path "$(TOP_DIR)/$(SHADOW_DIR)*"), -I$(d)) +INTERNAL_INCLUDES += \ +$(foreach d, \ + $(shell [ -d $(IMPORT_DIR)/$(CONFIG_VENDOR)/include ] && find -L $(IMPORT_DIR)/$(CONFIG_VENDOR)/include -type d), \ + -I$(d) \ +) +INTERNAL_INCLUDES += $(foreach mod, $(MODULE_NAME) $(HDR_REFS), \ + $(foreach d, \ + $(shell [ -d $(TOP_DIR)/$(mod) ] && \ + find -L $(TOP_DIR)/$(mod)/ -type d \ + -a -name "[^.]*" \ + -not -path "*.git*"), \ + -I$(d) \ + ) \ +) + +# INTERNAL_INCLUDES += \ + $(foreach d, \ + $(shell find $(OUTPUT_DIR)/$(MODULE_NAME) -type d -a -name "[^.]*"), \ + -I$(d) \ + ) + +INTERNAL_INCLUDES := $(strip $(sort $(INTERNAL_INCLUDES))) + +EXTERNAL_INCLUDES += $(foreach mod, $(DEPENDS), \ + $(foreach d, \ + $(shell $(SHELL_DBG) find \ + $(SYSROOT_INC)/$(mod)/ -maxdepth 2 -type d 2>/dev/null) \ + $(shell $(SHELL_DBG) find \ + $(IMPORT_VDRDIR)/include/$(mod)/ -maxdepth 2 -type d 2>/dev/null), \ + -I$(d) \ + ) \ +) +EXTERNAL_INCLUDES := $(strip $(EXTERNAL_INCLUDES)) +endif # ifneq ($(TOP_DIR),$(CURDIR)) + +ifeq (dynamic,$(strip $(CONFIG_LIB_EXPORT))) +CFLAGS += -fPIC +endif + +#CFLAGS := $(sort $(strip $(CFLAGS))) + +LDFLAGS += -L$(SYSROOT_LIB) +ifeq (y,$(shell [ -e $(TOP_DIR)/$(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR) ] && echo y)) +LDFLAGS += -L$(TOP_DIR)/$(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR) +endif + +LDFLAGS += $(foreach d,$(DEPENDS_$(MODULE_NAME)),$(REF_LDFLAGS_$(d))) + +WATCHED_VARS = \ + TARGET \ + CFLAGS \ + CC \ + LDFLAGS \ + CURDIR \ + INTERNAL_INCLUDES \ + DEPENDS \ + MAKECMDGOALS \ + EXTERNAL_INCLUDES \ + LIBA_TARGET \ + LIBSO_TARGET \ + +ALL_TARGETS := $(TARGET) $(LIBSO_TARGET) $(LIBA_TARGET) $(firstword $(KMOD_TARGET)) + +ifneq (,$(strip $(PKG_SWITCH))) +all: $(ALL_TARGETS) +else +all: + $(Q)true +endif + +clean: + $(Q)rm -f \ + $(strip \ + $(ALL_TARGETS) $(OBJS) $(LIB_OBJS) \ + $(OBJS:.o=.d) $(LIB_OBJS:.o=.d) \ + $(LIB_OBJS:.o=.gcno) $(LIB_OBJS:.o=.gcda) \ + ) \ + *.o.e *.d *.o *.a *.so *.log *.gc* + +%.o: %.c $(HD_MAKEFILE) + @$(call Brief_Log,"CC") + $(call Inspect_Env,$(WATCHED_VARS)) + $(Q) \ + set -o pipefail; \ + $(CC) -I$(CURDIR) \ + $(INTERNAL_INCLUDES) \ + $(EXTERNAL_INCLUDES) \ + $(CFLAGS) \ + -c -o $@ $< +ifneq (,$(OBJCOPY_FLAGS)) + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $@ +endif + +NODEP_LIST = \ + $(SYSROOT_INC)/git_version.h \ + $(SYSROOT_INC)/platform.h \ + $(SYSROOT_INC)/product.h \ + $(SYSROOT_INC)/product_config.h \ + +ifneq (,$(findstring gcc,$(CC))) +ifeq (,$(filter modinfo,$(MAKECMDGOALS))) +%.d: %.c + @ \ +( \ + D=$$(dirname $<|$(SED) 's,$(TOP_DIR),$(OUTPUT_DIR),1'); \ + F=$$(basename $<); \ + mkdir -p $${D}; \ + $(CC) -MM -I$(CURDIR) \ + $(INTERNAL_INCLUDES) \ + $(EXTERNAL_INCLUDES) \ + $(CFLAGS) \ + $< > $${D}/$${F}.$$$$; \ + $(SED) -i 's!$(shell basename $*)\.o[ :]!$*.o:!1' $${D}/$${F}.$$$$; \ + mv $${D}/$${F}.$$$$ $@; \ +) +endif +endif + +%.o: %.cpp + @$(call Brief_Log,"CC") + $(call Inspect_Env,$(WATCHED_VARS)) + $(Q)$(CXX) -I$(CURDIR) \ + $(INTERNAL_INCLUDES) \ + $(EXTERNAL_INCLUDES) \ + $(CFLAGS) \ + -c -o $@ $< + +ifneq (,$(findstring gcc,$(CC))) +%.d: %.cpp + @ \ + $(CXX) -MM -I$(CURDIR) \ + $(INTERNAL_INCLUDES) \ + $(EXTERNAL_INCLUDES) \ + $(CFLAGS) \ + $< > $@.$$$$; \ + $(foreach D,$(NODEP_LIST),$(SED) -i 's,$(D),,g' $@.$$$$;) \ + $(SED) 's,\($*\)\.o[ :]*,\1.o $@: ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$; +endif + +include $(RULE_DIR)/_rules-libs.mk +include $(RULE_DIR)/_rules-prog.mk +include $(RULE_DIR)/_rules-kmod.mk diff --git a/iotkit-embedded/tools/build-rules/_rules-kmod.mk b/iotkit-embedded/tools/build-rules/_rules-kmod.mk new file mode 100644 index 0000000..8df3d3c --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-kmod.mk @@ -0,0 +1,35 @@ +ifdef KMOD_TARGET +KMOD_NAME := $(subst .o,,$(obj-m)) +KMOD_OBJS := $(foreach mod, $(KMOD_NAME), $($(mod)-objs)) +KMOD_SRCS := $(subst .o,.c,$(KMOD_OBJS)) +KMOD_BUILD_DIR := $(CURDIR)/build-$(shell $(SHELL_DBG) basename $(CURDIR))-kmod +KMOD_MAKEFILE := $(KMOD_BUILD_DIR)/Makefile + +$(firstword $(KMOD_TARGET)): $(KMOD_SRCS) + $(Q)rm -rf $(KMOD_BUILD_DIR) && mkdir -p $(KMOD_BUILD_DIR) + $(Q)cp -f $(KMOD_SRCS) $(KMOD_BUILD_DIR) + $(Q)echo "EXTRA_CFLAGS += " \ + "-I$(CURDIR)" \ + "$(INTERNAL_INCLUDES)" \ + | $(SED) 's/-I/\\\n -I/g' \ + >> $(KMOD_MAKEFILE) + $(Q)echo "" >> $(KMOD_MAKEFILE) + $(Q)echo "obj-m := $(obj-m)" >> $(KMOD_MAKEFILE) + $(Q)echo "" >> $(KMOD_MAKEFILE) + $(Q) \ + $(foreach mod, $(KMOD_NAME), \ + echo "$(mod)-objs := $($(mod)-objs)" \ + | $(SED) 's/ [_a-z]*\.o/ \\\n &/g' \ + >> $(KMOD_MAKEFILE); \ + echo "" >> $(KMOD_MAKEFILE); \ + ) + @$(call Brief_Log,"CC",$(KMOD_TARGET)) + $(Q) \ + LDFLAGS=""; \ + $(MAKE) -C $(KERNEL_DIR) M=$(KMOD_BUILD_DIR) CROSS_COMPILE=$(CROSS_PREFIX) modules + $(Q)cp -f $(KMOD_BUILD_DIR)/*.ko $(CURDIR) + $(Q)mkdir -p $(SYSROOT_LIB) + $(Q)install -m 0755 $(KMOD_BUILD_DIR)/*.ko $(SYSROOT_LIB) + +endif # ifdef KMOD_TARGET + diff --git a/iotkit-embedded/tools/build-rules/_rules-libs.mk b/iotkit-embedded/tools/build-rules/_rules-libs.mk new file mode 100644 index 0000000..bae9a4f --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-libs.mk @@ -0,0 +1,102 @@ +ifndef LIBA_TARGET +ifndef LIBSO_TARGET +LIB_SRCS := +endif +endif + +VPATH := $(TOP_DIR)/$(MODULE_NAME) +LIB_SRCS ?= $(foreach M,*.c */*.c */*/*.c,$(wildcard $(TOP_DIR)/$(MODULE_NAME)/$(M))) $(wildcard *.c) + +.PHONY : cmake + +cmake: + + $(Q)$(foreach V,$(INFO_ENV_VARS),$(subst -,_,$(V))="$($(V))") \ + $(foreach V,$(TARGET),$(subst -,_,SRCS_$(V))="$(SRCS_$(V))") \ + bash $(if $(TOP_Q),,-x) $(RULE_DIR)/scripts/gen_sub_cmake.sh $(TOP_DIR)/${MODULE_NAME}/CMakeLists.txt + +ifdef Extra_CMake_Head + @rm -f $(OUTPUT_DIR)/$(STAMP_CMAKE) + @$(call Extra_CMake_Head, >> $(OUTPUT_DIR)/$(STAMP_CMAKE)) + @cat $(TOP_DIR)/${MODULE_NAME}/CMakeLists.txt >> $(OUTPUT_DIR)/$(STAMP_CMAKE) + @$(call Extra_CMake_Foot, >> $(OUTPUT_DIR)/$(STAMP_CMAKE)) + @mv $(OUTPUT_DIR)/$(STAMP_CMAKE) $(TOP_DIR)/${MODULE_NAME}/CMakeLists.txt +endif + +ifdef LIB_SRCS_PATTERN +SRC_LIST := $(foreach M,$(LIB_SRCS_PATTERN),$(shell ls $(TOP_DIR)/$(MODULE_NAME)/$(M) 2>/dev/null)) +LIB_SRCS := $(SRC_LIST) +endif + +LIB_SRCS := $(filter-out $(foreach M,$(LIB_SRCS_EXCLUDE),$(TOP_DIR)/$(MODULE_NAME)/$(M)),$(LIB_SRCS)) +LIB_OBJS := $(LIB_SRCS:.c=.o) +LIB_OBJS := $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(LIB_OBJS)) + +sinclude $(LIB_OBJS:.o=.d) + +ifdef LIBA_TARGET +.PHONY: StaticLib_Install + +ifeq (1,$(words $(LIBA_TARGET))) + +$(LIBA_TARGET) :: $(LIB_OBJS) + @$(call Brief_Log,"AR") + $(call Inspect_Env,$(WATCHED_VARS)) + $(Q)rm -f $@ +ifdef CONFIG_LIBOBJ_STRIP + @$(call Brief_Log,"ST") + $(TOP_Q)$(STRIP) $(STRIP_DBGOPT) $(LIB_OBJS) +endif + $(TOP_Q) \ + if [ "$$(echo "$(LIB_OBJS)"|awk '{ print NF }')" != "0" ]; then \ + $(AR) -rcs $@ $(LIB_OBJS); \ + fi + +$(LIBA_TARGET) :: StaticLib_Install + $(Q)mkdir -p $(LIBOBJ_TMPDIR)/$(MODULE_NAME) +ifneq (,$(strip $(LIB_OBJS))) +ifneq ($(LIBA_TARGET),$(LIBA_SKIP_COMBO)) + $(Q)cp -f $(LIB_OBJS) $(LIBOBJ_TMPDIR)/$(MODULE_NAME) 2>/dev/null || true +endif +endif + $(Q)mkdir -p $(SYSROOT_LIB) + $(Q)if [ -f $@ ]; then cp -f $@ $(SYSROOT_LIB); fi + $(call Copy_Headers, $(LIB_HEADERS),$(SYSROOT_INC),$(LIB_HDRS_DIR)) + +else + +$(foreach t,$(sort $(LIBA_TARGET)),$(t)): FORCE + $(Q) \ + $(MAKE) LIBA_TARGET=$@ \ + LIB_SRCS="$(LIB_SRCS_$(subst .a,,$(subst lib,,$@)))" \ + LIB_SRCS_PATTERN="$(LIB_SRCS_PATTERN_$(subst .a,,$(subst lib,,$@)))" \ + + +endif # ifeq (1,$(words $(LIBA_TARGET))) + +endif # ifdef LIBA_TARGET + +ifdef LIBSO_TARGET +.PHONY: DynamicLib_Install + +$(LIBSO_TARGET) :: SELF_LIBNAME = $(subst lib,,$(subst .so,,$(LIBSO_TARGET))) +$(LIBSO_TARGET) :: LDFLAGS := $(filter-out -l$(SELF_LIBNAME), $(LDFLAGS)) +$(LIBSO_TARGET) :: $(LIB_OBJS) $(foreach d,$(DEPENDS_$(MODULE_NAME)),$(SYSROOT_LIB)/$(LIBA_TARGET_$(d))) + @$(call Brief_Log,"CC") + $(call Inspect_Env,$(WATCHED_VARS)) + $(Q)$(CC) -shared -Os \ + $(CFLAGS) \ + $(RPATH_CFLAGS) \ + -o $@ \ + $(LIB_OBJS) \ + -Wl,--start-group $(LDFLAGS) -Wl,--end-group + +$(LIBSO_TARGET) :: DynamicLib_Install + $(Q)mkdir -p $(LIBOBJ_TMPDIR)/$(shell $(SHELL_DBG) basename $(CURDIR)) + $(Q)cp -f $(LIB_OBJS) $(LIBOBJ_TMPDIR)/$(shell $(SHELL_DBG) basename $(CURDIR)) + $(Q)mkdir -p $(SYSROOT_LIB) + $(Q)install -m 0755 $@ $(SYSROOT_LIB) + $(call Copy_Headers, $(LIB_HEADERS),$(SYSROOT_INC),$(LIB_HDRS_DIR)) + +endif # ifdef LIBSO_TARGET + diff --git a/iotkit-embedded/tools/build-rules/_rules-modinfo.mk b/iotkit-embedded/tools/build-rules/_rules-modinfo.mk new file mode 100644 index 0000000..4f54ef5 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-modinfo.mk @@ -0,0 +1,58 @@ +.PHONY: modinfo + +modinfo: + @true + +MODINFO_VARS := \ + EXTRA_SRCS \ + PKG_SWITCH \ + ORIGIN \ + PKG_SOURCE \ + PKG_BRANCH \ + PKG_REVISION \ + PKG_UPSTREAM \ + REF_CFLAGS \ + REF_LDFLAGS \ + LDFLAGS \ + LIBA_TARGET \ + LIB_OBJS \ + TARGET \ + LIBSO_TARGET \ + +ifneq (,$(CONFIG_$(MODULE_NAME))) +$(if $(filter modinfo,$(MAKECMDGOALS)), \ + $(if $(strip $(DEPENDS)), \ + $(info DEPENDS_$(MODULE_NAME) = $(strip $(DEPENDS))) \ + $(info CONFIG_$(MODULE_NAME) = $(CONFIG_$(MODULE_NAME))) \ + ) \ +) + +$(if $(filter modinfo,$(MAKECMDGOALS)), \ + $(foreach v, $(MODINFO_VARS), \ + $(if $(strip $($(v))), \ + $(info $(v)_$(MODULE_NAME) = $(strip $($(v)))) \ + ) \ + ) \ +) + +ifeq (0,$(words $(TARGET))) +else +ifeq (1,$(words $(TARGET))) + +$(if $(filter modinfo,$(MAKECMDGOALS)), \ + $(info SRCS_$(TARGET) = $(if $(SRCS_$(TARGET)), \ + $(subst $(TOP_DIR)/,,$(SRCS_$(TARGET))), \ + $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(SRCS)))) \ +) + +else + +$(if $(filter modinfo,$(MAKECMDGOALS)), \ + $(foreach v, $(TARGET), \ + $(info SRCS_$(v) = $(SRCS_$(v))) \ + ) \ +) + +endif +endif +endif diff --git a/iotkit-embedded/tools/build-rules/_rules-origin.mk b/iotkit-embedded/tools/build-rules/_rules-origin.mk new file mode 100644 index 0000000..5efea63 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-origin.mk @@ -0,0 +1,120 @@ +CFLAGS := $(filter-out -Werror,$(CFLAGS)) +LDFLAGS := + +.PHONY: config build install post-install + +ORIGIN_Q ?= @ +ifeq ($(strip $(PKG_SWITCH)),y) +all : +ifeq ($(PKG_SOURCE),) +$(error PKG_SOURCE for $(PKG_NAME) cannot be found!) +endif + + $(ORIGIN_Q) \ + MESSAGE=$(strip $(if $(filter 0 1,$(MAKELEVEL)), \ + "\r$(PKG_NAME) already pre-built at $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)\n","")); \ + if [ "$(LIBA_TARGET)" != "" -a -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(LIBA_TARGET) ] || \ + [ "$(LIBSO_TARGET)" != "" -a -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(LIBSO_TARGET) ]; then \ + echo -ne $${MESSAGE}; \ + cp -P -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/{$(LIBA_TARGET),$(LIBSO_TARGET)*} \ + $(SYSROOT_LIB) 2>/dev/null; \ + for t in $(TARGET); do \ + cp -f $(IMPORT_VDRDIR)/$(PREBUILT_BINDIR)/$${t} $(SYSROOT_BIN); \ + done; \ + touch $(STAMP_SHIELD); \ + fi + + $(ORIGIN_Q) \ + MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already unpacked\n",""); \ + if [ -f $(STAMP_SHIELD) ]; then true; \ + elif [ -f $(STAMP_UNPACK) ]; then \ + echo -ne $${MESSAGE}; \ + else \ + rm -rf $(PKG_NAME)* && \ + if [ -f $(PKG_SOURCE) ]; then \ + tar xf $(PKG_SOURCE) -C . && \ + for i in $(wildcard *.patch); do \ + cd $(PKG_NAME)* && patch -d . -p 1 < ../$${i} && cd $${OLDPWD}; \ + done \ + fi \ + && touch $(STAMP_UNPACK); \ + fi + + $(ORIGIN_Q) \ + MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already configured\n",""); \ + if [ -f $(STAMP_SHIELD) ]; then true; \ + elif [ -f $(STAMP_CONFIG) ]; then \ + echo -ne $${MESSAGE}; \ + else \ + if grep -q 'config *:' $(HD_MAKEFILE); then \ + export SHELL=$(SHELL); \ + $(MAKE) config -f $(HD_MAKEFILE); \ + else \ + cd $(PKG_NAME)* && ( \ + ./configure \ + --prefix=$(OUTPUT_DIR)/usr \ + --host=$(HOST) \ + --target=$(shell $(SHELL_DBG) basename $(CROSS_PREFIX) 2>/dev/null) \ + --enable-static --enable-shared \ + || \ + ./configure \ + --prefix=$(OUTPUT_DIR)/usr \ + --host=$(HOST) \ + --target=$(shell $(SHELL_DBG) basename $(CROSS_PREFIX) 2>/dev/null|cut -d'-' -f1) \ + --enable-static --enable-shared \ + ) && cd $${OLDPWD}; \ + fi \ + && touch $(STAMP_CONFIG); \ + fi + + $(ORIGIN_Q) \ + MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already built\n",""); \ + if [ -f $(STAMP_SHIELD) ]; then true; \ + elif [ -f $(STAMP_BUILD) ]; then \ + echo -ne $${MESSAGE}; \ + else \ + if grep -q 'build *:' $(HD_MAKEFILE); then \ + $(MAKE) build -f $(HD_MAKEFILE); \ + else \ + if [ -d $(PKG_NAME)* ]; then \ + cd $(PKG_NAME)* && $(MAKE) -j8 all && cd ..; \ + fi \ + fi \ + && touch $(STAMP_BUILD); \ + fi + + $(ORIGIN_Q) \ + MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already installed\n",""); \ + if [ -f $(STAMP_SHIELD) ]; then true; \ + elif [ -f $(STAMP_INSTALL) ]; then \ + echo -ne $${MESSAGE}; \ + else \ + if grep -q 'install *:' $(HD_MAKEFILE); then \ + $(MAKE) install -f $(HD_MAKEFILE); \ + else \ + if [ -d $(PKG_NAME)* ]; then \ + cd $(PKG_NAME)* && $(MAKE) install && cd ..; \ + fi \ + fi \ + && touch $(STAMP_INSTALL); \ + fi + + $(ORIGIN_Q) \ + MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already post-installed\n",""); \ + if [ -f $(STAMP_POSTINS) ]; then \ + echo -ne $${MESSAGE}; \ + else \ + if grep -q 'post-install *:' $(HD_MAKEFILE); then \ + $(MAKE) post-install -f $(HD_MAKEFILE); \ + fi \ + && touch $(STAMP_POSTINS); \ + fi + +clean-prepare: + $(Q)rm -f $(STAMP_BUILD) $(STAMP_INSTALL) $(STAMP_POSTINS) +else +all: + $(Q)true +clean: + $(Q)true +endif # ifeq ($(strip $(PKG_SWITCH)),y) diff --git a/iotkit-embedded/tools/build-rules/_rules-prefix.mk b/iotkit-embedded/tools/build-rules/_rules-prefix.mk new file mode 100644 index 0000000..68c9066 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-prefix.mk @@ -0,0 +1,25 @@ +ifeq (,$(findstring llvm,$(CC))) +CFLAGS := "$(sort $(CFLAGS) $(CONFIG_ENV_CFLAGS))" +else +CFLAGS := "$(CFLAGS) $(CONFIG_ENV_CFLAGS)" +endif + +LDFLAGS := $(sort $(LDFLAGS) $(CONFIG_ENV_LDFLAGS)) + +ifeq (dynamic,$(CONFIG_LIB_EXPORT)) +CFLAGS := $(filter-out --coverage,$(CFLAGS)) +endif + +MAKE_ENV_VARS := \ +$(foreach v, \ + $(shell grep -o 'CONFIG_ENV_[_A-Z]*' $(CONFIG_TPL) 2>/dev/null), \ + $(subst CONFIG_ENV_,,$(v)) \ +) + +# $(eval ...) causes '$' in CFLAGS lost +MAKE_ENV_VARS := $(sort $(filter-out CFLAGS LDFLAGS,$(MAKE_ENV_VARS))) + +$(foreach V, \ + $(MAKE_ENV_VARS), \ + $(eval export $(V) := $(sort $(CONFIG_ENV_$(V)))) \ +) diff --git a/iotkit-embedded/tools/build-rules/_rules-prog.mk b/iotkit-embedded/tools/build-rules/_rules-prog.mk new file mode 100644 index 0000000..72c7958 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-prog.mk @@ -0,0 +1,74 @@ +ifeq (1,$(words $(TARGET))) +SRCS := $(if $(SRCS_$(TARGET)),$(SRCS_$(TARGET)),$(SRCS)) +endif + +VPATH := $(TOP_DIR)/$(MODULE_NAME) +SRCS ?= $(foreach M,*.c */*.c */*/*.c,$(wildcard $(TOP_DIR)/$(MODULE_NAME)/$(M))) $(wildcard *.c) +OBJS := $(SRCS:.c=.o) +OBJS := $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(OBJS)) + +ifdef SRCS_PATTERN +PROG_LIST := $(foreach M,$(SRCS_PATTERN),$(shell ls $(TOP_DIR)/$(MODULE_NAME)/$(M) 2>/dev/null)) +SRCS := $(PROG_LIST) +OBJS := $(PROG_LIST:.c=.o) +OBJS := $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(OBJS)) +endif + +ifdef TARGET + +ifneq (modinfo,$(MAKECMDGOALS)) +ifneq (clean,$(MAKECMDGOALS)) +sinclude $(OBJS:.o=.d) +endif +endif + +ifdef LIBA_TARGET +$(TARGET): $(LIBA_TARGET) + +ifeq (,$(filter $(MODULE_NAME),$(COMP_LIB_COMPONENTS))) +LDFLAGS := -l$(subst .a,,$(subst lib,,$(LIBA_TARGET))) $(LDFLAGS) +endif +endif + +ifdef LIBSO_TARGET +$(TARGET): $(LIBSO_TARGET) + +LDFLAGS := -l$(subst .so,,$(subst lib,,$(LIBSO_TARGET))) $(LDFLAGS) +endif + +LDFLAGS += $(sort $(CONFIG_ENV_LDFLAGS)) + +ifneq (,$(filter %.cpp %.cc,$(SRCS))) +CCLD := $(CXX) +else +CCLD := $(CC) +endif + +ifeq (1,$(words $(TARGET))) + +$(TARGET): $(OBJS) FORCE + $(call Inspect_Env,$(WATCHED_VARS)) + $(Q)$(MAKE) comp-lib 2>/dev/null || true + $(Q) \ +( \ + if [ "$(strip $(CC))" = "gcc" -o "$(strip $(CC))" = "i686-w64-mingw32-gcc" ] \ + || [ "$(filter -D_PLATFORM_IS_LINUX_,$(CFLAGS))" != "" ] \ + || [ "$(filter -D_PLATFORM_IS_WINDOWS_,$(CFLAGS))" != "" ]; then \ + $(call Brief_Log,"LD"); \ + mkdir -p $(OUTPUT_DIR)${bindir}; \ + $(CCLD) $(CFLAGS) -o $@ \ + $(RPATH_CFLAGS) \ + $(OBJS) \ + $(LDFLAGS) && \ + cp -f $@ $(OUTPUT_DIR)${bindir}; \ + fi; \ +) + +else + +$(foreach t,$(sort $(TARGET)),$(t)): FORCE + $(Q)$(MAKE) TARGET=$@ OBJS="$(SRCS_$@:.c=.o)" + +endif + +endif # ifdef TARGET diff --git a/iotkit-embedded/tools/build-rules/_rules-repo.mk b/iotkit-embedded/tools/build-rules/_rules-repo.mk new file mode 100644 index 0000000..a97d207 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-repo.mk @@ -0,0 +1,16 @@ +OPS_CMDLINE_V := \ + PACKAGE_DIR \ + TOP_DIR \ + STAMP_BLD_VAR \ + +OPS_SCRIPT := \ + $(strip $(foreach V, $(OPS_CMDLINE_V), $(V)="$($(V))")) \ + $(SHELL) \ + $(RULE_DIR)/scripts/ops_repository.sh \ + $(STAMP_BLD_VAR) + +repo-list: config + $(TOP_Q)$(OPS_SCRIPT) list + +repo-update: config + $(TOP_Q)$(OPS_SCRIPT) update diff --git a/iotkit-embedded/tools/build-rules/_rules-submods.mk b/iotkit-embedded/tools/build-rules/_rules-submods.mk new file mode 100644 index 0000000..cc9bb3c --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-submods.mk @@ -0,0 +1,160 @@ +SUB_LOG_OPTION := $(if $(Q),,| tee -a $(OUTPUT_DIR)/$${i}/$(COMPILE_LOG)) +ALL_LOG_OPTION := $(if $(Q),,| tee -a $(COMPILE_LOG)) + +sub-mods: toolchain config + $(Q) \ + if [ -f $(STAMP_ONE_MK) ] && [ "$(MAKECMDGOALS)" = "" ]; then \ + CORE_NUM=$$(cat /proc/cpuinfo 2>/dev/null| grep processor | tail -1 | awk '{ print $$NF }'); \ + JOBS_NUM=32; \ + if [ "$${CORE_NUM}" != "" ]; then JOBS_NUM=$${CORE_NUM}; fi; \ + if [ "$(Q)" != "@" ]; then JOBS_NUM=0; fi; \ + rm -rf $(OUTPUT_DIR)${bindir}/* && \ + if [ -f $(STAMP_LCOV) ] && [ "$(WITH_LCOV)" != "1" ]; then \ + $(MAKE) --no-print-directory clean; \ + fi && \ + if ([ ! -f $(STAMP_LCOV) ] && [ "$(WITH_LCOV)" = "1" ]) || [ $(TOP_DIR)/make.settings -nt $(DIST_DIR) ]; then \ + $(MAKE) --no-print-directory clean; \ + fi && \ + $(MAKE) --no-print-directory -j$$((JOBS_NUM + 1)) -f $(STAMP_ONE_MK) && \ + TMPD=$$(mktemp -d) && \ + rm -rf $(LIBOBJ_TMPDIR) $${TMPD} && \ + cp -rf $(OUTPUT_DIR) $${TMPD} && \ + rm -rf $${TMPD}/{usr,stamps} && \ + mv $${TMPD} $(LIBOBJ_TMPDIR); \ + else \ + if [ -f $(STAMP_PRJ_CFG) ]; then true; else \ + set -o pipefail; \ + for i in \ + $(SUBDIRS); do \ + if [ ! -d $${i} ]; then continue; fi; \ + $(MAKE) --no-print-directory Q=$(Q) $${i} 2>&1 $(SUB_LOG_OPTION); \ + RETVAL=$$?; \ + if [ $${RETVAL} != 0 ]; then exit $${RETVAL}; fi; \ + done 2>&1 $(ALL_LOG_OPTION); \ + fi; \ + fi + +TOP_BUILD_VARS := \ + CC LD AR \ + CFLAGS LDFLAGS \ + PACKAGE_DIR \ + IMPORT_DIR \ + EXPORT_DIR \ + TOP_DIR \ + RULE_DIR \ + CONFIG_VENDOR \ + COMP_LIB \ + COMP_LIB_COMPONENTS \ + $(CROSS_CANDIDATES) \ + $(MAKE_ENV_VARS) \ + INSTALL_DIR \ + INSTALL_LIB_DIR \ + SYSROOT_INC \ + KERNEL_DIR \ + MAKE_ENV_VARS \ + CROSS_PREFIX \ + CROSS_CANDIDATES \ + ALL_SUB_DIRS \ + WIN32_CMAKE_SKIP \ + NOEXEC_CMAKE_DIRS \ + +CMDLINE_VARS := \ + HD_MAKEFILE \ + MAKE_SEGMENT \ + OUTPUT_DIR \ + PACKAGE_DIR \ + STAMP_BLD_ENV \ + STAMP_UNPACK \ + TOP_DIR \ + RULE_DIR \ + +# When TOP_BUILD_VARS like $(CFLAGS) contains special character '$' +# simply echo its value into 'Makefile' will cause '$' lost when GNU make read in again +# +$(STAMP_BLD_ENV): $(TOP_DIR)/makefile $(shell ls $(CONFIG_TPL) 2>/dev/null) \ + $(wildcard $(RULE_DIR)/*.mk) \ + $(shell grep "^ *include" $(TOP_DIR)/$(TOP_MAKEFILE)|awk '{ print $$NF }'|$(SED) '/^\$$/d') + @rm -f $@ + @$(foreach V, \ + $(sort $(TOP_BUILD_VARS)), \ + echo "$(V) := $(sort $($(V)))"|$(SED) 's:\$$:$$$$:g' >> $(STAMP_BLD_ENV); \ + ) + @echo "COMP_LIB_FILES := $(foreach V,$(COMP_LIB_COMPONENTS), $(LIBA_TARGET_$(V)))" >> $@ + +# note: +# $(SED) -i "/CONFIG_$${i//\//\\/}.*/d" $(CONFIG_TPL); +# above +# $(SED) -i "1iCONFIG_$${i} = y" $(CONFIG_TPL) +# was removed since modules will be skipped in some cases + +$(STAMP_BLD_VAR): $(foreach d,$(ALL_SUB_DIRS),$(d)/$(MAKE_SEGMENT)) $(STAMP_BLD_ENV) $(wildcard $(RULE_DIR)/*.mk) + $(TOP_Q) \ +( \ + if [ ! -f $(STAMP_BLD_VAR) ]; then echo ""; VERBOSE=1; fi; \ + rm -f $(STAMP_BLD_VAR); \ + for i in $(shell echo "$(ALL_SUB_DIRS)"|tr ' ' '\n'|sort -u); do \ + if [ "$${VERBOSE}" != "" ]; then \ + printf "CONFIGURE .............................. [%s]\n" $${i}; \ + $(SED) -i "1iCONFIG_$${i} = y" $(CONFIG_TPL); \ + if ! grep -q "target-$${i}:" $(STAMP_POST_RULE) 2>/dev/null; then \ + echo "target-$${i}:; @true" >> $(STAMP_POST_RULE); \ + fi; \ + fi; \ + $(foreach V, $(CMDLINE_VARS), $(V)="$($(V))") \ + bash $(RULE_DIR)/pre-build.sh $${i} makefile-only > /dev/null; \ + if [ -d $(OUTPUT_DIR)/$${i} ]; then \ + $(MAKE) -s -C $(OUTPUT_DIR)/$${i} modinfo > /dev/null; \ + if [ $$? = 0 ]; then \ + $(MAKE) --no-print-directory -s -C $(OUTPUT_DIR)/$${i} modinfo >> $(STAMP_BLD_VAR); \ + else \ + echo ""; \ + echo "ERROR detected in '$${i}/$(MAKE_SEGMENT)'..."|grep --color '.*'; \ + echo ""; \ + rm -f $(STAMP_BLD_VAR) $(STAMP_PRJ_CFG); \ + exit 13; \ + fi \ + fi \ + done; \ + sort -o $(STAMP_BLD_VAR) $(STAMP_BLD_VAR); \ + if [ "$${VERBOSE}" != "" ]; then echo ""; fi; \ +) + +pre-build: MOD = $(subst target-,,$(filter-out $@,$(MAKECMDGOALS))) +pre-build: $(STAMP_BLD_ENV) + $(TOP_Q)rm -f $(OUTPUT_DIR)/$(MOD)/$(STAMP_UNPACK) + $(if $(filter 0,$(MAKELEVEL)),,@) \ + $(strip $(foreach V, $(CMDLINE_VARS), $(V)="$($(V))") \ + PKG_SOURCE="$(PKG_SOURCE_$(MOD))" \ + PKG_BRANCH="$(PKG_BRANCH_$(MOD))" \ + PKG_REVISION="$(PKG_REVISION_$(MOD))" \ + PKG_UPSTREAM="$(PKG_UPSTREAM_$(MOD))" \ + PKG_SWITCH="$(PKG_SWITCH_$(MOD))" \ + ) \ + $(if $(filter 0,$(MAKELEVEL)),VERBOSE_PRE_BLD=1) \ + bash $(RULE_DIR)/pre-build.sh $(subst target-,,$(filter-out $@,$(MAKECMDGOALS))) + +.PHONY: $(ALL_SUB_DIRS) + +$(ALL_SUB_DIRS): ALL_LOG_OPT = $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(COMPILE_LOG)) +$(ALL_SUB_DIRS): SUB_LOG_OPT = $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$@/$(COMPILE_LOG)) + +$(ALL_SUB_DIRS): $(if $(filter 0,$(MAKELEVEL)),toolchain) $(STAMP_BLD_VAR) + $(TOP_Q)rm -f $(STAMP_PRJ_CFG) + $(TOP_Q)$(MAKE) --no-print-directory pre-build target-$@ +ifeq (0,$(MAKELEVEL)) + $(Q)$(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$@ clean +endif + $(Q) \ + if [ "$$( $(call Require_Build,$@) )" = "TRUE" ]; then \ + $(call Build_Depends,$@) && \ + $(call Build_CompLib,$@) && \ + $(call Update_Extra_Srcs,$(EXTRA_SRCS_$@),$@) && \ + $(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$@ all $(SUB_LOG_OPT) $(ALL_LOG_OPT) && \ + if [ "$$(echo $(ORIGIN_$@))" != "" ]; then \ + touch $(OUTPUT_DIR)/$@/{$(STAMP_UNPACK),$(STAMP_CONFIG),$(STAMP_BUILD),$(STAMP_INSTALL)}; \ + fi \ + else \ + echo -ne "\r$$(printf '%40s' '')\r"; \ + fi + + @mkdir -p $(STAMP_DIR) && touch $(STAMP_DIR)/$$(echo "$@"|$(SED) 's:/:~:g').build.done diff --git a/iotkit-embedded/tools/build-rules/_rules-top.mk b/iotkit-embedded/tools/build-rules/_rules-top.mk new file mode 100644 index 0000000..71bf144 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/_rules-top.mk @@ -0,0 +1,216 @@ +.PHONY: doc detect config reconfig toolchain sub-mods final-out env cmake one help + +all: detect config toolchain sub-mods final-out + $(TOP_Q) \ + if [ -f $(STAMP_PRJ_CFG) ]; then \ + $(RECURSIVE_MAKE) toolchain; \ + rm -f $(STAMP_PRJ_CFG); \ + fi + @rm -rf $(STAMP_DIR) + +RESET_ENV_VARS := \ + CROSS_PREFIX \ + CFLAGS \ + HOST \ + LDFLAGS \ + +help: + @echo -e "\033[1;37m[$(RULE_DIR)/docs]\e[0m" + @echo "" + @cat $(RULE_DIR)/docs/Help.md + @echo "" + +doc: + $(TOP_Q)rm -rf $(DOXYGEN_DIR)/html; mkdir -p $(DOXYGEN_DIR) + $(TOP_Q) \ + $(SED) \ + -e 's:^PROJECT_NAME.*:PROJECT_NAME = $(PRJ_NAME):g;' \ + -e 's:^PROJECT_NUMBER.*:PROJECT_NUMBER = $(PRJ_VERSION):g;' \ + -e 's:^OUTPUT_DIRECTORY.*:OUTPUT_DIRECTORY = $(DOXYGEN_DIR):g;' \ + build-rules/misc/Doxyfile.tpl > $(OUTPUT_DIR)/.doxygen.cfg + $(TOP_Q)doxygen $(OUTPUT_DIR)/.doxygen.cfg + +detect: + @if [ -d .git ]; then \ + mkdir -p .git/hooks; \ + for i in $(RULE_DIR)/hooks/*; do \ + cp -f $$i .git/hooks && chmod a+x .git/hooks/$$(basename $$i); \ + done; \ + fi + +prune: + @echo "$(TOP_DIR).pkgs directory removed!"|grep --color ".*" + @rm -rf $(TOP_DIR).pkgs + @$(MAKE) --no-print-directory distclean + +unzip: config $(STAMP_BLD_VAR) + @echo "Components: " + @echo "" + @for i in $(ALL_SUB_DIRS); do \ + $(MAKE) --no-print-directory pre-build target-$${i} ; \ + echo -ne "\r. $${i}"; \ + echo -e " "; \ + done + @echo "" + +cmake: + $(TOP_Q)$(MAKE) -s distclean + $(TOP_Q)$(MAKE) -s DEFAULT_BLD=$(RULE_DIR)/misc/config.generic.cmake config + $(TOP_Q)$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") CFLAGS=$(CFLAGS) \ + SEP_LIBS="$$(grep -m 1 '^COMP_LIB_FILES' $(STAMP_BLD_ENV) | cut -d' ' -f3-)" \ + bash $(if $(TOP_Q),,-x) $(RULE_DIR)/scripts/gen_top_cmake.sh $(TOP_DIR)/CMakeLists.txt + $(TOP_Q)for D in $(ALL_SUB_DIRS); do \ + echo "+ $${D}"; \ + $(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$${D} cmake; \ + done + $(TOP_Q)echo "" + +one: COMP_LIB_OBJS = $(foreach V,$(COMP_LIB_COMPONENTS),$(foreach U,$(LIB_OBJS_$(V)),$(V)/$(U))) +one: + $(TOP_Q)$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") \ + CFLAGS="$(subst ",,$(CFLAGS))" \ + ALL_LIBS="$(strip $(foreach V,$(SUBDIRS),$(LIBA_TARGET_$(V))))" \ + ALL_PROG="$(strip $(foreach V,$(SUBDIRS) $(COMP_LIB_COMPONENTS),$(TARGET_$(V))))" \ + COMP_LIB_OBJS="$(COMP_LIB_OBJS)" \ + bash $(RULE_DIR)/scripts/gen_one_makefile.sh + +config: + + @mkdir -p $(OUTPUT_DIR) $(STAMP_DIR) $(INSTALL_DIR) + @mkdir -p $(SYSROOT_BIN) $(SYSROOT_INC) $(SYSROOT_LIB) + + $(TOP_Q) \ + if [ -f $(STAMP_BLD_VAR) ]; then \ + if [ "$$($(SED) '/[-_/a-zA-Z0-9]* = *..*/d' $(STAMP_BLD_VAR)|wc -l|$(SED) 's:^ *::g')" != "0" ]; then \ + rm -vf $(STAMP_BLD_VAR); \ + fi \ + fi + + $(TOP_Q)+( \ + if [ -f $(CONFIG_TPL) ]; then \ + if [ "$(filter comp-lib,$(MAKECMDGOALS))" = "" ]; then \ + printf "BUILDING WITH EXISTING CONFIGURATION:\n\n"; \ + command grep -m 1 "VENDOR *:" $(CONFIG_TPL)|cut -c 3-; \ + command grep -m 1 "MODEL *:" $(CONFIG_TPL)|cut -c 3-; \ + echo ""; \ + fi \ + else \ + if ([ "$(MAKECMDGOALS)" = "all" ]) || ([ "$(DEFAULT_BLD)" != "" ] && [ -f $(DEFAULT_BLD) ] && \ + ([ "$(DEFAULT_BLD)" = "$(RULE_DIR)/misc/config.generic.default" ] \ + || [ "$(MAKECMDGOALS)" = "" ] || [ "$(MAKECMDGOALS)" = "config" ])); then \ + printf "# Automatically Generated Section End\n\n" >> $(CONFIG_TPL); \ + printf "# %-10s %s\n" "VENDOR :" $$(basename $(DEFAULT_BLD)|cut -d. -f2) >> $(CONFIG_TPL); \ + printf "# %-10s %s\n" "MODEL :" $$(basename $(DEFAULT_BLD)|cut -d. -f3) >> $(CONFIG_TPL); \ + cat $(DEFAULT_BLD) >> $(CONFIG_TPL); \ + else \ + printf "SELECT A CONFIGURATION:\n\n"; \ + LIST=$$(for i in $(CONFIG_DIR)/config.*.*; do basename $${i}; done|sort); \ + select V in $${LIST}; do \ + echo ""; \ + printf "# Automatically Generated Section End\n\n" >> $(CONFIG_TPL); \ + printf "# %-10s %s\n" "VENDOR :" $$(echo $${V}|cut -d. -f2) >> $(CONFIG_TPL); \ + printf "# %-10s %s\n" "MODEL :" $$(echo $${V}|cut -d. -f3) >> $(CONFIG_TPL); \ + cp -f -P $(IMPORT_DIR)/$$(echo $${V}|cut -d. -f2)/$(PREBUILT_LIBDIR)/*.so* $(SYSROOT_LIB) 2>/dev/null; \ + cat $(CONFIG_DIR)/$${V} >> $(CONFIG_TPL); \ + break; \ + done; \ + fi && \ + printf "SELECTED CONFIGURATION:\n\n" && \ + command grep -m 1 "VENDOR *:" $(CONFIG_TPL)|cut -c 3- && \ + command grep -m 1 "MODEL *:" $(CONFIG_TPL)|cut -c 3- && \ + echo ""; \ + if [ "$(MAKECMDGOALS)" = "config" ]; then true; else \ + if [ "$(DEFAULT_BLD)" = "" ]; then \ + touch $(STAMP_PRJ_CFG); \ + fi; \ + fi; \ + for i in $(RESET_ENV_VARS); do unset $${i}; done; \ + $(MAKE) --no-print-directory -f $(TOP_MAKEFILE) $(STAMP_BLD_VAR) unzip; \ + fi) + + @$(MAKE) --no-print-directory one + +DL_TOOLCHAIN_VARS = \ + TOOLCHAIN_DLDIR \ + OUTPUT_DIR \ + +toolchain: + @$(foreach V,$(DL_TOOLCHAIN_VARS),$(V)=$($(V))) \ + CC=$(shell basename $(CC)) \ + AR=$(shell basename $(AR)) \ + RELPATH=` $(call Relative_TcPath,$(shell basename $(CC))) ` \ + GITPATH=` $(call Gitrepo_TcPath,$(shell basename $(CC))) ` \ + bash $(RULE_DIR)/scripts/gen_cross_toolchain.sh + +reconfig: distclean + $(TOP_Q)+( \ + if [ -d $(CONFIG_DIR) ]; then \ + $(RECURSIVE_MAKE) config DEFAULT_BLD=not-exist-actually; \ + else \ + $(RECURSIVE_MAKE) config; \ + fi) + $(TOP_Q)rm -f $(STAMP_PRJ_CFG) + +clean: + $(TOP_Q) \ + + $(TOP_Q) \ + rm -rf \ + $(LIBOBJ_TMPDIR) \ + $(COMPILE_LOG) \ + $(DIST_DIR)/* \ + $(STAMP_DIR) \ + $(STAMP_LCOV) \ + $(SYSROOT_INC)/* $(SYSROOT_LIB)/* $(SYSROOT_LIB)/../bin/* \ + $(shell $(SHELL_DBG) find $(OUTPUT_DIR) -name "$(COMPILE_LOG)" \ + -or -name "$(WARNING_LOG)" \ + -or -name "$(STAMP_BUILD)" \ + -or -name "$(STAMP_INSTALL)" \ + -or -name "$(STAMP_POSTINS)" \ + -or -name "*.so" \ + -or -name "*.a" \ + -or -name "*.o" \ + -or -name "*.d" \ + -or -name "*.gc*" \ + | grep -v '$(OUTPUT_DIR)/compiler' \ + 2>/dev/null) + +distclean: + $(TOP_Q) \ + rm -rf \ + $(CONFIG_TPL) $(COMPILE_LOG) \ + $(STAMP_PRJ_CFG) $(STAMP_BLD_ENV) $(STAMP_BLD_VAR) $(STAMP_POST_RULE) $(STAMP_LCOV) \ + $(DIST_DIR) $(STAMP_DIR) *.gcda \ + + $(TOP_Q) \ + if [ -d $(OUTPUT_DIR) ]; then \ + cd $(OUTPUT_DIR); \ + if [ "$(CONFIG_TOOLCHAIN_NAME)" = "" ]; then \ + rm -rf *; \ + else \ + rm -rf $$(ls -I $(CONFIG_TOOLCHAIN_NAME)); \ + fi \ + fi + +ifeq ($(shell uname),Darwin) +KCONFIG_MCONF := tools/prebuilt/macos/kconfig-frontends-mac/kconfig-mconf +else +KCONFIG_MCONF := tools/prebuilt/ubuntu/bin/kconfig-mconf +endif + +COMMON_CONFIG_ENV = \ + KCONFIG_CONFIG=mconf.config \ + KCONFIG_AUTOCONFIG=$(OUTPUT_DIR)/auto.conf \ + KCONFIG_AUTOHEADER=$(OUTPUT_DIR)/autoconf.h \ + CONFIG_=FEATURE_ \ + +menuconfig: $(KCONFIG_MCONF) + $(TOP_Q)chmod a+x $(KCONFIG_MCONF) $(if $(TOP_Q),2>/dev/null) || true + $(TOP_Q)$(COMMON_CONFIG_ENV) $^ -s $(TOP_DIR)/tools/Config.in $(if $(TOP_Q),2>/dev/null) + $(TOP_Q) \ +( \ + if [ ! -f mconf.config ]; then exit 0; fi; \ + \ + cp -Lf mconf.config make.settings; \ + rm -f mconf.config*; \ +) diff --git a/iotkit-embedded/tools/build-rules/docs/Help.md b/iotkit-embedded/tools/build-rules/docs/Help.md new file mode 100644 index 0000000..256c125 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/docs/Help.md @@ -0,0 +1,14 @@ +常用命令 +--- + +| 命令 | 解释 | +|-----------------------|-----------------------------------------------------------------------------------| +| `make distclean` | **清除一切编译过程产生的中间文件, 使当前目录仿佛和刚刚clone下来一样** | +| `make` | **使用默认的或者已选中的平台配置文件开始编译** | +| `make reconfig` | **弹出多平台选择菜单, 用户可按数字键选择, 然后根据相应的硬件平台配置开始编译** | +| `make config` | **显示当前被选择的平台配置文件** | +| `make menuconfig` | **图形化的编辑 make.settings 文件** | +| `make help` | **打印帮助文本** | +| `make env` | **打印当前编译的选项和它们的值** | + +o 访问 https://code.aliyun.com/edward.yangx/public-docs/wikis/home 可获得编译系统线上最新和最全的帮助文档 diff --git a/iotkit-embedded/tools/build-rules/funcs.mk b/iotkit-embedded/tools/build-rules/funcs.mk new file mode 100644 index 0000000..ad66800 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/funcs.mk @@ -0,0 +1,259 @@ +define Append_Conditional +$(if $(strip $(foreach V,$(4),$(filter -D$(V),$(CFLAGS)))),, \ + $(if \ + $(if $(strip $(3)),,x)$(findstring $(foreach U,$(3),-D$(U)),$(foreach U,$(3),$(filter -D$(U),$(CFLAGS)))), \ + $(eval $(strip $(1)) += $(2)) \ + ) \ +) +endef + +define Dump_Var + NUM=`echo "$(strip $($(1)))"|awk '{ print NF }'`; \ + if (( $${NUM} \> 1 )); then \ + printf -- "-----------------------------------------------------------------\n"; \ + printf "%-24s| %s\n" ". $(1)" `echo "$(strip $($(1)))"|cut -d' ' -f1|$(SED) 's/^ *//'`; \ + for i in `echo "$(strip $($(1)))"|cut -d' ' -f2-`; do \ + printf "%-24s| %s\n" "" "$${i}"; \ + done; \ + printf -- "-----------------------------------------------------------------\n"; \ + else \ + printf "%-24s| %s\n" ". $(1)" "$(strip $($(1)))"; \ + fi; +endef + +ifneq (,$(Q)) +define Inspect_Env +endef +else +define Inspect_Env + @printf -- "-----------------------------------------------------------------\n" + @printf "%-20s| %s\n" ". BUILDING_TARGET" "$@" + @printf -- "-----------------------------------------------------------------\n" + @printf "%-20s| %s\n" ". BUILDING_DEPEND" "$(filter-out FORCE,$^)" + @printf -- "-----------------------------------------------------------------\n" + @$(foreach var,$(1),$(call Dump_Var,$(var))) + @printf -- "-----------------------------------------------------------------\n" +endef +endif + +# 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. +define Brief_Log +( \ + if [ "$1" = "CC" ]; then \ + if echo "$@"|grep -q "\.so$$"; then \ + COLOR_MARK="\033[1;32m"; \ + elif echo "$@"|grep -q "\.ko$$"; then \ + COLOR_MARK="\033[1;35m"; \ + else \ + COLOR_MARK="\033[1;36m"; \ + fi \ + elif [ "$1" = "AR" ]; then \ + COLOR_MARK="\033[1;33m"; \ + elif [ "$1" = "LD" ]; then \ + COLOR_MARK="\033[1;31m"; \ + elif [ "$1" = "ST" ]; then \ + COLOR_MARK="\033[0;33m"; \ + fi; \ + if [ "$(PLAIN_LOG)" != "1" ]; then \ + echo -ne "$${COLOR_MARK}"; \ + fi; \ + if [ "$2" = "" ]; then \ + FIRST_DEP="$(firstword $(filter-out FORCE,$?))"; \ + SPACE_BAR=" "; \ + if [ "$${FIRST_DEP}" != "" ]; then \ + FIRST_DEP="$$(basename $${FIRST_DEP})"; \ + fi; \ + printf "\r%-40s%s%s$(3)\n" "[$1] $$(echo -n "$$(basename $@)" | cut -c1-28)" "<= $${FIRST_DEP} $${SPACE_BAR}"; \ + else \ + printf "\r%-40s%s%s$(3)\n" "[$1] $$(echo -n "$(2)" | cut -c1-28)" "<= $${FIRST_DEP} $${SPACE_BAR}"; \ + fi; \ + if [ "$3" != "..." ]; then \ + for i in $(wordlist 2,150,$(filter-out FORCE,$?)); do \ + if [ "$$(echo $${i}|cut -c1)" != "/" ]; then \ + printf "%-40s%s$(3)\n" "" " $$(basename $${i})"; \ + fi \ + done; \ + fi; \ + if [ "$(PLAIN_LOG)" != "1" ]; then \ + echo -ne "\033[0m"; \ + fi; \ +) +endef + +define Copy_Headers + $(Q) \ + if [ "$(strip $(1))" != "" ]; then \ + mkdir -p $(2)/$(3); \ + for hdr in $(1); do \ + if [ ! -f $(2)/$(3)/$${hdr} ] || [ $${PWD}/$${hdr} -nt $(2)/$(3)/$${hdr} ]; then \ + mkdir -p $(2)/$(3); \ + cp -f $(TOP_DIR)/$(MODULE_NAME)/$${hdr} $(2)/$(3)/$$(basename $${hdr}); \ + fi; \ + done \ + fi +endef + +define Update_Extra_Srcs +( \ + for ELEM in $(strip $(1)); do \ + DST=$(OUTPUT_DIR)/$(2)/$$(basename $${ELEM}); \ + if [ $${ELEM} -nt $${DST} ]; then \ + cp -Lf $${ELEM} $${DST}; \ + fi; \ + done \ +) +endef + +define Require_Build +( \ + SW=$$(grep -m 1 "^PKG_SWITCH_$(1) =" $(STAMP_BLD_VAR)|awk '{ print $$NF }'); \ + [ "$${SW}" != "y" ] && \ + echo "FALSE" && exit; set +x; \ +\ + [ "$(LIBA_TARGET_$(1))" != "" ] && \ + $(foreach L,$(LIBA_TARGET_$(1)),[ -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(L) ] && ) \ + echo "FALSE" && exit; \ +\ + [ "$(LIBSO_TARGET_$(1))" != "" ] && \ + [ -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(LIBSO_TARGET_$(1)) ] && \ + echo "FALSE" && exit; \ +\ + echo "TRUE"; \ +) +endef + +define Build_Depends +( \ + set -o pipefail && \ + for i in $(DEPENDS_$(1)); do \ + STAMP=$(STAMP_DIR)/$$(echo $${i}|$(SED) 's:/:~:g').build.done; \ + if [ -f $${STAMP} ]; then \ + continue; \ + fi; \ + $(MAKE) --no-print-directory $${i} \ + $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$${i}/$(COMPILE_LOG)) \ + $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(COMPILE_LOG)); \ + RETVAL=$$?; \ + if [ $${RETVAL} != 0 ]; then \ + exit $${RETVAL}; \ + fi; \ + done \ +\ +) +endef + +# +# ($(foreach d,$(COMP_LIB_COMPONENTS), \ +# +# $(RECURSIVE_MAKE) pre-build target-$(d) && \ +# $(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$(d) $(LIBA_TARGET_$(d)) \ +# $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(d)/$(COMPILE_LOG)) \ +# $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(COMPILE_LOG)) \ +# ; \ +# +# if [ $$? != 0 ]; then \ +# +# KEEP SEPA-LIBS: +# +# rm -f $(SYSROOT_LIB)/$(firstword $(LIBA_TARGET_$(d))) $(SYSROOT_LIB)/$(firstword $(LIBSO_TARGET_$(d))) 2>/dev/null; \ +# + +ifdef COMP_LIB +define Build_CompLib +( \ + if [ "$(strip $(1))" = "FORCE" ] || \ + [ "$$(echo $(LDFLAGS_$(strip $(1)))|grep -wo -- '-l$(COMP_LIB_NAME)')" != "" ]; then \ + ( \ + $(foreach d,$(COMP_LIB_COMPONENTS), \ + [ -f $(STAMP_DIR)/$(subst /,~,$(d)).build.done ] || \ + set -o pipefail && \ + $(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$(d) $(firstword $(LIBA_TARGET_$(d))) $(firstword $(LIBSO_TARGET_$(d))) && set +x; \ + RETVAL=$$?; \ + if [ $${RETVAL} != 0 ]; then \ + exit $${RETVAL}; \ + fi; \ + ) \ + ); \ + if [ ! -f $(SYSROOT_LIB)/$(COMP_LIB) ]; then \ + $(call Info_CompLib,$(COMP_LIB_NAME),$(COMP_LIB_OBJS)); \ + fi; \ + $(call Finalize_CompLib,$(COMP_LIB_OBJS),$(SYSROOT_LIB),$(COMP_LIB_NAME)); \ + fi \ +) +endef +else +define Build_CompLib +true +endef +endif + +define Relative_TcPath +( \ + case $(1) in \ + xtensa-lx106-elf-gcc ) \ + echo "gcc-xtensa-lx106-linux/main/bin" ;; \ + arm-none-eabi-gcc ) \ + echo "gcc-arm-none-eabi-linux/main/bin" ;; \ + esac \ +) +endef + +define Gitrepo_TcPath +( \ + case $(1) in \ + xtensa-lx106-elf-gcc ) \ + echo "gcc-xtensa-lx106-linux" ;; \ + arm-none-eabi-gcc ) \ + echo "gcc-arm-none-eabi-linux" ;; \ + esac \ +) +endef + +define CompLib_Map +$(eval \ + COMP_LIB_COMPONENTS += \ + $(if \ + $(filter y,$($(strip $(1)))),$(foreach M,$(strip $(2)),$(if $(filter $(strip $(M)),$(COMP_LIB_COMPONENTS)),,$(strip $(M)))) \ + ) \ +) +endef + +OMIT_GOALS := distclean clean env help config reconfig menuconfig + +ifeq (,$(filter $(OMIT_GOALS),$(MAKECMDGOALS))) +define Conflict_Relation +$(if $(filter y,$($(strip $(1)))), \ + $(if $(filter y,$($(strip $(2)))), \ + $(error INVALID CONFIG: '$(strip $(1)) = $($(strip $(1)))' conflicts with '$(strip $(2)) = $($(strip $(2)))' at same time!), \ + ), \ +) +endef + +define Present1_Relation +$(if $(filter n,$($(strip $(1)))), \ + $(if $(filter n,$($(strip $(2)))), \ + $(error INVALID CONFIG: '$(strip $(1)) = $($(strip $(1)))' conflicts with '$(strip $(2)) = $($(strip $(2)))' at same time!), \ + ), \ +) +endef + +define Requires_Relation +$(if $(filter y,$($(strip $(1)))), \ + $(if $(filter y,$($(strip $(2)))),, \ + $(error INVALID CONFIG: '$(strip $(2)) = $($(strip $(2)))' breaks dependency since '$(strip $(1)) = $($(strip $(1)))'!), \ + ), \ +) +endef + +else # ifeq (,$(filter $(OMIT_GOALS),$(MAKECMDGOALS))) + +define Conflict_Relation +endef + +define Present1_Relation +endef + +define Requires_Relation +endef + +endif # ifeq (,$(filter $(OMIT_GOALS),$(MAKECMDGOALS))) diff --git a/iotkit-embedded/tools/build-rules/hooks/pre-commit b/iotkit-embedded/tools/build-rules/hooks/pre-commit new file mode 100644 index 0000000..d1888f1 --- /dev/null +++ b/iotkit-embedded/tools/build-rules/hooks/pre-commit @@ -0,0 +1,23 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +for i in `git status -s | awk '{ print $NF }'`; do + j=$(echo $(basename $i)|cut -d'.' -f2) + if [ "$j" = "c" -o "$j" = "h" -o "$j" = "md" -o "$j" = "mk" ] || [ "$i" = "makefile" -o "$i" = "make.settings" ]; then + if [ "$(find $i -perm /111 2>/dev/null)" != "" ]; then + chmod a-x $i + echo "[chmod] $i" + if [ "$(git status --short $i|cut -c1)" = "M" ]; then + git add $i + fi + fi + else + echo "[skip ] $i" + fi +done diff --git a/iotkit-embedded/tools/build-rules/misc/Doxyfile.tpl b/iotkit-embedded/tools/build-rules/misc/Doxyfile.tpl new file mode 100644 index 0000000..869123e --- /dev/null +++ b/iotkit-embedded/tools/build-rules/misc/Doxyfile.tpl @@ -0,0 +1,2426 @@ +# Doxyfile 1.8.11 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = TBD + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = TBD + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = . +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = YES + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, +# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = NO + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +# CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +# CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /