diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/DebugConfig/TencentOS_tiny_STM32L431RCTx.dbgconf b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/DebugConfig/TencentOS_tiny_STM32L431RCTx.dbgconf new file mode 100644 index 00000000..c9811753 --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/DebugConfig/TencentOS_tiny_STM32L431RCTx.dbgconf @@ -0,0 +1,97 @@ +// File: STM32L43x_44x_45x_46x.dbgconf +// Version: 1.0.0 +// Note: refer to STM32L43xxx STM32L44xxx STM32L45xxx STM32L46xxx Reference manual (RM0394) +// refer to STM32L431xx, STM32L432xx, STM32L433xx, STM32L442xx, STM32L443xx, STM32L451xx, STM32L452xx, STM32L462xx datasheets + +// <<< Use Configuration Wizard in Context Menu >>> + +// Debug MCU configuration register (DBGMCU_CR) +// DBG_STANDBY +// Debug Standby mode +// 0: (FCLK=Off, HCLK=Off) The whole digital part is unpowered. +// 1: (FCLK=On, HCLK=On) The digital part is not unpowered and FCLK and HCLK are provided by the internal RC oscillator which remains active +// DBG_STOP +// Debug Stop mode +// 0: (FCLK=Off, HCLK=Off) In STOP mode, the clock controller disables all clocks (including HCLK and FCLK). +// 1: (FCLK=On, HCLK=On) When entering STOP mode, FCLK and HCLK are provided by the internal RC oscillator which remains active in STOP mode. +// DBG_SLEEP +// Debug Sleep mode +// 0: (FCLK=On, HCLK=Off) In Sleep mode, FCLK is clocked by the system clock as previously configured by the software while HCLK is disabled. +// 1: (FCLK=On, HCLK=On) When entering Sleep mode, HCLK is fed by the same clock that is provided to FCLK (system clock as previously configured by the software). +// +DbgMCU_CR = 0x00000007; + +// Debug MCU APB1 freeze register1 (DBGMCU_APB1FZR1) +// DBG_LPTIM1_STOP +// LPTIM1 counter stopped when core is halted +// 0: The counter clock of LPTIM1 is fed even if the core is halted +// 1: The counter clock of LPTIM1 is stopped when the core is halted +// DBG_CAN_STOP +// bxCAN1 stopped when core is halted +// 0: Same behavior as in normal mode +// 1: The bxCAN1 receive registers are frozen +// DBG_I2C3_STOP +// I2C3 SMBUS timeout counter stopped when core is halted +// 0: Same behavior as in normal mode +// 1: The I2C3 SMBus timeout is frozen +// DBG_I2C2_STOP +// I2C2 SMBUS timeout counter stopped when core is halted +// 0: Same behavior as in normal mode +// 1: The I2C2 SMBus timeout is frozen +// DBG_I2C1_STOP +// I2C1 SMBUS timeout counter stopped when core is halted +// 0: Same behavior as in normal mode +// 1: The I2C1 SMBus timeout is frozen +// DBG_IWDG_STOP +// Independent watchdog counter stopped when core is halted +// 0: The independent watchdog counter clock continues even if the core is halted +// 1: The independent watchdog counter clock is stopped when the core is halted +// DBG_WWDG_STOP +// Window watchdog counter stopped when core is halted +// 0: The window watchdog counter clock continues even if the core is halted +// 1: The window watchdog counter clock is stopped when the core is halted +// DBG_RTC_STOP +// RTC counter stopped when core is halted +// 0: The clock of the RTC counter is fed even if the core is halted +// 1: The clock of the RTC counter is stopped when the core is halted +// DBG_TIM7_STOP +// TIM7 counter stopped when core is halted +// 0: The counter clock of TIM7 is fed even if the core is halted +// 1: The counter clock of TIM7 is stopped when the core is halted +// DBG_TIM6_STOP +// TIM6 counter stopped when core is halted +// 0: The counter clock of TIM6 is fed even if the core is halted +// 1: The counter clock of TIM6 is stopped when the core is halted +// DBG_TIM2_STOP +// TIM2 counter stopped when core is halted +// 0: The counter clock of TIM2 is fed even if the core is halted +// 1: The counter clock of TIM2 is stopped when the core is halted +// +DbgMCU_APB1_Fz1 = 0x00000000; + +// Debug MCU APB1 freeze register 2 (DBGMCU_APB1FZR2) +// DBG_LPTIM2_STOP +// LPTIM2 counter stopped when core is halted +// 0: The counter clock of LPTIM2 is fed even if the core is halted +// 1: The counter clock of LPTIM2 is stopped when the core is halted +// +DbgMCU_APB1_Fz2 = 0x00000000; + +// Debug MCU APB2 freeze register (DBGMCU_APB2FZR) +// DBG_TIM16_STOP +// TIM16 counter stopped when core is halted +// 0: The clock of the TIM16 counter is fed even if the core is halted +// 1: The clock of the TIM16 counter is stopped when the core is halted +// DBG_TIM15_STOP +// TIM15 counter stopped when core is halted +// 0: The clock of the TIM15 counter is fed even if the core is halted +// 1: The clock of the TIM15 counter is stopped when the core is halted +// DBG_TIM1_STOP +// TIM1 counter stopped when core is halted +// 0: The clock of the TIM1 counter is fed even if the core is halted +// 1: The clock of the TIM1 counter is stopped when the core is halted +// +DbgMCU_APB2_Fz = 0x00000000; +// + +// <<< end of configuration section >>> \ No newline at end of file diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/RTE/_TencentOS_tiny/RTE_Components.h b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/RTE/_TencentOS_tiny/RTE_Components.h new file mode 100644 index 00000000..45b7722b --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/RTE/_TencentOS_tiny/RTE_Components.h @@ -0,0 +1,20 @@ + +/* + * Auto generated Run-Time-Environment Component Configuration File + * *** Do not modify ! *** + * + * Project: 'TencentOS_tiny' + * Target: 'TencentOS_tiny' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + +#endif /* RTE_COMPONENTS_H */ diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvoptx b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvoptx new file mode 100644 index 00000000..fc0de570 --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvoptx @@ -0,0 +1,2647 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + TencentOS_tiny + 0x4 + ARM-ADS + + 80000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\list\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 6 + + + + + + + + + + + STLink\ST-LINKIII-KEIL_SWO.dll + + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32L4xx_256 -FS08000000 -FL040000 -FP0($$Device:STM32L431RCTx$CMSIS\Flash\STM32L4xx_256.FLM)) + + + 0 + ST-LINKIII-KEIL_SWO + -U303030303030303030303031 -O10446 -SF4000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32L4xx_256.FLM -FS08000000 -FL040000 -FP0($$Device:STM32L431RCTx$CMSIS\Flash\STM32L4xx_256.FLM) + + + + + 0 + 0 + 54 + 1 +
134240894
+ 0 + 0 + 0 + 0 + 0 + 1 + D:\Code\tencentos_tiny\temp_develop\TencentOS-tiny\examples\mqtt\mqtt_demo.c + + \\TencentOS_tiny\../../../../examples/mqtt/mqtt_demo.c\54 +
+ + 1 + 0 + 107 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + D:\github\TencentOS-tiny\components\connectivity\Eclipse-Paho-MQTT\wrapper\src\mqtt_wrapper.c + + +
+
+ + + 0 + 1 + huart3 + + + + + 0 + 2 + con_param + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 1 + 0 + 2 + 10000000 + +
+
+ + + Application/MDK-ARM + 0 + 0 + 0 + 0 + + 1 + 1 + 2 + 0 + 0 + 0 + startup_stm32l431xx.s + startup_stm32l431xx.s + 0 + 0 + + + + + Application/User + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\gpio.c + gpio.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\main.c + main.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\mcu_init.c + mcu_init.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\stm32l4xx_hal_msp.c + stm32l4xx_hal_msp.c + 0 + 0 + + + 2 + 6 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\usart.c + usart.c + 0 + 0 + + + 2 + 7 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\adc.c + adc.c + 0 + 0 + + + 2 + 8 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\dac.c + dac.c + 0 + 0 + + + 2 + 9 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\i2c.c + i2c.c + 0 + 0 + + + 2 + 10 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\spi.c + spi.c + 0 + 0 + + + 2 + 11 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\stm32l4xx_it_module.c + stm32l4xx_it_module.c + 0 + 0 + + + + + examples + 0 + 0 + 0 + 0 + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\mqtt_example.c + mqtt_example.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\aliyun_iotkit_csdk_mqtt.c + aliyun_iotkit_csdk_mqtt.c + 0 + 0 + + + + + Drivers/STM32L4xx_HAL_Driver + 0 + 0 + 0 + 0 + + 4 + 14 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim.c + stm32l4xx_hal_tim.c + 0 + 0 + + + 4 + 15 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim_ex.c + stm32l4xx_hal_tim_ex.c + 0 + 0 + + + 4 + 16 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart.c + stm32l4xx_hal_uart.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart_ex.c + stm32l4xx_hal_uart_ex.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal.c + stm32l4xx_hal.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c.c + stm32l4xx_hal_i2c.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c_ex.c + stm32l4xx_hal_i2c_ex.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc.c + stm32l4xx_hal_rcc.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc_ex.c + stm32l4xx_hal_rcc_ex.c + 0 + 0 + + + 4 + 23 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash.c + stm32l4xx_hal_flash.c + 0 + 0 + + + 4 + 24 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ex.c + stm32l4xx_hal_flash_ex.c + 0 + 0 + + + 4 + 25 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ramfunc.c + stm32l4xx_hal_flash_ramfunc.c + 0 + 0 + + + 4 + 26 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_gpio.c + stm32l4xx_hal_gpio.c + 0 + 0 + + + 4 + 27 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma.c + stm32l4xx_hal_dma.c + 0 + 0 + + + 4 + 28 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma_ex.c + stm32l4xx_hal_dma_ex.c + 0 + 0 + + + 4 + 29 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr.c + stm32l4xx_hal_pwr.c + 0 + 0 + + + 4 + 30 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr_ex.c + stm32l4xx_hal_pwr_ex.c + 0 + 0 + + + 4 + 31 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cortex.c + stm32l4xx_hal_cortex.c + 0 + 0 + + + 4 + 32 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc_ex.c + stm32l4xx_hal_adc_ex.c + 0 + 0 + + + 4 + 33 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc.c + stm32l4xx_hal_adc.c + 0 + 0 + + + 4 + 34 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac.c + stm32l4xx_hal_dac.c + 0 + 0 + + + 4 + 35 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac_ex.c + stm32l4xx_hal_dac_ex.c + 0 + 0 + + + 4 + 36 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi.c + stm32l4xx_hal_spi.c + 0 + 0 + + + 4 + 37 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi_ex.c + stm32l4xx_hal_spi_ex.c + 0 + 0 + + + + + Drivers/CMSIS + 0 + 0 + 0 + 0 + + 5 + 38 + 1 + 0 + 0 + 0 + ..\..\BSP\Src\system_stm32l4xx.c + system_stm32l4xx.c + 0 + 0 + + + + + Hardware + 0 + 0 + 0 + 0 + + 6 + 39 + 1 + 0 + 0 + 0 + ..\..\BSP\Hardware\DHT11\DHT11_BUS.c + DHT11_BUS.c + 0 + 0 + + + 6 + 40 + 1 + 0 + 0 + 0 + ..\..\BSP\Hardware\OLED\oled.c + oled.c + 0 + 0 + + + 6 + 41 + 1 + 0 + 0 + 0 + ..\..\BSP\Hardware\BH1750\BH1750.c + BH1750.c + 0 + 0 + + + + + kernel + 0 + 0 + 0 + 0 + + 7 + 42 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_binary_heap.c + tos_binary_heap.c + 0 + 0 + + + 7 + 43 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_char_fifo.c + tos_char_fifo.c + 0 + 0 + + + 7 + 44 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_completion.c + tos_completion.c + 0 + 0 + + + 7 + 45 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_countdownlatch.c + tos_countdownlatch.c + 0 + 0 + + + 7 + 46 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_event.c + tos_event.c + 0 + 0 + + + 7 + 47 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_global.c + tos_global.c + 0 + 0 + + + 7 + 48 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_mail_queue.c + tos_mail_queue.c + 0 + 0 + + + 7 + 49 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_message_queue.c + tos_message_queue.c + 0 + 0 + + + 7 + 50 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_mmblk.c + tos_mmblk.c + 0 + 0 + + + 7 + 51 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_mmheap.c + tos_mmheap.c + 0 + 0 + + + 7 + 52 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_mutex.c + tos_mutex.c + 0 + 0 + + + 7 + 53 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_pend.c + tos_pend.c + 0 + 0 + + + 7 + 54 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_priority_mail_queue.c + tos_priority_mail_queue.c + 0 + 0 + + + 7 + 55 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_priority_message_queue.c + tos_priority_message_queue.c + 0 + 0 + + + 7 + 56 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_priority_queue.c + tos_priority_queue.c + 0 + 0 + + + 7 + 57 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_ring_queue.c + tos_ring_queue.c + 0 + 0 + + + 7 + 58 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_robin.c + tos_robin.c + 0 + 0 + + + 7 + 59 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_sched.c + tos_sched.c + 0 + 0 + + + 7 + 60 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_sem.c + tos_sem.c + 0 + 0 + + + 7 + 61 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_sys.c + tos_sys.c + 0 + 0 + + + 7 + 62 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_task.c + tos_task.c + 0 + 0 + + + 7 + 63 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_tick.c + tos_tick.c + 0 + 0 + + + 7 + 64 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_time.c + tos_time.c + 0 + 0 + + + 7 + 65 + 1 + 0 + 0 + 0 + ..\..\..\..\kernel\core\tos_timer.c + tos_timer.c + 0 + 0 + + + + + cpu + 0 + 0 + 0 + 0 + + 8 + 66 + 2 + 0 + 0 + 0 + ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_s.S + port_s.S + 0 + 0 + + + 8 + 67 + 1 + 0 + 0 + 0 + ..\..\..\..\arch\arm\arm-v7m\common\tos_cpu.c + tos_cpu.c + 0 + 0 + + + 8 + 68 + 1 + 0 + 0 + 0 + ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_c.c + port_c.c + 0 + 0 + + + + + cmsis + 0 + 0 + 0 + 0 + + 9 + 69 + 1 + 0 + 0 + 0 + ..\..\..\..\osal\cmsis_os\cmsis_os.c + cmsis_os.c + 0 + 0 + + + + + config + 0 + 0 + 0 + 0 + + 10 + 70 + 5 + 0 + 0 + 0 + ..\..\TOS-CONFIG\tos_config.h + tos_config.h + 0 + 0 + + + + + devices + 0 + 0 + 0 + 0 + + 11 + 71 + 1 + 0 + 0 + 0 + ..\..\..\..\devices\bc35_28_95\bc35_28_95.c + bc35_28_95.c + 0 + 0 + + + 11 + 72 + 1 + 0 + 0 + 0 + ..\..\..\..\devices\esp8266\esp8266.c + esp8266.c + 0 + 0 + + + + + hal + 0 + 0 + 0 + 0 + + 12 + 73 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\hal\st\stm32l4xx\src\tos_hal_uart.c + tos_hal_uart.c + 0 + 0 + + + + + at + 0 + 0 + 0 + 0 + + 13 + 74 + 1 + 0 + 0 + 0 + ..\..\..\..\net\at\src\tos_at.c + tos_at.c + 0 + 0 + + + 13 + 75 + 1 + 0 + 0 + 0 + ..\..\..\..\net\at\src\tos_at_utils.c + tos_at_utils.c + 0 + 0 + + + 13 + 76 + 1 + 0 + 0 + 0 + ..\..\..\..\net\sal_module_wrapper\sal_module_wrapper.c + sal_module_wrapper.c + 0 + 0 + + + + + port/TencentOS_tiny + 0 + 0 + 0 + 0 + + 14 + 77 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_os.c + osal_os.c + 0 + 0 + + + 14 + 78 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_tcp_module.c + osal_tcp_module.c + 0 + 0 + + + 14 + 79 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_timer.c + osal_timer.c + 0 + 0 + + + + + iotkit/mqtt + 0 + 0 + 0 + 0 + + 15 + 80 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\mqtt_api.c + mqtt_api.c + 0 + 0 + + + 15 + 81 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\iotx_mqtt_client.c + iotx_mqtt_client.c + 0 + 0 + + + 15 + 82 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTConnectClient.c + MQTTConnectClient.c + 0 + 0 + + + 15 + 83 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTDeserializePublish.c + MQTTDeserializePublish.c + 0 + 0 + + + 15 + 84 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTPacket.c + MQTTPacket.c + 0 + 0 + + + 15 + 85 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSerializePublish.c + MQTTSerializePublish.c + 0 + 0 + + + 15 + 86 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSubscribeClient.c + MQTTSubscribeClient.c + 0 + 0 + + + 15 + 87 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTUnsubscribeClient.c + MQTTUnsubscribeClient.c + 0 + 0 + + + + + iotkit/infra + 0 + 0 + 0 + 0 + + 16 + 88 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_aes.c + infra_aes.c + 0 + 0 + + + 16 + 89 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_cjson.c + infra_cjson.c + 0 + 0 + + + 16 + 90 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_compat.c + infra_compat.c + 0 + 0 + + + 16 + 91 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_defs.c + infra_defs.c + 0 + 0 + + + 16 + 92 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_httpc.c + infra_httpc.c + 0 + 0 + + + 16 + 93 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_json_parser.c + infra_json_parser.c + 0 + 0 + + + 16 + 94 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_log.c + infra_log.c + 0 + 0 + + + 16 + 95 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_md5.c + infra_md5.c + 0 + 0 + + + 16 + 96 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_mem_stats.c + infra_mem_stats.c + 0 + 0 + + + 16 + 97 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_net.c + infra_net.c + 0 + 0 + + + 16 + 98 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_preauth.c + infra_preauth.c + 0 + 0 + + + 16 + 99 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_prt_nwk_payload.c + infra_prt_nwk_payload.c + 0 + 0 + + + 16 + 100 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_report.c + infra_report.c + 0 + 0 + + + 16 + 101 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha1.c + infra_sha1.c + 0 + 0 + + + 16 + 102 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha256.c + infra_sha256.c + 0 + 0 + + + 16 + 103 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_string.c + infra_string.c + 0 + 0 + + + 16 + 104 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_timer.c + infra_timer.c + 0 + 0 + + + + + iotkit/dev_sign + 0 + 0 + 0 + 0 + + 17 + 105 + 1 + 0 + 0 + 0 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\dev_sign\dev_sign_mqtt.c + dev_sign_mqtt.c + 0 + 0 + + + + + mbedtls + 0 + 0 + 0 + 0 + + 18 + 106 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\aes.c + aes.c + 0 + 0 + + + 18 + 107 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\aesni.c + aesni.c + 0 + 0 + + + 18 + 108 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\arc4.c + arc4.c + 0 + 0 + + + 18 + 109 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\aria.c + aria.c + 0 + 0 + + + 18 + 110 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1parse.c + asn1parse.c + 0 + 0 + + + 18 + 111 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1write.c + asn1write.c + 0 + 0 + + + 18 + 112 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\base64.c + base64.c + 0 + 0 + + + 18 + 113 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\bignum.c + bignum.c + 0 + 0 + + + 18 + 114 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\blowfish.c + blowfish.c + 0 + 0 + + + 18 + 115 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\camellia.c + camellia.c + 0 + 0 + + + 18 + 116 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ccm.c + ccm.c + 0 + 0 + + + 18 + 117 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\certs.c + certs.c + 0 + 0 + + + 18 + 118 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\chacha20.c + chacha20.c + 0 + 0 + + + 18 + 119 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\chachapoly.c + chachapoly.c + 0 + 0 + + + 18 + 120 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher.c + cipher.c + 0 + 0 + + + 18 + 121 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher_wrap.c + cipher_wrap.c + 0 + 0 + + + 18 + 122 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\cmac.c + cmac.c + 0 + 0 + + + 18 + 123 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ctr_drbg.c + ctr_drbg.c + 0 + 0 + + + 18 + 124 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\debug.c + debug.c + 0 + 0 + + + 18 + 125 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\des.c + des.c + 0 + 0 + + + 18 + 126 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\dhm.c + dhm.c + 0 + 0 + + + 18 + 127 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdh.c + ecdh.c + 0 + 0 + + + 18 + 128 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdsa.c + ecdsa.c + 0 + 0 + + + 18 + 129 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecjpake.c + ecjpake.c + 0 + 0 + + + 18 + 130 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp.c + ecp.c + 0 + 0 + + + 18 + 131 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp_curves.c + ecp_curves.c + 0 + 0 + + + 18 + 132 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy.c + entropy.c + 0 + 0 + + + 18 + 133 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy_poll.c + entropy_poll.c + 0 + 0 + + + 18 + 134 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\error.c + error.c + 0 + 0 + + + 18 + 135 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\gcm.c + gcm.c + 0 + 0 + + + 18 + 136 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\havege.c + havege.c + 0 + 0 + + + 18 + 137 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\hkdf.c + hkdf.c + 0 + 0 + + + 18 + 138 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\hmac_drbg.c + hmac_drbg.c + 0 + 0 + + + 18 + 139 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md.c + md.c + 0 + 0 + + + 18 + 140 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md_wrap.c + md_wrap.c + 0 + 0 + + + 18 + 141 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md2.c + md2.c + 0 + 0 + + + 18 + 142 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md4.c + md4.c + 0 + 0 + + + 18 + 143 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md5.c + md5.c + 0 + 0 + + + 18 + 144 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\memory_buffer_alloc.c + memory_buffer_alloc.c + 0 + 0 + + + 18 + 145 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\net_sockets.c + net_sockets.c + 0 + 0 + + + 18 + 146 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\nist_kw.c + nist_kw.c + 0 + 0 + + + 18 + 147 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\oid.c + oid.c + 0 + 0 + + + 18 + 148 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\padlock.c + padlock.c + 0 + 0 + + + 18 + 149 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pem.c + pem.c + 0 + 0 + + + 18 + 150 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pk.c + pk.c + 0 + 0 + + + 18 + 151 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pk_wrap.c + pk_wrap.c + 0 + 0 + + + 18 + 152 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs5.c + pkcs5.c + 0 + 0 + + + 18 + 153 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs11.c + pkcs11.c + 0 + 0 + + + 18 + 154 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs12.c + pkcs12.c + 0 + 0 + + + 18 + 155 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkparse.c + pkparse.c + 0 + 0 + + + 18 + 156 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkwrite.c + pkwrite.c + 0 + 0 + + + 18 + 157 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\platform.c + platform.c + 0 + 0 + + + 18 + 158 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\platform_util.c + platform_util.c + 0 + 0 + + + 18 + 159 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\poly1305.c + poly1305.c + 0 + 0 + + + 18 + 160 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ripemd160.c + ripemd160.c + 0 + 0 + + + 18 + 161 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa.c + rsa.c + 0 + 0 + + + 18 + 162 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa_internal.c + rsa_internal.c + 0 + 0 + + + 18 + 163 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\sha1.c + sha1.c + 0 + 0 + + + 18 + 164 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\sha256.c + sha256.c + 0 + 0 + + + 18 + 165 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\sha512.c + sha512.c + 0 + 0 + + + 18 + 166 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cache.c + ssl_cache.c + 0 + 0 + + + 18 + 167 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ciphersuites.c + ssl_ciphersuites.c + 0 + 0 + + + 18 + 168 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cli.c + ssl_cli.c + 0 + 0 + + + 18 + 169 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cookie.c + ssl_cookie.c + 0 + 0 + + + 18 + 170 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_srv.c + ssl_srv.c + 0 + 0 + + + 18 + 171 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ticket.c + ssl_ticket.c + 0 + 0 + + + 18 + 172 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_tls.c + ssl_tls.c + 0 + 0 + + + 18 + 173 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\threading.c + threading.c + 0 + 0 + + + 18 + 174 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\timing.c + timing.c + 0 + 0 + + + 18 + 175 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\version.c + version.c + 0 + 0 + + + 18 + 176 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\version_features.c + version_features.c + 0 + 0 + + + 18 + 177 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509.c + x509.c + 0 + 0 + + + 18 + 178 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_create.c + x509_create.c + 0 + 0 + + + 18 + 179 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crl.c + x509_crl.c + 0 + 0 + + + 18 + 180 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crt.c + x509_crt.c + 0 + 0 + + + 18 + 181 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_csr.c + x509_csr.c + 0 + 0 + + + 18 + 182 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_crt.c + x509write_crt.c + 0 + 0 + + + 18 + 183 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_csr.c + x509write_csr.c + 0 + 0 + + + 18 + 184 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\3rdparty\src\xtea.c + xtea.c + 0 + 0 + + + 18 + 185 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\wrapper\src\entropy_hardware_alt.c + entropy_hardware_alt.c + 0 + 0 + + + 18 + 186 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\wrapper\src\net_module_alt.c + net_module_alt.c + 0 + 0 + + + 18 + 187 + 1 + 0 + 0 + 0 + ..\..\..\..\components\security\mbedtls\wrapper\src\timing_alt.c + timing_alt.c + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvprojx b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvprojx new file mode 100644 index 00000000..d8c88ce9 --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvprojx @@ -0,0 +1,1427 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + TencentOS_tiny + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + STM32L431RCTx + STMicroelectronics + Keil.STM32L4xx_DFP.2.0.0 + http://www.keil.com/pack + IRAM(0x20000000-0x2000FFFF) IROM(0x8000000-0x803FFFF) CLOCK(8000000) FPU2 CPUTYPE("Cortex-M4") + + + + + + + + + + + + + + + $$Device:STM32L431RCTx$CMSIS\SVD\STM32L4x1.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\obj\ + TencentOS_tiny + 1 + 0 + 1 + 1 + 0 + .\list\ + 1 + 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 + 1 + 0 + 0 + 0 + 0 + 3 + + + 0 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4107 + + 1 + STLink\ST-LINKIII-KEIL_SWO.dll + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + USE_HAL_DRIVER,STM32L431xx,PLATFORM_HAS_STDINT,INFRA_COMPAT,INFRA_LOG,INFRA_TIMER,INFRA_REPORT,INFRA_NET,INFRA_STRING,INFRA_SHA256,MBEDTLS_CONFIG_FILE=<qcloud/tls_psk_config.h> + + ..\..\BSP\Inc;..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Inc;..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Legacy;..\..\..\..\platform\vendor_bsp\st\CMSIS\Device\ST\STM32L4xx\Include;..\..\..\..\platform\vendor_bsp\st\CMSIS\Include;..\..\..\..\kernel\core\include;..\..\TOS-CONFIG;..\..\..\..\platform\arch\arm\cortex-m4\keil;..\..\..\..\kernel\pm\include;..\..\..\..\osal\cmsis_os;..\..\..\..\arch\arm\arm-v7m\common\include;..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc;..\..\BSP\Hardware\DHT11;..\..\BSP\Hardware\BH1750;..\..\BSP\Hardware\OLED;..\..\..\..\examples\helloworld;..\..\..\..\net\at\include;..\..\..\..\kernel\hal\include;..\..\..\..\net\sal_module_wrapper;..\..\..\..\examples\mqtt;..\..\..\..\devices\bc35_28_95;..\..\..\..\devices\esp8266;..\..\..\..\devices\m26;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\dev_sign;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\wrappers;..\..\..\..\components\security\mbedtls\3rdparty\include;..\..\..\..\components\security\mbedtls\wrapper\include + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application/MDK-ARM + + + startup_stm32l431xx.s + 2 + startup_stm32l431xx.s + + + + + Application/User + + + gpio.c + 1 + ..\..\BSP\Src\gpio.c + + + main.c + 1 + ..\..\BSP\Src\main.c + + + mcu_init.c + 1 + ..\..\BSP\Src\mcu_init.c + + + stm32l4xx_hal_msp.c + 1 + ..\..\BSP\Src\stm32l4xx_hal_msp.c + + + usart.c + 1 + ..\..\BSP\Src\usart.c + + + adc.c + 1 + ..\..\BSP\Src\adc.c + + + dac.c + 1 + ..\..\BSP\Src\dac.c + + + i2c.c + 1 + ..\..\BSP\Src\i2c.c + + + spi.c + 1 + ..\..\BSP\Src\spi.c + + + stm32l4xx_it_module.c + 1 + ..\..\BSP\Src\stm32l4xx_it_module.c + + + + + examples + + + mqtt_example.c + 1 + ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\mqtt_example.c + + + aliyun_iotkit_csdk_mqtt.c + 1 + ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\aliyun_iotkit_csdk_mqtt.c + + + + + Drivers/STM32L4xx_HAL_Driver + + + stm32l4xx_hal_tim.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim.c + + + stm32l4xx_hal_tim_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim_ex.c + + + stm32l4xx_hal_uart.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart.c + + + stm32l4xx_hal_uart_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart_ex.c + + + stm32l4xx_hal.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal.c + + + stm32l4xx_hal_i2c.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c.c + + + stm32l4xx_hal_i2c_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c_ex.c + + + stm32l4xx_hal_rcc.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc.c + + + stm32l4xx_hal_rcc_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc_ex.c + + + stm32l4xx_hal_flash.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash.c + + + stm32l4xx_hal_flash_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ex.c + + + stm32l4xx_hal_flash_ramfunc.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ramfunc.c + + + stm32l4xx_hal_gpio.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_gpio.c + + + stm32l4xx_hal_dma.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma.c + + + stm32l4xx_hal_dma_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma_ex.c + + + stm32l4xx_hal_pwr.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr.c + + + stm32l4xx_hal_pwr_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr_ex.c + + + stm32l4xx_hal_cortex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cortex.c + + + stm32l4xx_hal_adc_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc_ex.c + + + stm32l4xx_hal_adc.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc.c + + + stm32l4xx_hal_dac.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac.c + + + stm32l4xx_hal_dac_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac_ex.c + + + stm32l4xx_hal_spi.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi.c + + + stm32l4xx_hal_spi_ex.c + 1 + ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi_ex.c + + + + + Drivers/CMSIS + + + system_stm32l4xx.c + 1 + ..\..\BSP\Src\system_stm32l4xx.c + + + + + Hardware + + + DHT11_BUS.c + 1 + ..\..\BSP\Hardware\DHT11\DHT11_BUS.c + + + oled.c + 1 + ..\..\BSP\Hardware\OLED\oled.c + + + BH1750.c + 1 + ..\..\BSP\Hardware\BH1750\BH1750.c + + + + + kernel + + + tos_binary_heap.c + 1 + ..\..\..\..\kernel\core\tos_binary_heap.c + + + tos_char_fifo.c + 1 + ..\..\..\..\kernel\core\tos_char_fifo.c + + + tos_completion.c + 1 + ..\..\..\..\kernel\core\tos_completion.c + + + tos_countdownlatch.c + 1 + ..\..\..\..\kernel\core\tos_countdownlatch.c + + + tos_event.c + 1 + ..\..\..\..\kernel\core\tos_event.c + + + tos_global.c + 1 + ..\..\..\..\kernel\core\tos_global.c + + + tos_mail_queue.c + 1 + ..\..\..\..\kernel\core\tos_mail_queue.c + + + tos_message_queue.c + 1 + ..\..\..\..\kernel\core\tos_message_queue.c + + + tos_mmblk.c + 1 + ..\..\..\..\kernel\core\tos_mmblk.c + + + tos_mmheap.c + 1 + ..\..\..\..\kernel\core\tos_mmheap.c + + + tos_mutex.c + 1 + ..\..\..\..\kernel\core\tos_mutex.c + + + tos_pend.c + 1 + ..\..\..\..\kernel\core\tos_pend.c + + + tos_priority_mail_queue.c + 1 + ..\..\..\..\kernel\core\tos_priority_mail_queue.c + + + tos_priority_message_queue.c + 1 + ..\..\..\..\kernel\core\tos_priority_message_queue.c + + + tos_priority_queue.c + 1 + ..\..\..\..\kernel\core\tos_priority_queue.c + + + tos_ring_queue.c + 1 + ..\..\..\..\kernel\core\tos_ring_queue.c + + + tos_robin.c + 1 + ..\..\..\..\kernel\core\tos_robin.c + + + tos_sched.c + 1 + ..\..\..\..\kernel\core\tos_sched.c + + + tos_sem.c + 1 + ..\..\..\..\kernel\core\tos_sem.c + + + tos_sys.c + 1 + ..\..\..\..\kernel\core\tos_sys.c + + + tos_task.c + 1 + ..\..\..\..\kernel\core\tos_task.c + + + tos_tick.c + 1 + ..\..\..\..\kernel\core\tos_tick.c + + + tos_time.c + 1 + ..\..\..\..\kernel\core\tos_time.c + + + tos_timer.c + 1 + ..\..\..\..\kernel\core\tos_timer.c + + + + + cpu + + + port_s.S + 2 + ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_s.S + + + tos_cpu.c + 1 + ..\..\..\..\arch\arm\arm-v7m\common\tos_cpu.c + + + port_c.c + 1 + ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_c.c + + + + + cmsis + + + cmsis_os.c + 1 + ..\..\..\..\osal\cmsis_os\cmsis_os.c + + + + + config + + + tos_config.h + 5 + ..\..\TOS-CONFIG\tos_config.h + + + + + devices + + + bc35_28_95.c + 1 + ..\..\..\..\devices\bc35_28_95\bc35_28_95.c + + + esp8266.c + 1 + ..\..\..\..\devices\esp8266\esp8266.c + + + + + hal + + + tos_hal_uart.c + 1 + ..\..\..\..\platform\hal\st\stm32l4xx\src\tos_hal_uart.c + + + + + at + + + tos_at.c + 1 + ..\..\..\..\net\at\src\tos_at.c + + + tos_at_utils.c + 1 + ..\..\..\..\net\at\src\tos_at_utils.c + + + sal_module_wrapper.c + 1 + ..\..\..\..\net\sal_module_wrapper\sal_module_wrapper.c + + + + + port/TencentOS_tiny + + + osal_os.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_os.c + + + osal_tcp_module.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_tcp_module.c + + + osal_timer.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_timer.c + + + + + iotkit/mqtt + + + mqtt_api.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\mqtt_api.c + + + iotx_mqtt_client.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\iotx_mqtt_client.c + + + MQTTConnectClient.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTConnectClient.c + + + MQTTDeserializePublish.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTDeserializePublish.c + + + MQTTPacket.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTPacket.c + + + MQTTSerializePublish.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSerializePublish.c + + + MQTTSubscribeClient.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSubscribeClient.c + + + MQTTUnsubscribeClient.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTUnsubscribeClient.c + + + + + iotkit/infra + + + infra_aes.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_aes.c + + + infra_cjson.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_cjson.c + + + infra_compat.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_compat.c + + + infra_defs.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_defs.c + + + infra_httpc.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_httpc.c + + + infra_json_parser.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_json_parser.c + + + infra_log.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_log.c + + + infra_md5.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_md5.c + + + infra_mem_stats.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_mem_stats.c + + + infra_net.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_net.c + + + infra_preauth.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_preauth.c + + + infra_prt_nwk_payload.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_prt_nwk_payload.c + + + infra_report.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_report.c + + + infra_sha1.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha1.c + + + infra_sha256.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha256.c + + + infra_string.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_string.c + + + infra_timer.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_timer.c + + + + + iotkit/dev_sign + + + dev_sign_mqtt.c + 1 + ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\dev_sign\dev_sign_mqtt.c + + + + + mbedtls + + + aes.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\aes.c + + + aesni.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\aesni.c + + + arc4.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\arc4.c + + + aria.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\aria.c + + + asn1parse.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1parse.c + + + asn1write.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1write.c + + + base64.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\base64.c + + + bignum.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\bignum.c + + + blowfish.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\blowfish.c + + + camellia.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\camellia.c + + + ccm.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ccm.c + + + certs.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\certs.c + + + chacha20.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\chacha20.c + + + chachapoly.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\chachapoly.c + + + cipher.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher.c + + + cipher_wrap.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher_wrap.c + + + cmac.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\cmac.c + + + ctr_drbg.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ctr_drbg.c + + + debug.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\debug.c + + + des.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\des.c + + + dhm.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\dhm.c + + + ecdh.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdh.c + + + ecdsa.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdsa.c + + + ecjpake.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecjpake.c + + + ecp.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp.c + + + ecp_curves.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp_curves.c + + + entropy.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy.c + + + entropy_poll.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy_poll.c + + + error.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\error.c + + + gcm.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\gcm.c + + + havege.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\havege.c + + + hkdf.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\hkdf.c + + + hmac_drbg.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\hmac_drbg.c + + + md.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md.c + + + md_wrap.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md_wrap.c + + + md2.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md2.c + + + md4.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md4.c + + + md5.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\md5.c + + + memory_buffer_alloc.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\memory_buffer_alloc.c + + + net_sockets.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\net_sockets.c + + + nist_kw.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\nist_kw.c + + + oid.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\oid.c + + + padlock.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\padlock.c + + + pem.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pem.c + + + pk.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pk.c + + + pk_wrap.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pk_wrap.c + + + pkcs5.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs5.c + + + pkcs11.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs11.c + + + pkcs12.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs12.c + + + pkparse.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkparse.c + + + pkwrite.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\pkwrite.c + + + platform.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\platform.c + + + platform_util.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\platform_util.c + + + poly1305.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\poly1305.c + + + ripemd160.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ripemd160.c + + + rsa.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa.c + + + rsa_internal.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa_internal.c + + + sha1.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\sha1.c + + + sha256.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\sha256.c + + + sha512.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\sha512.c + + + ssl_cache.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cache.c + + + ssl_ciphersuites.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ciphersuites.c + + + ssl_cli.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cli.c + + + ssl_cookie.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cookie.c + + + ssl_srv.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_srv.c + + + ssl_ticket.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ticket.c + + + ssl_tls.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_tls.c + + + threading.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\threading.c + + + timing.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\timing.c + + + version.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\version.c + + + version_features.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\version_features.c + + + x509.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509.c + + + x509_create.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_create.c + + + x509_crl.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crl.c + + + x509_crt.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crt.c + + + x509_csr.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_csr.c + + + x509write_crt.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_crt.c + + + x509write_csr.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_csr.c + + + xtea.c + 1 + ..\..\..\..\components\security\mbedtls\3rdparty\src\xtea.c + + + entropy_hardware_alt.c + 1 + ..\..\..\..\components\security\mbedtls\wrapper\src\entropy_hardware_alt.c + + + net_module_alt.c + 1 + ..\..\..\..\components\security\mbedtls\wrapper\src\net_module_alt.c + + + timing_alt.c + 1 + ..\..\..\..\components\security\mbedtls\wrapper\src\timing_alt.c + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + +
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.build_log.htm b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.build_log.htm new file mode 100644 index 00000000..eac2a534 --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.build_log.htm @@ -0,0 +1,60 @@ + + +
+

µVision Build Log

+

Tool Versions:

+IDE-Version: ¦ÌVision V5.26.2.0 +Copyright (C) 2018 ARM Ltd and ARM Germany GmbH. All rights reserved. +License Information: sheldon dai, tencent, LIC=AK1CX-H5HPV-SGF7K-ZGDWF-QC6LB-GRJE8 + +Tool Versions: +Toolchain: MDK-ARM Professional Version: 5.26.2.0 +Toolchain Path: C:\Keil_v5\ARM\ARMCC\Bin +C Compiler: Armcc.exe V5.06 update 6 (build 750) +Assembler: Armasm.exe V5.06 update 6 (build 750) +Linker/Locator: ArmLink.exe V5.06 update 6 (build 750) +Library Manager: ArmAr.exe V5.06 update 6 (build 750) +Hex Converter: FromElf.exe V5.06 update 6 (build 750) +CPU DLL: SARMCM3.DLL V5.26.2.0 +Dialog DLL: DCM.DLL V1.17.2.0 +Target DLL: STLink\ST-LINKIII-KEIL_SWO.dll V3.0.5.0 +Dialog DLL: TCM.DLL V1.36.1.0 + +

Project:

+D:\github\fuck\TencentOS-tiny\board\TencentOS_tiny_EVB_MX_Plus\KEIL\aliyun_iotkit_csdk_mqtt\TencentOS_tiny.uvprojx +Project File Date: 10/31/2019 + +

Output:

+*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin' +Build target 'TencentOS_tiny' +compiling aliyun_iotkit_csdk_mqtt.c... +linking... +Program Size: Code=58316 RO-data=5772 RW-data=1144 ZI-data=50552 +FromELF: creating hex file... +".\obj\TencentOS_tiny.axf" - 0 Error(s), 0 Warning(s). + +

Software Packages used:

+ +Package Vendor: ARM + http://www.keil.com/pack/ARM.CMSIS.5.6.0.pack + ARM.CMSIS.5.6.0 + CMSIS (Cortex Microcontroller Software Interface Standard) + * Component: CORE Version: 5.3.0 + +Package Vendor: Keil + http://www.keil.com/pack/Keil.STM32L4xx_DFP.2.0.0.pack + Keil.STM32L4xx_DFP.2.0.0 + STMicroelectronics STM32L4 Series Device Support, Drivers and Examples + +

Collection of Component include folders:

+ .\RTE\_TencentOS_tiny + C:\Keil_v5\ARM\PACK\ARM\CMSIS\5.6.0\CMSIS\Core\Include + C:\Keil_v5\ARM\PACK\Keil\STM32L4xx_DFP\2.0.0\Drivers\CMSIS\Device\ST\STM32L4xx\Include + +

Collection of Component Files used:

+ + * Component: ARM::CMSIS:CORE:5.3.0 +Build Time Elapsed: 00:00:02 +
+ + diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.htm b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.htm new file mode 100644 index 00000000..90df1e9f --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.htm @@ -0,0 +1,5739 @@ + + +Static Call Graph - [.\obj\TencentOS_tiny.axf] +
+

Static Call Graph for image .\obj\TencentOS_tiny.axf


+

#<CALLGRAPH># ARM Linker, 5060750: Last Updated: Thu Oct 31 16:31:15 2019 +

+

Maximum Stack Usage = 1496 bytes + Unknown(Functions without stacksize, Cycles, Untraceable Function Pointers)

+Call chain for Maximum Stack Depth:

+application_entry ⇒ mqtt_basic_thread ⇒ IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +

+

+Functions with no stack information +

+ +

+

+Mutually Recursive functions +

  • ADC1_IRQHandler   ⇒   ADC1_IRQHandler
    + +

    +

    +Function Pointers +

      +
    • ADC1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • BusFault_Handler from stm32l4xx_it_module.o(i.BusFault_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • CAN1_RX0_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • CAN1_RX1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • CAN1_SCE_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • CAN1_TX_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • COMP_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • CRS_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel3_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel4_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel5_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel6_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA1_Channel7_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel3_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel4_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel5_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel6_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DMA2_Channel7_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • DebugMon_Handler from stm32l4xx_it_module.o(i.DebugMon_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI0_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI15_10_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI1_IRQHandler from stm32l4xx_it_module.o(i.EXTI1_IRQHandler) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI2_IRQHandler from stm32l4xx_it_module.o(i.EXTI2_IRQHandler) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI3_IRQHandler from stm32l4xx_it_module.o(i.EXTI3_IRQHandler) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI4_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • EXTI9_5_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • FLASH_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • FPU_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • HardFault_Handler from stm32l4xx_it_module.o(i.HardFault_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • I2C1_ER_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • I2C1_EV_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • I2C2_ER_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • I2C2_EV_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • I2C3_ER_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • I2C3_EV_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • IOT_MQTT_Publish_Simple from mqtt_api.o(i.IOT_MQTT_Publish_Simple) referenced from mqtt_api.o(i.iotx_mqtt_report_funcs) +
    • LPTIM1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • LPTIM2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • LPUART1_IRQHandler from stm32l4xx_it_module.o(i.LPUART1_IRQHandler) referenced from startup_stm32l431xx.o(RESET) +
    • MemManage_Handler from stm32l4xx_it_module.o(i.MemManage_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • NMI_Handler from stm32l4xx_it_module.o(i.NMI_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • PVD_PVM_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • PendSV_Handler from port_s.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • QUADSPI_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • RCC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • RNG_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • RTC_Alarm_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • RTC_WKUP_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • Reset_Handler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SAI1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SDMMC1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SPI1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SPI2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SPI3_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SVC_Handler from stm32l4xx_it_module.o(i.SVC_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • SWPMI1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • SysTick_Handler from stm32l4xx_it_module.o(i.SysTick_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • SystemInit from system_stm32l4xx.o(i.SystemInit) referenced from startup_stm32l431xx.o(.text) +
    • TAMP_STAMP_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM1_BRK_TIM15_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM1_CC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM1_TRG_COM_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM1_UP_TIM16_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM6_DAC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TIM7_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • TSC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • UART_DMAAbortOnError from stm32l4xx_hal_uart.o(i.UART_DMAAbortOnError) referenced from stm32l4xx_hal_uart.o(i.HAL_UART_IRQHandler) +
    • UART_RxISR_16BIT from stm32l4xx_hal_uart.o(i.UART_RxISR_16BIT) referenced from stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT) +
    • UART_RxISR_8BIT from stm32l4xx_hal_uart.o(i.UART_RxISR_8BIT) referenced from stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT) +
    • USART1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • USART2_IRQHandler from stm32l4xx_it_module.o(i.USART2_IRQHandler) referenced from startup_stm32l431xx.o(RESET) +
    • USART3_IRQHandler from stm32l4xx_it_module.o(i.USART3_IRQHandler) referenced from startup_stm32l431xx.o(RESET) +
    • UsageFault_Handler from stm32l4xx_it_module.o(i.UsageFault_Handler) referenced from startup_stm32l431xx.o(RESET) +
    • WWDG_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET) +
    • __main from entry.o(.ARM.Collect$$$$00000000) referenced from startup_stm32l431xx.o(.text) +
    • _sbackspace from _sgetc.o(.text) referenced from __0sscanf.o(.text) +
    • _scanf_char_input from scanf_char.o(.text) referenced from scanf_char.o(.text) +
    • _sgetc from _sgetc.o(.text) referenced from __0sscanf.o(.text) +
    • _snputc from printfa.o(i._snputc) referenced from printfa.o(i.__0snprintf) +
    • _snputc from printfa.o(i._snputc) referenced from printfa.o(i.__0vsnprintf) +
    • application_entry from aliyun_iotkit_csdk_mqtt.o(i.application_entry) referenced from main.o(.constdata) +
    • at_parser from tos_at.o(i.at_parser) referenced from tos_at.o(i.tos_at_init) +
    • bufchar from mqttpacket.o(i.bufchar) referenced from mqttpacket.o(i.MQTTPacket_decodeBuf) +
    • esp8266_close from esp8266.o(i.esp8266_close) referenced 2 times from esp8266.o(.data) +
    • esp8266_connect from esp8266.o(i.esp8266_connect) referenced 2 times from esp8266.o(.data) +
    • esp8266_incoming_data_process from esp8266.o(i.esp8266_incoming_data_process) referenced 2 times from esp8266.o(.data) +
    • esp8266_init from esp8266.o(i.esp8266_init) referenced 2 times from esp8266.o(.data) +
    • esp8266_parse_domain from esp8266.o(i.esp8266_parse_domain) referenced 2 times from esp8266.o(.data) +
    • esp8266_recv from esp8266.o(i.esp8266_recv) referenced 2 times from esp8266.o(.data) +
    • esp8266_recv_timeout from esp8266.o(i.esp8266_recv_timeout) referenced 2 times from esp8266.o(.data) +
    • esp8266_recvfrom from esp8266.o(i.esp8266_recvfrom) referenced 2 times from esp8266.o(.data) +
    • esp8266_recvfrom_timeout from esp8266.o(i.esp8266_recvfrom_timeout) referenced 2 times from esp8266.o(.data) +
    • esp8266_send from esp8266.o(i.esp8266_send) referenced 2 times from esp8266.o(.data) +
    • esp8266_sendto from esp8266.o(i.esp8266_sendto) referenced 2 times from esp8266.o(.data) +
    • example_event_handle from mqtt_example.o(i.example_event_handle) referenced from mqtt_example.o(i.mqtt_basic_thread) +
    • example_message_arrive from mqtt_example.o(i.example_message_arrive) referenced from mqtt_example.o(i.example_subscribe) +
    • fputc from mcu_init.o(i.fputc) referenced from printfa.o(i.__0printf) +
    • fputc from mcu_init.o(i.fputc) referenced from printfa.o(i.__0vprintf) +
    • iotx_net_connect from infra_net.o(i.iotx_net_connect) referenced from infra_net.o(i.iotx_net_init) +
    • iotx_net_disconnect from infra_net.o(i.iotx_net_disconnect) referenced from infra_net.o(i.iotx_net_init) +
    • isspace from isspace_c.o(.text) referenced from scanf_char.o(.text) +
    • knl_idle_entry from tos_sys.o(i.knl_idle_entry) referenced from tos_sys.o(i.knl_idle_init) +
    • main from main.o(i.main) referenced from entry9a.o(.ARM.Collect$$$$0000000B) +
    • task_exit from tos_task.o(i.task_exit) referenced from tos_task.o(i.tos_task_create) +
    • utils_net_read from infra_net.o(i.utils_net_read) referenced from infra_net.o(i.iotx_net_init) +
    • utils_net_write from infra_net.o(i.utils_net_write) referenced from infra_net.o(i.iotx_net_init) +
    +

    +

    +Global Symbols +

    +

    __main (Thumb, 0 bytes, Stack size unknown bytes, entry.o(.ARM.Collect$$$$00000000)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(.text) +
    +

    _main_stk (Thumb, 0 bytes, Stack size unknown bytes, entry2.o(.ARM.Collect$$$$00000001)) + +

    _main_scatterload (Thumb, 0 bytes, Stack size unknown bytes, entry5.o(.ARM.Collect$$$$00000004)) +

    [Calls]

    • >>   __scatterload +
    + +

    __main_after_scatterload (Thumb, 0 bytes, Stack size unknown bytes, entry5.o(.ARM.Collect$$$$00000004)) +

    [Called By]

    • >>   __scatterload +
    + +

    _main_clock (Thumb, 0 bytes, Stack size unknown bytes, entry7b.o(.ARM.Collect$$$$00000008)) + +

    _main_cpp_init (Thumb, 0 bytes, Stack size unknown bytes, entry8b.o(.ARM.Collect$$$$0000000A)) + +

    _main_init (Thumb, 0 bytes, Stack size unknown bytes, entry9a.o(.ARM.Collect$$$$0000000B)) + +

    __rt_final_cpp (Thumb, 0 bytes, Stack size unknown bytes, entry10a.o(.ARM.Collect$$$$0000000D)) + +

    __rt_final_exit (Thumb, 0 bytes, Stack size unknown bytes, entry11a.o(.ARM.Collect$$$$0000000F)) + +

    Reset_Handler (Thumb, 8 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    ADC1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +

    [Calls]

    • >>   ADC1_IRQHandler +
    +
    [Called By]
    • >>   ADC1_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    CAN1_RX0_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    CAN1_RX1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    CAN1_SCE_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    CAN1_TX_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    COMP_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    CRS_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel3_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel4_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel5_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel6_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA1_Channel7_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel3_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel4_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel5_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel6_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DMA2_Channel7_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    EXTI0_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    EXTI15_10_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    EXTI4_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    EXTI9_5_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    FLASH_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    FPU_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    I2C1_ER_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    I2C1_EV_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    I2C2_ER_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    I2C2_EV_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    I2C3_ER_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    I2C3_EV_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    LPTIM1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    LPTIM2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    PVD_PVM_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    QUADSPI_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    RCC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    RNG_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    RTC_Alarm_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    RTC_WKUP_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SAI1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SDMMC1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SPI1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SPI2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SPI3_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SWPMI1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TAMP_STAMP_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM1_BRK_TIM15_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM1_CC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM1_TRG_COM_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM1_UP_TIM16_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM6_DAC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TIM7_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    TSC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    USART1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    WWDG_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    port_int_disable (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text), UNUSED) + +

    port_int_enable (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text), UNUSED) + +

    port_cpsr_save (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +

    [Called By]

    • >>   tos_cpu_cpsr_save +
    + +

    port_cpsr_restore (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +

    [Called By]

    • >>   tos_cpu_cpsr_restore +
    + +

    port_clz (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +

    [Called By]

    • >>   tos_cpu_clz +
    + +

    port_sched_start (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +

    [Called By]

    • >>   cpu_sched_start +
    + +

    port_context_switch (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +

    [Called By]

    • >>   cpu_context_switch +
    + +

    port_irq_context_switch (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +

    [Called By]

    • >>   cpu_irq_context_switch +
    + +

    PendSV_Handler (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    __aeabi_uldivmod (Thumb, 98 bytes, Stack size 40 bytes, uldiv.o(.text)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = __aeabi_uldivmod +
    +
    [Calls]
    • >>   __aeabi_llsl +
    • >>   __aeabi_llsr +
    +
    [Called By]
    • >>   UART_SetConfig +
    • >>   tos_sleep_hmsm +
    • >>   tos_millisec2tick +
    • >>   cpu_init +
    • >>   _printf_core +
    • >>   _fp_digits +
    + +

    __aeabi_llsl (Thumb, 30 bytes, Stack size 0 bytes, llshl.o(.text)) +

    [Called By]

    • >>   __aeabi_uldivmod +
    • >>   _double_epilogue +
    • >>   __aeabi_dadd +
    • >>   __aeabi_d2ulz +
    + +

    _ll_shift_l (Thumb, 0 bytes, Stack size 0 bytes, llshl.o(.text), UNUSED) + +

    ___aeabi_memcpy8$move (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED) + +

    __aeabi_memcpy (Thumb, 64 bytes, Stack size 8 bytes, memmovea.o(.text)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = __aeabi_memcpy +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   tos_ring_q_enqueue +
    • >>   tos_ring_q_dequeue +
    • >>   at_echo_buffer_copy +
    • >>   iotx_mc_push_pubInfo_to +
    • >>   MQTTSubscribe +
    • >>   _sign_get_clientid +
    • >>   IOT_Sign_MQTT +
    • >>   IOT_Ioctl +
    • >>   iotx_mqtt_offline_subscribe +
    • >>   utils_sha256_update +
    • >>   utils_hmac_sha256 +
    • >>   writeMQTTString +
    • >>   writeCString +
    • >>   MQTTSerialize_publish +
    • >>   _iotx_generate_sign_string +
    + +

    __aeabi_memcpy4 (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = __aeabi_memcpy4 +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   iotx_mc_init +
    • >>   _iotx_generate_sign_string +
    + +

    __aeabi_memmove (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED) + +

    __aeabi_memmove4 (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED) + +

    __aeabi_memmove8 (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED) + +

    __aeabi_memset (Thumb, 14 bytes, Stack size 0 bytes, memseta.o(.text)) +

    [Called By]

    • >>   memset +
    • >>   __aeabi_memclr +
    + +

    __aeabi_memset4 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text), UNUSED) + +

    __aeabi_memset8 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text), UNUSED) + +

    __aeabi_memclr (Thumb, 4 bytes, Stack size 0 bytes, memseta.o(.text)) +

    [Calls]

    • >>   __aeabi_memset +
    +
    [Called By]
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceSecret +
    • >>   HAL_GetDeviceName +
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   at_uart_line_parse +
    • >>   tos_at_echo_create +
    • >>   iotx_report_devinfo +
    • >>   _sign_get_clientid +
    • >>   IOT_Sign_MQTT +
    • >>   IOT_Ioctl +
    • >>   HAL_GetFirmwareVersion +
    • >>   LITE_syslog_routine +
    • >>   infra_strtok +
    + +

    __aeabi_memclr4 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text)) +

    [Called By]

    • >>   HAL_UART_MspInit +
    • >>   SystemClock_Config +
    • >>   MX_GPIO_Init +
    • >>   IOT_MQTT_Publish_Simple +
    • >>   IOT_MQTT_Construct +
    • >>   mqtt_basic_thread +
    • >>   at_channel_init +
    • >>   tos_at_init +
    • >>   tos_at_channel_free +
    • >>   iotx_mc_release +
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_pub_wait_list_init +
    • >>   iotx_mc_pub_wait_list_deinit +
    • >>   iotx_mc_init +
    • >>   iotx_mc_handle_recv_PUBLISH +
    • >>   iotx_mc_check_topic +
    • >>   MQTTSubscribe +
    • >>   MQTTPubInfoProc +
    • >>   wrapper_mqtt_release +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    • >>   IOT_Sign_MQTT +
    • >>   IOT_Ioctl +
    • >>   iotx_mqtt_offline_subscribe +
    • >>   _offline_subs_list_init +
    • >>   _offline_subs_list_deinit +
    • >>   utils_sha256_init +
    • >>   utils_hmac_sha256 +
    • >>   MQTTPublish +
    • >>   _iotx_generate_sign_string +
    + +

    __aeabi_memclr8 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text), UNUSED) + +

    memset (Thumb, 18 bytes, Stack size 8 bytes, memseta.o(.text), UNUSED) +

    [Calls]

    • >>   __aeabi_memset +
    + +

    strstr (Thumb, 36 bytes, Stack size 12 bytes, strstr.o(.text)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = strstr +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   at_echo_status_set +
    • >>   esp8266_parse_domain +
    • >>   esp8266_is_link_broken +
    + +

    strncpy (Thumb, 24 bytes, Stack size 8 bytes, strncpy.o(.text)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = strncpy +
    +
    [Called By]
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceSecret +
    • >>   HAL_GetDeviceName +
    • >>   iotx_mc_check_topic +
    • >>   HAL_GetFirmwareVersion +
    + +

    strlen (Thumb, 14 bytes, Stack size 0 bytes, strlen.o(.text)) +

    [Called By]

    • >>   IOT_MQTT_Subscribe +
    • >>   IOT_MQTT_Publish_Simple +
    • >>   IOT_MQTT_Construct +
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceSecret +
    • >>   HAL_GetDeviceName +
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   at_is_echo_expect +
    • >>   at_event_do_get +
    • >>   iotx_mc_check_topic +
    • >>   iotx_mc_check_rule +
    • >>   iotx_mc_check_handle_is_identical_ex +
    • >>   MQTTSubscribe +
    • >>   wrapper_mqtt_subscribe +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    • >>   _sign_get_clientid +
    • >>   IOT_Sign_MQTT +
    • >>   IOT_Ioctl +
    • >>   iotx_mqtt_offline_subscribe +
    • >>   HAL_GetFirmwareVersion +
    • >>   LITE_syslog_routine +
    • >>   writeCString +
    • >>   MQTTstrlen +
    • >>   iotx_net_init +
    • >>   infra_strtok +
    • >>   MQTTPacket_equals +
    • >>   MQTTPublish +
    • >>   _iotx_generate_sign_string +
    + +

    memcmp (Thumb, 26 bytes, Stack size 12 bytes, memcmp.o(.text)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = memcmp +
    +
    [Called By]
    • >>   iotx_mqtt_offline_subscribe +
    • >>   infra_strtok +
    • >>   MQTTPacket_equals +
    + +

    strncmp (Thumb, 30 bytes, Stack size 12 bytes, strncmp.o(.text)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = strncmp +
    +
    [Called By]
    • >>   at_is_echo_expect +
    • >>   at_event_do_get +
    • >>   iotx_mc_check_handle_is_identical_ex +
    + +

    __0sscanf (Thumb, 48 bytes, Stack size 72 bytes, __0sscanf.o(.text)) +

    [Stack]

    • Max Depth = 216
    • Call Chain = __0sscanf ⇒ __vfscanf_char ⇒ __vfscanf ⇒ _scanf_string +
    +
    [Calls]
    • >>   __vfscanf_char +
    +
    [Called By]
    • >>   esp8266_parse_domain +
    + +

    _scanf_string (Thumb, 224 bytes, Stack size 56 bytes, _scanf_str.o(.text)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = _scanf_string +
    +
    [Called By]
    • >>   __vfscanf +
    + +

    __aeabi_ddiv (Thumb, 222 bytes, Stack size 32 bytes, ddiv.o(.text), UNUSED) +

    [Calls]

    • >>   _double_round +
    +
    [Called By]
    • >>   _fp_digits +
    + +

    __aeabi_uidiv (Thumb, 0 bytes, Stack size 12 bytes, uidiv.o(.text), UNUSED) + +

    __aeabi_uidivmod (Thumb, 44 bytes, Stack size 12 bytes, uidiv.o(.text), UNUSED) +

    [Called By]

    • >>   _printf_core +
    + +

    __aeabi_llsr (Thumb, 32 bytes, Stack size 0 bytes, llushr.o(.text)) +

    [Called By]

    • >>   __aeabi_uldivmod +
    • >>   _double_epilogue +
    • >>   __aeabi_d2ulz +
    + +

    _ll_ushift_r (Thumb, 0 bytes, Stack size 0 bytes, llushr.o(.text), UNUSED) + +

    __vfscanf_char (Thumb, 20 bytes, Stack size 0 bytes, scanf_char.o(.text)) +

    [Stack]

    • Max Depth = 144
    • Call Chain = __vfscanf_char ⇒ __vfscanf ⇒ _scanf_string +
    +
    [Calls]
    • >>   __vfscanf +
    +
    [Called By]
    • >>   __0sscanf +
    + +

    _sgetc (Thumb, 30 bytes, Stack size 0 bytes, _sgetc.o(.text)) +
    [Address Reference Count : 1]

    • __0sscanf.o(.text) +
    +

    _sbackspace (Thumb, 34 bytes, Stack size 0 bytes, _sgetc.o(.text)) +
    [Address Reference Count : 1]

    • __0sscanf.o(.text) +
    +

    __I$use$fp (Thumb, 0 bytes, Stack size 8 bytes, iusefp.o(.text), UNUSED) + +

    _double_round (Thumb, 30 bytes, Stack size 8 bytes, depilogue.o(.text), UNUSED) +

    [Called By]

    • >>   __aeabi_ddiv +
    • >>   _double_epilogue +
    • >>   __aeabi_dadd +
    + +

    _double_epilogue (Thumb, 156 bytes, Stack size 32 bytes, depilogue.o(.text), UNUSED) +

    [Calls]

    • >>   __aeabi_llsl +
    • >>   __aeabi_llsr +
    • >>   _double_round +
    +
    [Called By]
    • >>   __aeabi_dmul +
    • >>   __aeabi_dadd +
    + +

    __aeabi_dadd (Thumb, 322 bytes, Stack size 48 bytes, dadd.o(.text), UNUSED) +

    [Calls]

    • >>   __aeabi_llsl +
    • >>   __aeabi_lasr +
    • >>   _double_epilogue +
    • >>   _double_round +
    +
    [Called By]
    • >>   __aeabi_drsub +
    • >>   __aeabi_dsub +
    • >>   _fp_digits +
    + +

    __aeabi_dsub (Thumb, 6 bytes, Stack size 0 bytes, dadd.o(.text), UNUSED) +

    [Calls]

    • >>   __aeabi_dadd +
    + +

    __aeabi_drsub (Thumb, 6 bytes, Stack size 0 bytes, dadd.o(.text), UNUSED) +

    [Calls]

    • >>   __aeabi_dadd +
    + +

    __aeabi_dmul (Thumb, 228 bytes, Stack size 48 bytes, dmul.o(.text), UNUSED) +

    [Calls]

    • >>   _double_epilogue +
    +
    [Called By]
    • >>   _fp_digits +
    + +

    __aeabi_d2ulz (Thumb, 48 bytes, Stack size 0 bytes, dfixul.o(.text), UNUSED) +

    [Calls]

    • >>   __aeabi_llsl +
    • >>   __aeabi_llsr +
    +
    [Called By]
    • >>   _fp_digits +
    + +

    __aeabi_cdrcmple (Thumb, 48 bytes, Stack size 0 bytes, cdrcmple.o(.text), UNUSED) +

    [Called By]

    • >>   _fp_digits +
    + +

    __scatterload (Thumb, 28 bytes, Stack size 0 bytes, init.o(.text)) +

    [Calls]

    • >>   __main_after_scatterload +
    +
    [Called By]
    • >>   _main_scatterload +
    + +

    __scatterload_rt2 (Thumb, 0 bytes, Stack size 0 bytes, init.o(.text), UNUSED) + +

    __aeabi_lasr (Thumb, 36 bytes, Stack size 0 bytes, llsshr.o(.text), UNUSED) +

    [Called By]

    • >>   __aeabi_dadd +
    + +

    _ll_sshift_r (Thumb, 0 bytes, Stack size 0 bytes, llsshr.o(.text), UNUSED) + +

    isspace (Thumb, 10 bytes, Stack size 0 bytes, isspace_c.o(.text)) +

    [Calls]

    • >>   __ctype_lookup +
    +
    [Address Reference Count : 1]
    • scanf_char.o(.text) +
    +

    __vfscanf (Thumb, 808 bytes, Stack size 88 bytes, _scanf.o(.text)) +

    [Stack]

    • Max Depth = 144
    • Call Chain = __vfscanf ⇒ _scanf_string +
    +
    [Calls]
    • >>   _scanf_string +
    +
    [Called By]
    • >>   __vfscanf_char +
    + +

    __ctype_lookup (Thumb, 34 bytes, Stack size 0 bytes, ctype_c.o(.text)) +

    [Called By]

    • >>   isspace +
    + +

    __decompress (Thumb, 0 bytes, Stack size unknown bytes, __dczerorl2.o(.text), UNUSED) + +

    __decompress1 (Thumb, 86 bytes, Stack size unknown bytes, __dczerorl2.o(.text), UNUSED) + +

    BusFault_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.BusFault_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    DHT11_Init (Thumb, 48 bytes, Stack size 8 bytes, dht11_bus.o(i.DHT11_Init)) +

    [Stack]

    • Max Depth = 52
    • Call Chain = DHT11_Init ⇒ DHT11_Mode_Out_PP ⇒ HAL_GPIO_Init +
    +
    [Calls]
    • >>   HAL_GPIO_WritePin +
    • >>   DHT11_Mode_Out_PP +
    +
    [Called By]
    • >>   board_init +
    + +

    DebugMon_Handler (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.DebugMon_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    EXTI1_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.EXTI1_IRQHandler)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = EXTI1_IRQHandler ⇒ HAL_GPIO_EXTI_IRQHandler +
    +
    [Calls]
    • >>   HAL_GPIO_EXTI_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    EXTI2_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.EXTI2_IRQHandler)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = EXTI2_IRQHandler ⇒ HAL_GPIO_EXTI_IRQHandler +
    +
    [Calls]
    • >>   HAL_GPIO_EXTI_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    EXTI3_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.EXTI3_IRQHandler)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = EXTI3_IRQHandler ⇒ HAL_GPIO_EXTI_IRQHandler +
    +
    [Calls]
    • >>   HAL_GPIO_EXTI_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    Error_Handler (Thumb, 2 bytes, Stack size 0 bytes, mcu_init.o(i.Error_Handler)) +

    [Called By]

    • >>   MX_USART1_UART_Init +
    • >>   MX_LPUART1_UART_Init +
    • >>   MX_USART3_UART_Init +
    • >>   MX_USART2_UART_Init +
    • >>   SystemClock_Config +
    + +

    HAL_DMA_Abort_IT (Thumb, 92 bytes, Stack size 16 bytes, stm32l4xx_hal_dma.o(i.HAL_DMA_Abort_IT)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = HAL_DMA_Abort_IT +
    +
    [Called By]
    • >>   HAL_UART_IRQHandler +
    + +

    HAL_Delay (Thumb, 32 bytes, Stack size 16 bytes, stm32l4xx_hal.o(i.HAL_Delay)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = HAL_Delay +
    +
    [Calls]
    • >>   HAL_GetTick +
    +
    [Called By]
    • >>   OLED_Init +
    + +

    HAL_Free (Thumb, 12 bytes, Stack size 8 bytes, osal_os.o(i.HAL_Free)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = HAL_Free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_mmheap_free +
    +
    [Called By]
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   iotx_report_devinfo +
    • >>   HAL_MutexDestroy +
    + +

    HAL_GPIO_DeInit (Thumb, 256 bytes, Stack size 20 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_DeInit)) +

    [Stack]

    • Max Depth = 20
    • Call Chain = HAL_GPIO_DeInit +
    +
    [Called By]
    • >>   HAL_UART_MspDeInit +
    + +

    HAL_GPIO_EXTI_Callback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_EXTI_Callback)) +

    [Called By]

    • >>   HAL_GPIO_EXTI_IRQHandler +
    + +

    HAL_GPIO_EXTI_IRQHandler (Thumb, 24 bytes, Stack size 8 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_EXTI_IRQHandler)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = HAL_GPIO_EXTI_IRQHandler +
    +
    [Calls]
    • >>   HAL_GPIO_EXTI_Callback +
    +
    [Called By]
    • >>   EXTI3_IRQHandler +
    • >>   EXTI2_IRQHandler +
    • >>   EXTI1_IRQHandler +
    + +

    HAL_GPIO_Init (Thumb, 428 bytes, Stack size 20 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_Init)) +

    [Stack]

    • Max Depth = 20
    • Call Chain = HAL_GPIO_Init +
    +
    [Called By]
    • >>   HAL_UART_MspInit +
    • >>   MX_GPIO_Init +
    • >>   DHT11_Mode_Out_PP +
    + +

    HAL_GPIO_WritePin (Thumb, 10 bytes, Stack size 0 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_WritePin)) +

    [Called By]

    • >>   DHT11_Init +
    • >>   MX_GPIO_Init +
    • >>   Write_IIC_Byte +
    • >>   IIC_Wait_Ack +
    • >>   IIC_Stop +
    • >>   IIC_Start +
    + +

    HAL_GetDeviceName (Thumb, 38 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetDeviceName)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_GetDeviceName ⇒ strncpy +
    +
    [Calls]
    • >>   strlen +
    • >>   strncpy +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   mqtt_basic_thread +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    + +

    HAL_GetDeviceSecret (Thumb, 34 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetDeviceSecret)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_GetDeviceSecret ⇒ strncpy +
    +
    [Calls]
    • >>   strlen +
    • >>   strncpy +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   mqtt_basic_thread +
    + +

    HAL_GetFirmwareVersion (Thumb, 44 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetFirmwareVersion)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_GetFirmwareVersion ⇒ strncpy +
    +
    [Calls]
    • >>   strlen +
    • >>   strncpy +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   iotx_report_firmware_version +
    + +

    HAL_GetProductKey (Thumb, 34 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetProductKey)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_GetProductKey ⇒ strncpy +
    +
    [Calls]
    • >>   strlen +
    • >>   strncpy +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   mqtt_basic_thread +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    + +

    HAL_GetTick (Thumb, 6 bytes, Stack size 0 bytes, stm32l4xx_hal.o(i.HAL_GetTick)) +

    [Called By]

    • >>   HAL_UART_Transmit +
    • >>   HAL_RCC_OscConfig +
    • >>   HAL_RCC_ClockConfig +
    • >>   HAL_RCCEx_PeriphCLKConfig +
    • >>   HAL_Delay +
    • >>   UART_WaitOnFlagUntilTimeout +
    • >>   UART_CheckIdleState +
    • >>   RCCEx_PLLSAI1_Config +
    + +

    HAL_IncTick (Thumb, 12 bytes, Stack size 0 bytes, stm32l4xx_hal.o(i.HAL_IncTick)) +

    [Called By]

    • >>   SysTick_Handler +
    + +

    HAL_Init (Thumb, 30 bytes, Stack size 8 bytes, stm32l4xx_hal.o(i.HAL_Init)) +

    [Stack]

    • Max Depth = 72
    • Call Chain = HAL_Init ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_MspInit +
    • >>   HAL_InitTick +
    • >>   HAL_NVIC_SetPriorityGrouping +
    +
    [Called By]
    • >>   board_init +
    + +

    HAL_InitTick (Thumb, 44 bytes, Stack size 16 bytes, stm32l4xx_hal.o(i.HAL_InitTick)) +

    [Stack]

    • Max Depth = 64
    • Call Chain = HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_NVIC_SetPriority +
    • >>   HAL_SYSTICK_Config +
    +
    [Called By]
    • >>   HAL_RCC_OscConfig +
    • >>   HAL_RCC_ClockConfig +
    • >>   HAL_Init +
    + +

    HAL_Malloc (Thumb, 12 bytes, Stack size 8 bytes, osal_os.o(i.HAL_Malloc)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   tos_mmheap_alloc +
    +
    [Called By]
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   iotx_report_devinfo +
    • >>   HAL_MutexCreate +
    + +

    HAL_MspInit (Thumb, 58 bytes, Stack size 8 bytes, stm32l4xx_hal_msp.o(i.HAL_MspInit)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = HAL_MspInit +
    +
    [Called By]
    • >>   HAL_Init +
    + +

    HAL_MutexCreate (Thumb, 20 bytes, Stack size 8 bytes, osal_os.o(i.HAL_MutexCreate)) +

    [Stack]

    • Max Depth = 144 + Unknown Stack Size +
    • Call Chain = HAL_MutexCreate ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   HAL_Malloc +
    • >>   tos_mutex_create +
    +
    [Called By]
    • >>   iotx_mc_init +
    • >>   _offline_subs_list_init +
    + +

    HAL_MutexDestroy (Thumb, 32 bytes, Stack size 16 bytes, osal_os.o(i.HAL_MutexDestroy)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = HAL_MutexDestroy ⇒ HAL_Free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   HAL_Printf +
    • >>   HAL_Free +
    • >>   tos_mutex_destroy +
    +
    [Called By]
    • >>   iotx_mc_init +
    • >>   wrapper_mqtt_release +
    • >>   _offline_subs_list_deinit +
    + +

    HAL_MutexLock (Thumb, 24 bytes, Stack size 16 bytes, osal_os.o(i.HAL_MutexLock)) +

    [Stack]

    • Max Depth = 152 + Unknown Stack Size +
    • Call Chain = HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_Printf +
    • >>   tos_mutex_pend +
    +
    [Called By]
    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_get_next_packetid +
    • >>   iotx_mc_get_client_state +
    • >>   iotx_mc_deliver_message +
    • >>   iotx_mc_cycle +
    • >>   _iotx_mqtt_event_handle_sub +
    • >>   MQTTSubscribe +
    • >>   MQTTRePublish +
    • >>   MQTTPuback +
    • >>   MQTTPubInfoProc +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   wrapper_mqtt_yield +
    • >>   iotx_mqtt_offline_subscribe +
    • >>   iotx_mqtt_deal_offline_subs +
    • >>   _mqtt_cycle +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    HAL_MutexUnlock (Thumb, 24 bytes, Stack size 16 bytes, osal_os.o(i.HAL_MutexUnlock)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = HAL_MutexUnlock ⇒ tos_mutex_post ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   HAL_Printf +
    • >>   tos_mutex_post +
    +
    [Called By]
    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_get_next_packetid +
    • >>   iotx_mc_get_client_state +
    • >>   iotx_mc_deliver_message +
    • >>   iotx_mc_cycle +
    • >>   _iotx_mqtt_event_handle_sub +
    • >>   MQTTSubscribe +
    • >>   MQTTRePublish +
    • >>   MQTTPuback +
    • >>   MQTTPubInfoProc +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   wrapper_mqtt_yield +
    • >>   iotx_mqtt_offline_subscribe +
    • >>   iotx_mqtt_deal_offline_subs +
    • >>   _mqtt_cycle +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    HAL_NVIC_DisableIRQ (Thumb, 62 bytes, Stack size 8 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_DisableIRQ)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = HAL_NVIC_DisableIRQ +
    +
    [Called By]
    • >>   HAL_UART_MspDeInit +
    + +

    HAL_NVIC_EnableIRQ (Thumb, 32 bytes, Stack size 0 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_EnableIRQ)) +

    [Called By]

    • >>   HAL_UART_MspInit +
    • >>   MX_GPIO_Init +
    + +

    HAL_NVIC_SetPriority (Thumb, 124 bytes, Stack size 40 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_SetPriority)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   __NVIC_SetPriority +
    • >>   __NVIC_GetPriorityGrouping +
    +
    [Called By]
    • >>   HAL_UART_MspInit +
    • >>   MX_GPIO_Init +
    • >>   HAL_InitTick +
    + +

    HAL_NVIC_SetPriorityGrouping (Thumb, 32 bytes, Stack size 0 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_SetPriorityGrouping)) +

    [Called By]

    • >>   HAL_Init +
    + +

    HAL_PWREx_ControlVoltageScaling (Thumb, 128 bytes, Stack size 0 bytes, stm32l4xx_hal_pwr_ex.o(i.HAL_PWREx_ControlVoltageScaling)) +

    [Called By]

    • >>   SystemClock_Config +
    + +

    HAL_PWREx_GetVoltageRange (Thumb, 10 bytes, Stack size 0 bytes, stm32l4xx_hal_pwr_ex.o(i.HAL_PWREx_GetVoltageRange)) +

    [Called By]

    • >>   RCC_SetFlashLatencyFromMSIRange +
    + +

    HAL_PWR_EnableBkUpAccess (Thumb, 14 bytes, Stack size 0 bytes, stm32l4xx_hal_pwr.o(i.HAL_PWR_EnableBkUpAccess)) +

    [Called By]

    • >>   SystemClock_Config +
    + +

    HAL_Printf (Thumb, 26 bytes, Stack size 24 bytes, osal_os.o(i.HAL_Printf)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_Printf +
    +
    [Calls]
    • >>   vprintf +
    +
    [Called By]
    • >>   mqtt_basic_thread +
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   example_message_arrive +
    • >>   example_event_handle +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   HAL_MutexDestroy +
    • >>   LITE_syslog_routine +
    + +

    HAL_RCCEx_EnableMSIPLLMode (Thumb, 14 bytes, Stack size 0 bytes, stm32l4xx_hal_rcc_ex.o(i.HAL_RCCEx_EnableMSIPLLMode)) +

    [Called By]

    • >>   SystemClock_Config +
    + +

    HAL_RCCEx_PeriphCLKConfig (Thumb, 894 bytes, Stack size 32 bytes, stm32l4xx_hal_rcc_ex.o(i.HAL_RCCEx_PeriphCLKConfig)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = HAL_RCCEx_PeriphCLKConfig ⇒ RCCEx_PLLSAI1_Config +
    +
    [Calls]
    • >>   HAL_GetTick +
    • >>   RCCEx_PLLSAI1_Config +
    +
    [Called By]
    • >>   SystemClock_Config +
    + +

    HAL_RCC_ClockConfig (Thumb, 358 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_ClockConfig)) +

    [Stack]

    • Max Depth = 88
    • Call Chain = HAL_RCC_ClockConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_InitTick +
    • >>   HAL_RCC_GetSysClockFreq +
    • >>   HAL_GetTick +
    +
    [Called By]
    • >>   SystemClock_Config +
    + +

    HAL_RCC_GetHCLKFreq (Thumb, 6 bytes, Stack size 0 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetHCLKFreq)) +

    [Called By]

    • >>   HAL_RCC_GetPCLK2Freq +
    • >>   HAL_RCC_GetPCLK1Freq +
    + +

    HAL_RCC_GetPCLK1Freq (Thumb, 26 bytes, Stack size 4 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetPCLK1Freq)) +

    [Stack]

    • Max Depth = 4
    • Call Chain = HAL_RCC_GetPCLK1Freq +
    +
    [Calls]
    • >>   HAL_RCC_GetHCLKFreq +
    +
    [Called By]
    • >>   UART_SetConfig +
    + +

    HAL_RCC_GetPCLK2Freq (Thumb, 26 bytes, Stack size 4 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetPCLK2Freq)) +

    [Stack]

    • Max Depth = 4
    • Call Chain = HAL_RCC_GetPCLK2Freq +
    +
    [Calls]
    • >>   HAL_RCC_GetHCLKFreq +
    +
    [Called By]
    • >>   UART_SetConfig +
    + +

    HAL_RCC_GetSysClockFreq (Thumb, 266 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetSysClockFreq)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_RCC_GetSysClockFreq +
    +
    [Called By]
    • >>   HAL_RCC_OscConfig +
    • >>   HAL_RCC_ClockConfig +
    • >>   UART_SetConfig +
    + +

    HAL_RCC_OscConfig (Thumb, 1660 bytes, Stack size 32 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_OscConfig)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   RCC_SetFlashLatencyFromMSIRange +
    • >>   HAL_InitTick +
    • >>   HAL_RCC_GetSysClockFreq +
    • >>   HAL_GetTick +
    +
    [Called By]
    • >>   SystemClock_Config +
    + +

    HAL_SYSTICK_Config (Thumb, 52 bytes, Stack size 16 bytes, stm32l4xx_hal_cortex.o(i.HAL_SYSTICK_Config)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = HAL_SYSTICK_Config ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   __NVIC_SetPriority +
    +
    [Called By]
    • >>   HAL_InitTick +
    + +

    HAL_SleepMs (Thumb, 18 bytes, Stack size 8 bytes, osal_os.o(i.HAL_SleepMs)) +

    [Stack]

    • Max Depth = 144 + Unknown Stack Size +
    • Call Chain = HAL_SleepMs ⇒ tos_sleep_hmsm ⇒ tos_task_delay ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_sleep_hmsm +
    +
    [Called By]
    • >>   iotx_mc_handle_reconnect +
    • >>   _mqtt_connect +
    • >>   wrapper_mqtt_release +
    • >>   wrapper_mqtt_connect +
    • >>   _mqtt_cycle +
    + +

    HAL_Snprintf (Thumb, 38 bytes, Stack size 40 bytes, osal_os.o(i.HAL_Snprintf)) +

    [Stack]

    • Max Depth = 64
    • Call Chain = HAL_Snprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   vsnprintf +
    +
    [Called By]
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    + +

    HAL_TCP_Destroy (Thumb, 14 bytes, Stack size 8 bytes, osal_tcp_module.o(i.HAL_TCP_Destroy)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = HAL_TCP_Destroy ⇒ tos_sal_module_close +
    +
    [Calls]
    • >>   tos_sal_module_close +
    +
    [Called By]
    • >>   disconnect_tcp +
    + +

    HAL_TCP_Establish (Thumb, 126 bytes, Stack size 32 bytes, osal_tcp_module.o(i.HAL_TCP_Establish)) +

    [Stack]

    • Max Depth = 64
    • Call Chain = HAL_TCP_Establish ⇒ __2snprintf +
    +
    [Calls]
    • >>   tos_sal_module_init +
    • >>   tos_sal_module_connect +
    • >>   __2snprintf +
    • >>   __2printf +
    +
    [Called By]
    • >>   connect_tcp +
    + +

    HAL_TCP_Read (Thumb, 28 bytes, Stack size 24 bytes, osal_tcp_module.o(i.HAL_TCP_Read)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = HAL_TCP_Read ⇒ tos_sal_module_recv_timeout +
    +
    [Calls]
    • >>   tos_sal_module_recv_timeout +
    +
    [Called By]
    • >>   read_tcp +
    + +

    HAL_TCP_Write (Thumb, 26 bytes, Stack size 24 bytes, osal_tcp_module.o(i.HAL_TCP_Write)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = HAL_TCP_Write ⇒ tos_sal_module_send +
    +
    [Calls]
    • >>   tos_sal_module_send +
    +
    [Called By]
    • >>   write_tcp +
    + +

    HAL_UARTEx_WakeupCallback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_uart_ex.o(i.HAL_UARTEx_WakeupCallback)) +

    [Called By]

    • >>   HAL_UART_IRQHandler +
    + +

    HAL_UART_DeInit (Thumb, 72 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_DeInit)) +

    [Stack]

    • Max Depth = 36
    • Call Chain = HAL_UART_DeInit ⇒ HAL_UART_MspDeInit ⇒ HAL_GPIO_DeInit +
    +
    [Calls]
    • >>   HAL_UART_MspDeInit +
    +
    [Called By]
    • >>   tos_hal_uart_deinit +
    + +

    HAL_UART_ErrorCallback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_ErrorCallback)) +

    [Called By]

    • >>   HAL_UART_IRQHandler +
    • >>   UART_DMAAbortOnError +
    + +

    HAL_UART_IRQHandler (Thumb, 392 bytes, Stack size 24 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_IRQHandler)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT +
    +
    [Calls]
    • >>   HAL_UART_ErrorCallback +
    • >>   HAL_UARTEx_WakeupCallback +
    • >>   HAL_DMA_Abort_IT +
    • >>   UART_EndTransmit_IT +
    • >>   UART_EndRxTransfer +
    +
    [Called By]
    • >>   USART3_IRQHandler +
    • >>   USART2_IRQHandler +
    • >>   LPUART1_IRQHandler +
    + +

    HAL_UART_Init (Thumb, 120 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_Init)) +

    [Stack]

    • Max Depth = 88
    • Call Chain = HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_UART_MspInit +
    • >>   UART_SetConfig +
    • >>   UART_CheckIdleState +
    • >>   UART_AdvFeatureConfig +
    +
    [Called By]
    • >>   MX_USART1_UART_Init +
    • >>   MX_LPUART1_UART_Init +
    • >>   MX_USART3_UART_Init +
    • >>   MX_USART2_UART_Init +
    + +

    HAL_UART_MspDeInit (Thumb, 114 bytes, Stack size 8 bytes, usart.o(i.HAL_UART_MspDeInit)) +

    [Stack]

    • Max Depth = 28
    • Call Chain = HAL_UART_MspDeInit ⇒ HAL_GPIO_DeInit +
    +
    [Calls]
    • >>   HAL_NVIC_DisableIRQ +
    • >>   HAL_GPIO_DeInit +
    +
    [Called By]
    • >>   HAL_UART_DeInit +
    • >>   tos_hal_uart_deinit +
    + +

    HAL_UART_MspInit (Thumb, 342 bytes, Stack size 32 bytes, usart.o(i.HAL_UART_MspInit)) +

    [Stack]

    • Max Depth = 80
    • Call Chain = HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_NVIC_SetPriority +
    • >>   HAL_NVIC_EnableIRQ +
    • >>   HAL_GPIO_Init +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   HAL_UART_Init +
    + +

    HAL_UART_Receive_IT (Thumb, 214 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = HAL_UART_Receive_IT +
    +
    [Called By]
    • >>   MX_LPUART1_UART_Init +
    • >>   HAL_UART_RxCpltCallback +
    + +

    HAL_UART_RxCpltCallback (Thumb, 32 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.HAL_UART_RxCpltCallback)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = HAL_UART_RxCpltCallback ⇒ tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   HAL_UART_Receive_IT +
    • >>   tos_at_uart_write_byte +
    +
    [Called By]
    • >>   UART_RxISR_8BIT +
    • >>   UART_RxISR_16BIT +
    + +

    HAL_UART_Transmit (Thumb, 200 bytes, Stack size 32 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_Transmit)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = HAL_UART_Transmit ⇒ UART_WaitOnFlagUntilTimeout +
    +
    [Calls]
    • >>   HAL_GetTick +
    • >>   UART_WaitOnFlagUntilTimeout +
    +
    [Called By]
    • >>   fputc +
    • >>   tos_hal_uart_write +
    + +

    HAL_UART_TxCpltCallback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_TxCpltCallback)) +

    [Called By]

    • >>   UART_EndTransmit_IT +
    + +

    HAL_UptimeMs (Thumb, 8 bytes, Stack size 8 bytes, osal_timer.o(i.HAL_UptimeMs)) +

    [Stack]

    • Max Depth = 32 + Unknown Stack Size +
    • Call Chain = HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_systick_get +
    +
    [Called By]
    • >>   utils_time_spend +
    • >>   utils_time_is_expired +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_start +
    • >>   iotx_time_left +
    + +

    HAL_Vsnprintf (Thumb, 24 bytes, Stack size 32 bytes, osal_os.o(i.HAL_Vsnprintf)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   vsnprintf +
    +
    [Called By]
    • >>   LITE_syslog_routine +
    + +

    HardFault_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.HardFault_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    IIC_Start (Thumb, 48 bytes, Stack size 8 bytes, oled.o(i.IIC_Start)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = IIC_Start +
    +
    [Calls]
    • >>   HAL_GPIO_WritePin +
    +
    [Called By]
    • >>   Write_IIC_Data +
    • >>   Write_IIC_Command +
    + +

    IIC_Stop (Thumb, 36 bytes, Stack size 8 bytes, oled.o(i.IIC_Stop)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = IIC_Stop +
    +
    [Calls]
    • >>   HAL_GPIO_WritePin +
    +
    [Called By]
    • >>   Write_IIC_Data +
    • >>   Write_IIC_Command +
    + +

    IIC_Wait_Ack (Thumb, 28 bytes, Stack size 8 bytes, oled.o(i.IIC_Wait_Ack)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = IIC_Wait_Ack +
    +
    [Calls]
    • >>   HAL_GPIO_WritePin +
    +
    [Called By]
    • >>   Write_IIC_Data +
    • >>   Write_IIC_Command +
    + +

    IOT_Ioctl (Thumb, 312 bytes, Stack size 24 bytes, infra_compat.o(i.IOT_Ioctl)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = IOT_Ioctl ⇒ __aeabi_memcpy +
    +
    [Calls]
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memclr +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    + +

    IOT_MQTT_Construct (Thumb, 1534 bytes, Stack size 360 bytes, mqtt_api.o(i.IOT_MQTT_Construct)) +

    [Stack]

    • Max Depth = 1416 + Unknown Stack Size +
    • Call Chain = IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceSecret +
    • >>   HAL_GetDeviceName +
    • >>   wrapper_mqtt_release +
    • >>   wrapper_mqtt_init +
    • >>   wrapper_mqtt_connect +
    • >>   iotx_event_callback +
    • >>   _sign_get_clientid +
    • >>   LITE_syslog +
    • >>   IOT_Sign_MQTT +
    • >>   IOT_Ioctl +
    • >>   iotx_mqtt_report_funcs +
    • >>   strlen +
    • >>   strstr +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memcpy4 +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   mqtt_basic_thread +
    + +

    IOT_MQTT_Destroy (Thumb, 66 bytes, Stack size 16 bytes, mqtt_api.o(i.IOT_MQTT_Destroy)) +

    [Stack]

    • Max Depth = 232 + Unknown Stack Size +
    • Call Chain = IOT_MQTT_Destroy ⇒ wrapper_mqtt_release ⇒ iotx_mc_disconnect ⇒ MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   wrapper_mqtt_release +
    • >>   LITE_syslog +
    +
    [Called By]
    • >>   mqtt_basic_thread +
    + +

    IOT_MQTT_Publish_Simple (Thumb, 154 bytes, Stack size 56 bytes, mqtt_api.o(i.IOT_MQTT_Publish_Simple)) +

    [Stack]

    • Max Depth = 336 + Unknown Stack Size +
    • Call Chain = IOT_MQTT_Publish_Simple ⇒ wrapper_mqtt_publish ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   wrapper_mqtt_publish +
    • >>   LITE_syslog +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   example_publish +
    +
    [Address Reference Count : 1]
    • mqtt_api.o(i.iotx_mqtt_report_funcs) +
    +

    IOT_MQTT_Subscribe (Thumb, 144 bytes, Stack size 48 bytes, mqtt_api.o(i.IOT_MQTT_Subscribe)) +

    [Stack]

    • Max Depth = 352 + Unknown Stack Size +
    • Call Chain = IOT_MQTT_Subscribe ⇒ wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   wrapper_mqtt_subscribe +
    • >>   LITE_syslog +
    • >>   iotx_mqtt_offline_subscribe +
    • >>   strlen +
    +
    [Called By]
    • >>   example_subscribe +
    + +

    IOT_MQTT_Yield (Thumb, 28 bytes, Stack size 16 bytes, mqtt_api.o(i.IOT_MQTT_Yield)) +

    [Stack]

    • Max Depth = 968 + Unknown Stack Size +
    • Call Chain = IOT_MQTT_Yield ⇒ wrapper_mqtt_yield ⇒ iotx_mc_keepalive ⇒ iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   wrapper_mqtt_yield +
    +
    [Called By]
    • >>   mqtt_basic_thread +
    + +

    IOT_Sign_MQTT (Thumb, 498 bytes, Stack size 96 bytes, dev_sign_mqtt.o(i.IOT_Sign_MQTT)) +

    [Stack]

    • Max Depth = 1056
    • Call Chain = IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   _sign_get_clientid +
    • >>   _iotx_generate_sign_string +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memclr +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    + +

    LITE_get_loglevel (Thumb, 6 bytes, Stack size 0 bytes, infra_log.o(i.LITE_get_loglevel)) +

    [Called By]

    • >>   LITE_syslog_routine +
    + +

    LITE_syslog (Thumb, 40 bytes, Stack size 32 bytes, infra_log.o(i.LITE_syslog)) +

    [Stack]

    • Max Depth = 128
    • Call Chain = LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog_routine +
    +
    [Called By]
    • >>   IOT_MQTT_Subscribe +
    • >>   IOT_MQTT_Publish_Simple +
    • >>   IOT_MQTT_Destroy +
    • >>   IOT_MQTT_Construct +
    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_set_connect_params +
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_push_pubInfo_to +
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_keepalive +
    • >>   iotx_mc_init +
    • >>   iotx_mc_handle_recv_SUBACK +
    • >>   iotx_mc_handle_recv_PUBLISH +
    • >>   iotx_mc_handle_recv_CONNACK +
    • >>   iotx_mc_handle_reconnect +
    • >>   iotx_mc_disconnect +
    • >>   iotx_mc_deliver_message +
    • >>   iotx_mc_cycle +
    • >>   iotx_mc_check_topic +
    • >>   iotx_mc_check_rule +
    • >>   iotx_mc_attempt_reconnect +
    • >>   _mqtt_connect +
    • >>   _iotx_mqtt_event_handle_sub +
    • >>   MQTTSubscribe +
    • >>   MQTTKeepalive +
    • >>   wrapper_mqtt_yield +
    • >>   wrapper_mqtt_subscribe +
    • >>   wrapper_mqtt_release +
    • >>   wrapper_mqtt_publish +
    • >>   wrapper_mqtt_init +
    • >>   wrapper_mqtt_connect +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    • >>   iotx_mqtt_report_funcs +
    • >>   utils_net_write +
    • >>   utils_net_read +
    • >>   iotx_net_disconnect +
    • >>   iotx_net_connect +
    • >>   disconnect_tcp +
    • >>   connect_tcp +
    • >>   iotx_net_init +
    • >>   _mqtt_cycle +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    LITE_syslog_routine (Thumb, 182 bytes, Stack size 40 bytes, infra_log.o(i.LITE_syslog_routine)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   HAL_Printf +
    • >>   HAL_Vsnprintf +
    • >>   LITE_get_loglevel +
    • >>   strlen +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   LITE_syslog +
    + +

    LPUART1_IRQHandler (Thumb, 18 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.LPUART1_IRQHandler)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = LPUART1_IRQHandler ⇒ HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT +
    +
    [Calls]
    • >>   tos_knl_irq_leave +
    • >>   tos_knl_irq_enter +
    • >>   HAL_UART_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    MQTTConnect (Thumb, 208 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.MQTTConnect)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = MQTTConnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   _reset_send_buffer +
    • >>   _get_connect_length +
    • >>   _alloc_send_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    • >>   MQTTSerialize_connect +
    +
    [Called By]
    • >>   _mqtt_connect +
    + +

    MQTTDeserialize_ack (Thumb, 108 bytes, Stack size 48 bytes, mqttdeserializepublish.o(i.MQTTDeserialize_ack)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   readInt +
    • >>   readChar +
    • >>   MQTTPacket_decodeBuf +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_PUBACK +
    • >>   MQTTDeserialize_unsuback +
    + +

    MQTTDeserialize_connack (Thumb, 118 bytes, Stack size 48 bytes, mqttconnectclient.o(i.MQTTDeserialize_connack)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MQTTDeserialize_connack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   readChar +
    • >>   MQTTPacket_decodeBuf +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_CONNACK +
    + +

    MQTTDeserialize_publish (Thumb, 174 bytes, Stack size 56 bytes, mqttdeserializepublish.o(i.MQTTDeserialize_publish)) +

    [Stack]

    • Max Depth = 104
    • Call Chain = MQTTDeserialize_publish ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   readMQTTLenString +
    • >>   readInt +
    • >>   readChar +
    • >>   MQTTPacket_decodeBuf +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_PUBLISH +
    + +

    MQTTDeserialize_suback (Thumb, 146 bytes, Stack size 48 bytes, mqttsubscribeclient.o(i.MQTTDeserialize_suback)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MQTTDeserialize_suback ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   readInt +
    • >>   readChar +
    • >>   MQTTPacket_decodeBuf +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_SUBACK +
    + +

    MQTTDeserialize_unsuback (Thumb, 46 bytes, Stack size 32 bytes, mqttunsubscribeclient.o(i.MQTTDeserialize_unsuback)) +

    [Stack]

    • Max Depth = 128
    • Call Chain = MQTTDeserialize_unsuback ⇒ MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   MQTTDeserialize_ack +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_UNSUBACK +
    + +

    MQTTPacket_decode (Thumb, 88 bytes, Stack size 32 bytes, mqttpacket.o(i.MQTTPacket_decode)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = MQTTPacket_decode +
    +
    [Called By]
    • >>   MQTTPacket_decodeBuf +
    + +

    MQTTPacket_decodeBuf (Thumb, 20 bytes, Stack size 16 bytes, mqttpacket.o(i.MQTTPacket_decodeBuf)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   MQTTPacket_decode +
    +
    [Called By]
    • >>   MQTTDeserialize_suback +
    • >>   MQTTDeserialize_publish +
    • >>   MQTTDeserialize_connack +
    • >>   MQTTDeserialize_ack +
    + +

    MQTTPacket_encode (Thumb, 54 bytes, Stack size 12 bytes, mqttpacket.o(i.MQTTPacket_encode)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = MQTTPacket_encode +
    +
    [Called By]
    • >>   iotx_mc_read_packet +
    • >>   MQTTSerialize_zero +
    • >>   MQTTSerialize_subscribe +
    • >>   MQTTSerialize_publish +
    • >>   MQTTSerialize_connect +
    • >>   MQTTSerialize_ack +
    + +

    MQTTPacket_equals (Thumb, 66 bytes, Stack size 24 bytes, mqttpacket.o(i.MQTTPacket_equals)) +

    [Stack]

    • Max Depth = 36
    • Call Chain = MQTTPacket_equals ⇒ memcmp +
    +
    [Calls]
    • >>   memcmp +
    • >>   strlen +
    +
    [Called By]
    • >>   iotx_mc_deliver_message +
    + +

    MQTTPacket_len (Thumb, 34 bytes, Stack size 0 bytes, mqttpacket.o(i.MQTTPacket_len)) +

    [Called By]

    • >>   MQTTSerialize_subscribe +
    • >>   MQTTSerialize_publish +
    • >>   MQTTSerialize_connect +
    + +

    MQTTPublish (Thumb, 398 bytes, Stack size 72 bytes, iotx_mqtt_client.o(i.MQTTPublish)) +

    [Stack]

    • Max Depth = 240 + Unknown Stack Size +
    • Call Chain = MQTTPublish ⇒ iotx_mc_push_pubInfo_to ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   iotx_mc_push_pubInfo_to +
    • >>   _reset_send_buffer +
    • >>   _alloc_send_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    • >>   MQTTSerialize_publish +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   wrapper_mqtt_publish +
    + +

    MQTTSerialize_ack (Thumb, 144 bytes, Stack size 40 bytes, mqttserializepublish.o(i.MQTTSerialize_ack)) +

    [Stack]

    • Max Depth = 52
    • Call Chain = MQTTSerialize_ack ⇒ MQTTPacket_encode +
    +
    [Calls]
    • >>   writeInt +
    • >>   writeChar +
    • >>   MQTTPacket_encode +
    +
    [Called By]
    • >>   MQTTPuback +
    + +

    MQTTSerialize_connect (Thumb, 370 bytes, Stack size 40 bytes, mqttconnectclient.o(i.MQTTSerialize_connect)) +

    [Stack]

    • Max Depth = 88
    • Call Chain = MQTTSerialize_connect ⇒ writeMQTTString ⇒ writeCString ⇒ writeInt +
    +
    [Calls]
    • >>   writeMQTTString +
    • >>   writeInt +
    • >>   writeChar +
    • >>   writeCString +
    • >>   MQTTPacket_len +
    • >>   MQTTSerialize_connectLength +
    • >>   MQTTPacket_encode +
    +
    [Called By]
    • >>   MQTTConnect +
    + +

    MQTTSerialize_connectLength (Thumb, 118 bytes, Stack size 16 bytes, mqttconnectclient.o(i.MQTTSerialize_connectLength)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = MQTTSerialize_connectLength ⇒ MQTTstrlen +
    +
    [Calls]
    • >>   MQTTstrlen +
    +
    [Called By]
    • >>   MQTTSerialize_connect +
    + +

    MQTTSerialize_disconnect (Thumb, 18 bytes, Stack size 16 bytes, mqttconnectclient.o(i.MQTTSerialize_disconnect)) +

    [Stack]

    • Max Depth = 60
    • Call Chain = MQTTSerialize_disconnect ⇒ MQTTSerialize_zero ⇒ MQTTPacket_encode +
    +
    [Calls]
    • >>   MQTTSerialize_zero +
    +
    [Called By]
    • >>   MQTTDisconnect +
    + +

    MQTTSerialize_pingreq (Thumb, 18 bytes, Stack size 16 bytes, mqttconnectclient.o(i.MQTTSerialize_pingreq)) +

    [Stack]

    • Max Depth = 60
    • Call Chain = MQTTSerialize_pingreq ⇒ MQTTSerialize_zero ⇒ MQTTPacket_encode +
    +
    [Calls]
    • >>   MQTTSerialize_zero +
    +
    [Called By]
    • >>   MQTTKeepalive +
    + +

    MQTTSerialize_publish (Thumb, 208 bytes, Stack size 64 bytes, mqttserializepublish.o(i.MQTTSerialize_publish)) +

    [Stack]

    • Max Depth = 120
    • Call Chain = MQTTSerialize_publish ⇒ MQTTSerialize_publishLength ⇒ MQTTstrlen +
    +
    [Calls]
    • >>   MQTTSerialize_publishLength +
    • >>   writeMQTTString +
    • >>   writeInt +
    • >>   writeChar +
    • >>   MQTTPacket_len +
    • >>   MQTTPacket_encode +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   MQTTPublish +
    + +

    MQTTSerialize_publishLength (Thumb, 34 bytes, Stack size 32 bytes, mqttserializepublish.o(i.MQTTSerialize_publishLength)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = MQTTSerialize_publishLength ⇒ MQTTstrlen +
    +
    [Calls]
    • >>   MQTTstrlen +
    +
    [Called By]
    • >>   MQTTSerialize_publish +
    + +

    MQTTSerialize_subscribe (Thumb, 192 bytes, Stack size 56 bytes, mqttsubscribeclient.o(i.MQTTSerialize_subscribe)) +

    [Stack]

    • Max Depth = 104
    • Call Chain = MQTTSerialize_subscribe ⇒ MQTTSerialize_subscribeLength ⇒ MQTTstrlen +
    +
    [Calls]
    • >>   MQTTSerialize_subscribeLength +
    • >>   writeMQTTString +
    • >>   writeInt +
    • >>   writeChar +
    • >>   MQTTPacket_len +
    • >>   MQTTPacket_encode +
    +
    [Called By]
    • >>   MQTTSubscribe +
    + +

    MQTTSerialize_subscribeLength (Thumb, 46 bytes, Stack size 24 bytes, mqttsubscribeclient.o(i.MQTTSerialize_subscribeLength)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = MQTTSerialize_subscribeLength ⇒ MQTTstrlen +
    +
    [Calls]
    • >>   MQTTstrlen +
    +
    [Called By]
    • >>   MQTTSerialize_subscribe +
    + +

    MQTTSerialize_zero (Thumb, 84 bytes, Stack size 32 bytes, mqttconnectclient.o(i.MQTTSerialize_zero)) +

    [Stack]

    • Max Depth = 44
    • Call Chain = MQTTSerialize_zero ⇒ MQTTPacket_encode +
    +
    [Calls]
    • >>   writeChar +
    • >>   MQTTPacket_encode +
    +
    [Called By]
    • >>   MQTTSerialize_pingreq +
    • >>   MQTTSerialize_disconnect +
    + +

    MQTTstrlen (Thumb, 24 bytes, Stack size 24 bytes, mqttpacket.o(i.MQTTstrlen)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = MQTTstrlen +
    +
    [Calls]
    • >>   strlen +
    +
    [Called By]
    • >>   MQTTSerialize_subscribeLength +
    • >>   MQTTSerialize_publishLength +
    • >>   MQTTSerialize_connectLength +
    + +

    MX_GPIO_Init (Thumb, 316 bytes, Stack size 32 bytes, gpio.o(i.MX_GPIO_Init)) +

    [Stack]

    • Max Depth = 80
    • Call Chain = MX_GPIO_Init ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_NVIC_SetPriority +
    • >>   HAL_NVIC_EnableIRQ +
    • >>   HAL_GPIO_WritePin +
    • >>   HAL_GPIO_Init +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   board_init +
    + +

    MX_LPUART1_UART_Init (Thumb, 64 bytes, Stack size 8 bytes, usart.o(i.MX_LPUART1_UART_Init)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MX_LPUART1_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_UART_Receive_IT +
    • >>   HAL_UART_Init +
    • >>   Error_Handler +
    +
    [Called By]
    • >>   tos_hal_uart_init +
    + +

    MX_USART1_UART_Init (Thumb, 56 bytes, Stack size 8 bytes, usart.o(i.MX_USART1_UART_Init)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MX_USART1_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_UART_Init +
    • >>   Error_Handler +
    +
    [Called By]
    • >>   tos_hal_uart_init +
    + +

    MX_USART2_UART_Init (Thumb, 56 bytes, Stack size 8 bytes, usart.o(i.MX_USART2_UART_Init)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MX_USART2_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_UART_Init +
    • >>   Error_Handler +
    +
    [Called By]
    • >>   board_init +
    • >>   tos_hal_uart_init +
    + +

    MX_USART3_UART_Init (Thumb, 56 bytes, Stack size 8 bytes, usart.o(i.MX_USART3_UART_Init)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = MX_USART3_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_UART_Init +
    • >>   Error_Handler +
    +
    [Called By]
    • >>   board_init +
    • >>   tos_hal_uart_init +
    + +

    MemManage_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.MemManage_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    NMI_Handler (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.NMI_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    OLED_Clear (Thumb, 62 bytes, Stack size 16 bytes, oled.o(i.OLED_Clear)) +

    [Stack]

    • Max Depth = 64
    • Call Chain = OLED_Clear ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   OLED_WR_Byte +
    +
    [Called By]
    • >>   OLED_Init +
    • >>   board_init +
    + +

    OLED_Init (Thumb, 198 bytes, Stack size 8 bytes, oled.o(i.OLED_Init)) +

    [Stack]

    • Max Depth = 72
    • Call Chain = OLED_Init ⇒ OLED_Clear ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   OLED_Clear +
    • >>   HAL_Delay +
    • >>   OLED_WR_Byte +
    +
    [Called By]
    • >>   board_init +
    + +

    OLED_Set_Pos (Thumb, 40 bytes, Stack size 16 bytes, oled.o(i.OLED_Set_Pos)) +

    [Stack]

    • Max Depth = 64
    • Call Chain = OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   OLED_WR_Byte +
    +
    [Called By]
    • >>   OLED_ShowChinese +
    • >>   OLED_ShowChar +
    + +

    OLED_ShowChar (Thumb, 154 bytes, Stack size 32 bytes, oled.o(i.OLED_ShowChar)) +

    [Stack]

    • Max Depth = 96
    • Call Chain = OLED_ShowChar ⇒ OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   OLED_WR_Byte +
    • >>   OLED_Set_Pos +
    +
    [Called By]
    • >>   OLED_ShowString +
    + +

    OLED_ShowChinese (Thumb, 98 bytes, Stack size 24 bytes, oled.o(i.OLED_ShowChinese)) +

    [Stack]

    • Max Depth = 88
    • Call Chain = OLED_ShowChinese ⇒ OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   OLED_WR_Byte +
    • >>   OLED_Set_Pos +
    +
    [Called By]
    • >>   board_init +
    + +

    OLED_ShowString (Thumb, 58 bytes, Stack size 24 bytes, oled.o(i.OLED_ShowString)) +

    [Stack]

    • Max Depth = 120
    • Call Chain = OLED_ShowString ⇒ OLED_ShowChar ⇒ OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   OLED_ShowChar +
    +
    [Called By]
    • >>   board_init +
    + +

    OLED_WR_Byte (Thumb, 24 bytes, Stack size 16 bytes, oled.o(i.OLED_WR_Byte)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   Write_IIC_Data +
    • >>   Write_IIC_Command +
    +
    [Called By]
    • >>   OLED_ShowChinese +
    • >>   OLED_Init +
    • >>   OLED_Clear +
    • >>   OLED_ShowChar +
    • >>   OLED_Set_Pos +
    + +

    SVC_Handler (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.SVC_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    SysTick_Handler (Thumb, 26 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.SysTick_Handler)) +

    [Stack]

    • Max Depth = 104 + Unknown Stack Size +
    • Call Chain = SysTick_Handler ⇒ tos_tick_handler ⇒ tick_update ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_tick_handler +
    • >>   tos_knl_is_running +
    • >>   tos_knl_irq_leave +
    • >>   tos_knl_irq_enter +
    • >>   HAL_IncTick +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    SystemClock_Config (Thumb, 214 bytes, Stack size 184 bytes, mcu_init.o(i.SystemClock_Config)) +

    [Stack]

    • Max Depth = 280
    • Call Chain = SystemClock_Config ⇒ HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   HAL_RCC_OscConfig +
    • >>   HAL_RCC_ClockConfig +
    • >>   HAL_RCCEx_PeriphCLKConfig +
    • >>   HAL_RCCEx_EnableMSIPLLMode +
    • >>   HAL_PWR_EnableBkUpAccess +
    • >>   HAL_PWREx_ControlVoltageScaling +
    • >>   Error_Handler +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   board_init +
    + +

    SystemInit (Thumb, 68 bytes, Stack size 0 bytes, system_stm32l4xx.o(i.SystemInit)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(.text) +
    +

    UART_AdvFeatureConfig (Thumb, 248 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.UART_AdvFeatureConfig)) +

    [Called By]

    • >>   HAL_UART_Init +
    + +

    UART_CheckIdleState (Thumb, 116 bytes, Stack size 16 bytes, stm32l4xx_hal_uart.o(i.UART_CheckIdleState)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = UART_CheckIdleState ⇒ UART_WaitOnFlagUntilTimeout +
    +
    [Calls]
    • >>   HAL_GetTick +
    • >>   UART_WaitOnFlagUntilTimeout +
    +
    [Called By]
    • >>   HAL_UART_Init +
    + +

    UART_SetConfig (Thumb, 1000 bytes, Stack size 40 bytes, stm32l4xx_hal_uart.o(i.UART_SetConfig)) +

    [Stack]

    • Max Depth = 80
    • Call Chain = UART_SetConfig ⇒ __aeabi_uldivmod +
    +
    [Calls]
    • >>   HAL_RCC_GetSysClockFreq +
    • >>   HAL_RCC_GetPCLK2Freq +
    • >>   HAL_RCC_GetPCLK1Freq +
    • >>   __aeabi_uldivmod +
    +
    [Called By]
    • >>   HAL_UART_Init +
    + +

    UART_WaitOnFlagUntilTimeout (Thumb, 108 bytes, Stack size 24 bytes, stm32l4xx_hal_uart.o(i.UART_WaitOnFlagUntilTimeout)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = UART_WaitOnFlagUntilTimeout +
    +
    [Calls]
    • >>   HAL_GetTick +
    +
    [Called By]
    • >>   HAL_UART_Transmit +
    • >>   UART_CheckIdleState +
    + +

    USART2_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.USART2_IRQHandler)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = USART2_IRQHandler ⇒ HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT +
    +
    [Calls]
    • >>   HAL_UART_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    USART3_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.USART3_IRQHandler)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = USART3_IRQHandler ⇒ HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT +
    +
    [Calls]
    • >>   HAL_UART_IRQHandler +
    +
    [Address Reference Count : 1]
    • startup_stm32l431xx.o(RESET) +
    +

    UsageFault_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.UsageFault_Handler)) +
    [Address Reference Count : 1]

    • startup_stm32l431xx.o(RESET) +
    +

    Write_IIC_Byte (Thumb, 96 bytes, Stack size 24 bytes, oled.o(i.Write_IIC_Byte)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = Write_IIC_Byte +
    +
    [Calls]
    • >>   HAL_GPIO_WritePin +
    +
    [Called By]
    • >>   Write_IIC_Data +
    • >>   Write_IIC_Command +
    + +

    Write_IIC_Command (Thumb, 44 bytes, Stack size 8 bytes, oled.o(i.Write_IIC_Command)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = Write_IIC_Command ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   Write_IIC_Byte +
    • >>   IIC_Wait_Ack +
    • >>   IIC_Stop +
    • >>   IIC_Start +
    +
    [Called By]
    • >>   OLED_WR_Byte +
    + +

    Write_IIC_Data (Thumb, 44 bytes, Stack size 8 bytes, oled.o(i.Write_IIC_Data)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = Write_IIC_Data ⇒ Write_IIC_Byte +
    +
    [Calls]
    • >>   Write_IIC_Byte +
    • >>   IIC_Wait_Ack +
    • >>   IIC_Stop +
    • >>   IIC_Start +
    +
    [Called By]
    • >>   OLED_WR_Byte +
    + +

    __0printf (Thumb, 22 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED) +

    [Calls]

    • >>   _printf_core +
    + +

    __1printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED) + +

    __2printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = __2printf +
    +
    [Called By]
    • >>   main +
    • >>   application_entry +
    • >>   at_parser +
    • >>   at_cmd_do_exec +
    • >>   esp8266_reconnect_init +
    • >>   esp8266_parse_domain +
    • >>   esp8266_init +
    • >>   HAL_TCP_Establish +
    + +

    __c89printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED) + +

    printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED) + +

    __0snprintf (Thumb, 44 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED) +

    [Calls]

    • >>   _printf_core +
    + +

    __1snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED) + +

    __2snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = __2snprintf +
    +
    [Called By]
    • >>   HAL_TCP_Establish +
    + +

    __c89snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED) + +

    snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED) + +

    __0vprintf (Thumb, 8 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED) +

    [Calls]

    • >>   _printf_core +
    + +

    __1vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED) + +

    __2vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED) + +

    __c89vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED) + +

    vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf)) +

    [Called By]

    • >>   HAL_Printf +
    + +

    __0vsnprintf (Thumb, 40 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED) +

    [Calls]

    • >>   _printf_core +
    + +

    __1vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED) + +

    __2vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED) + +

    __c89vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED) + +

    vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = vsnprintf +
    +
    [Called By]
    • >>   HAL_Snprintf +
    • >>   at_cmd_do_exec +
    • >>   HAL_Vsnprintf +
    + +

    __scatterload_copy (Thumb, 14 bytes, Stack size unknown bytes, handlers.o(i.__scatterload_copy), UNUSED) + +

    __scatterload_null (Thumb, 2 bytes, Stack size unknown bytes, handlers.o(i.__scatterload_null), UNUSED) + +

    __scatterload_zeroinit (Thumb, 14 bytes, Stack size unknown bytes, handlers.o(i.__scatterload_zeroinit), UNUSED) + +

    _iotx_generate_sign_string (Thumb, 340 bytes, Stack size 320 bytes, dev_sign_mqtt.o(i._iotx_generate_sign_string)) +

    [Stack]

    • Max Depth = 960
    • Call Chain = _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   utils_hmac_sha256 +
    • >>   _hex2str +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memcpy4 +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   IOT_Sign_MQTT +
    + +

    _mqtt_cycle (Thumb, 122 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i._mqtt_cycle)) +

    [Stack]

    • Max Depth = 784 + Unknown Stack Size +
    • Call Chain = _mqtt_cycle ⇒ iotx_mc_cycle ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_cycle +
    • >>   MQTTPubInfoProc +
    • >>   LITE_syslog +
    • >>   HAL_SleepMs +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_is_expired +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_left +
    • >>   iotx_time_init +
    +
    [Called By]
    • >>   wrapper_mqtt_yield +
    + +

    _sign_get_clientid (Thumb, 330 bytes, Stack size 32 bytes, dev_sign_mqtt.o(i._sign_get_clientid)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = _sign_get_clientid ⇒ __aeabi_memcpy +
    +
    [Calls]
    • >>   strlen +
    • >>   __aeabi_memclr +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   IOT_Sign_MQTT +
    + +

    application_entry (Thumb, 38 bytes, Stack size 0 bytes, aliyun_iotkit_csdk_mqtt.o(i.application_entry)) +

    [Stack]

    • Max Depth = 1496 + Unknown Stack Size +
    • Call Chain = application_entry ⇒ mqtt_basic_thread ⇒ IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   tos_task_delay +
    • >>   esp8266_sal_init +
    • >>   esp8266_join_ap +
    • >>   mqtt_basic_thread +
    • >>   __2printf +
    +
    [Address Reference Count : 1]
    • main.o(.constdata) +
    +

    at_delay (Thumb, 38 bytes, Stack size 24 bytes, tos_at_utils.o(i.at_delay)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = at_delay ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_systick_get +
    +
    [Called By]
    • >>   at_uart_getchar +
    + +

    at_timer_countdown (Thumb, 30 bytes, Stack size 16 bytes, tos_at_utils.o(i.at_timer_countdown)) +

    [Stack]

    • Max Depth = 40 + Unknown Stack Size +
    • Call Chain = at_timer_countdown ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_systick_get +
    +
    [Called By]
    • >>   tos_at_channel_read_timed +
    + +

    at_timer_init (Thumb, 14 bytes, Stack size 0 bytes, tos_at_utils.o(i.at_timer_init)) +

    [Called By]

    • >>   tos_at_init +
    + +

    at_timer_is_expired (Thumb, 40 bytes, Stack size 16 bytes, tos_at_utils.o(i.at_timer_is_expired)) +

    [Stack]

    • Max Depth = 40 + Unknown Stack Size +
    • Call Chain = at_timer_is_expired ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_systick_get +
    +
    [Called By]
    • >>   at_timer_remain +
    • >>   tos_at_channel_read_timed +
    + +

    at_timer_remain (Thumb, 40 bytes, Stack size 16 bytes, tos_at_utils.o(i.at_timer_remain)) +

    [Stack]

    • Max Depth = 56 + Unknown Stack Size +
    • Call Chain = at_timer_remain ⇒ at_timer_is_expired ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_systick_get +
    • >>   at_timer_is_expired +
    +
    [Called By]
    • >>   tos_at_channel_read_timed +
    + +

    board_init (Thumb, 110 bytes, Stack size 8 bytes, mcu_init.o(i.board_init)) +

    [Stack]

    • Max Depth = 288
    • Call Chain = board_init ⇒ SystemClock_Config ⇒ HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   OLED_ShowString +
    • >>   OLED_ShowChinese +
    • >>   OLED_Init +
    • >>   OLED_Clear +
    • >>   MX_USART3_UART_Init +
    • >>   MX_USART2_UART_Init +
    • >>   HAL_Init +
    • >>   DHT11_Init +
    • >>   SystemClock_Config +
    • >>   MX_GPIO_Init +
    +
    [Called By]
    • >>   main +
    + +

    bufchar (Thumb, 36 bytes, Stack size 8 bytes, mqttpacket.o(i.bufchar)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = bufchar +
    +
    [Address Reference Count : 1]
    • mqttpacket.o(i.MQTTPacket_decodeBuf) +
    +

    cpu_context_switch (Thumb, 8 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_context_switch)) +

    [Stack]

    • Max Depth = 8 + Unknown Stack Size +
    • Call Chain = cpu_context_switch +
    +
    [Calls]
    • >>   port_context_switch +
    +
    [Called By]
    • >>   knl_sched +
    + +

    cpu_init (Thumb, 30 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_init)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = cpu_init ⇒ __aeabi_uldivmod +
    +
    [Calls]
    • >>   cpu_systick_init +
    • >>   __aeabi_uldivmod +
    +
    [Called By]
    • >>   tos_knl_init +
    + +

    cpu_irq_context_switch (Thumb, 8 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_irq_context_switch)) +

    [Stack]

    • Max Depth = 8 + Unknown Stack Size +
    • Call Chain = cpu_irq_context_switch +
    +
    [Calls]
    • >>   port_irq_context_switch +
    +
    [Called By]
    • >>   tos_knl_irq_leave +
    + +

    cpu_sched_start (Thumb, 4 bytes, Stack size 0 bytes, tos_cpu.o(i.cpu_sched_start)) +

    [Calls]

    • >>   port_sched_start +
    +
    [Called By]
    • >>   tos_knl_start +
    + +

    cpu_systick_init (Thumb, 18 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_systick_init)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = cpu_systick_init ⇒ port_systick_config ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   port_systick_priority_set +
    • >>   port_systick_config +
    +
    [Called By]
    • >>   cpu_init +
    + +

    cpu_task_stk_init (Thumb, 216 bytes, Stack size 20 bytes, tos_cpu.o(i.cpu_task_stk_init)) +

    [Stack]

    • Max Depth = 20
    • Call Chain = cpu_task_stk_init +
    +
    [Called By]
    • >>   tos_task_create +
    + +

    esp8266_join_ap (Thumb, 68 bytes, Stack size 64 bytes, esp8266.o(i.esp8266_join_ap)) +

    [Stack]

    • Max Depth = 296 + Unknown Stack Size +
    • Call Chain = esp8266_join_ap ⇒ tos_at_cmd_exec_until ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_echo_create +
    +
    [Called By]
    • >>   application_entry +
    + +

    esp8266_sal_init (Thumb, 52 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_sal_init)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = esp8266_sal_init ⇒ tos_at_init ⇒ at_recv_cache_init ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   tos_sal_module_register +
    • >>   tos_sal_module_init +
    • >>   tos_at_init +
    +
    [Called By]
    • >>   application_entry +
    + +

    example_event_handle (Thumb, 40 bytes, Stack size 16 bytes, mqtt_example.o(i.example_event_handle)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = example_event_handle ⇒ HAL_Printf +
    +
    [Calls]
    • >>   HAL_Printf +
    +
    [Address Reference Count : 1]
    • mqtt_example.o(i.mqtt_basic_thread) +
    +

    example_message_arrive (Thumb, 148 bytes, Stack size 24 bytes, mqtt_example.o(i.example_message_arrive)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = example_message_arrive ⇒ HAL_Printf +
    +
    [Calls]
    • >>   HAL_Printf +
    +
    [Address Reference Count : 1]
    • mqtt_example.o(i.example_subscribe) +
    +

    example_publish (Thumb, 192 bytes, Stack size 40 bytes, mqtt_example.o(i.example_publish)) +

    [Stack]

    • Max Depth = 376 + Unknown Stack Size +
    • Call Chain = example_publish ⇒ IOT_MQTT_Publish_Simple ⇒ wrapper_mqtt_publish ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   IOT_MQTT_Publish_Simple +
    • >>   HAL_Snprintf +
    • >>   HAL_Printf +
    • >>   HAL_Malloc +
    • >>   HAL_Free +
    • >>   strlen +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   mqtt_basic_thread +
    + +

    example_subscribe (Thumb, 186 bytes, Stack size 32 bytes, mqtt_example.o(i.example_subscribe)) +

    [Stack]

    • Max Depth = 384 + Unknown Stack Size +
    • Call Chain = example_subscribe ⇒ IOT_MQTT_Subscribe ⇒ wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   IOT_MQTT_Subscribe +
    • >>   HAL_Snprintf +
    • >>   HAL_Printf +
    • >>   HAL_Malloc +
    • >>   HAL_Free +
    • >>   strlen +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   mqtt_basic_thread +
    + +

    fputc (Thumb, 42 bytes, Stack size 16 bytes, mcu_init.o(i.fputc)) +

    [Stack]

    • Max Depth = 72
    • Call Chain = fputc ⇒ HAL_UART_Transmit ⇒ UART_WaitOnFlagUntilTimeout +
    +
    [Calls]
    • >>   HAL_UART_Transmit +
    +
    [Address Reference Count : 2]
    • printfa.o(i.__0printf) +
    • printfa.o(i.__0vprintf) +
    +

    infra_strtok (Thumb, 258 bytes, Stack size 24 bytes, infra_string.o(i.infra_strtok)) +

    [Stack]

    • Max Depth = 36
    • Call Chain = infra_strtok ⇒ memcmp +
    +
    [Calls]
    • >>   memcmp +
    • >>   strlen +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   iotx_mc_check_topic +
    + +

    iotx_event_callback (Thumb, 24 bytes, Stack size 0 bytes, infra_compat.o(i.iotx_event_callback)) +

    [Called By]

    • >>   IOT_MQTT_Construct +
    + +

    iotx_net_connect (Thumb, 46 bytes, Stack size 16 bytes, infra_net.o(i.iotx_net_connect)) +

    [Stack]

    • Max Depth = 160
    • Call Chain = iotx_net_connect ⇒ connect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   connect_tcp +
    +
    [Address Reference Count : 1]
    • infra_net.o(i.iotx_net_init) +
    +

    iotx_net_disconnect (Thumb, 46 bytes, Stack size 16 bytes, infra_net.o(i.iotx_net_disconnect)) +

    [Stack]

    • Max Depth = 160
    • Call Chain = iotx_net_disconnect ⇒ disconnect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   disconnect_tcp +
    +
    [Address Reference Count : 1]
    • infra_net.o(i.iotx_net_init) +
    +

    iotx_net_init (Thumb, 86 bytes, Stack size 32 bytes, infra_net.o(i.iotx_net_init)) +

    [Stack]

    • Max Depth = 160
    • Call Chain = iotx_net_init ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   strlen +
    +
    [Called By]
    • >>   iotx_mc_init +
    + +

    iotx_report_devinfo (Thumb, 376 bytes, Stack size 232 bytes, infra_report.o(i.iotx_report_devinfo)) +

    [Stack]

    • Max Depth = 368 + Unknown Stack Size +
    • Call Chain = iotx_report_devinfo ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   HAL_Snprintf +
    • >>   HAL_Malloc +
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceName +
    • >>   HAL_Free +
    • >>   LITE_syslog +
    • >>   iotx_report_id +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   iotx_mqtt_report_funcs +
    + +

    iotx_report_firmware_version (Thumb, 346 bytes, Stack size 328 bytes, infra_report.o(i.iotx_report_firmware_version)) +

    [Stack]

    • Max Depth = 456
    • Call Chain = iotx_report_firmware_version ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   HAL_Snprintf +
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceName +
    • >>   LITE_syslog +
    • >>   HAL_GetFirmwareVersion +
    • >>   iotx_report_id +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   iotx_mqtt_report_funcs +
    + +

    iotx_report_id (Thumb, 16 bytes, Stack size 0 bytes, infra_report.o(i.iotx_report_id)) +

    [Called By]

    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    + +

    iotx_report_mid (Thumb, 6 bytes, Stack size 0 bytes, infra_report.o(i.iotx_report_mid)) +

    [Called By]

    • >>   iotx_mqtt_report_funcs +
    + +

    iotx_set_report_func (Thumb, 6 bytes, Stack size 0 bytes, infra_report.o(i.iotx_set_report_func)) +

    [Called By]

    • >>   iotx_mqtt_report_funcs +
    + +

    iotx_time_init (Thumb, 12 bytes, Stack size 0 bytes, infra_timer.o(i.iotx_time_init)) +

    [Called By]

    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_init +
    • >>   MQTTSubscribe +
    • >>   MQTTRePublish +
    • >>   MQTTPuback +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   _mqtt_cycle +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    iotx_time_left (Thumb, 36 bytes, Stack size 16 bytes, infra_timer.o(i.iotx_time_left)) +

    [Stack]

    • Max Depth = 64 + Unknown Stack Size +
    • Call Chain = iotx_time_left ⇒ utils_time_is_expired ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_UptimeMs +
    • >>   utils_time_is_expired +
    +
    [Called By]
    • >>   iotx_mc_send_packet +
    • >>   iotx_mc_read_packet +
    • >>   _mqtt_cycle +
    + +

    iotx_time_start (Thumb, 18 bytes, Stack size 8 bytes, infra_timer.o(i.iotx_time_start)) +

    [Stack]

    • Max Depth = 40 + Unknown Stack Size +
    • Call Chain = iotx_time_start ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_UptimeMs +
    +
    [Called By]
    • >>   iotx_mc_push_pubInfo_to +
    • >>   MQTTPubInfoProc +
    + +

    knl_idle_init (Thumb, 38 bytes, Stack size 24 bytes, tos_sys.o(i.knl_idle_init)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = knl_idle_init ⇒ tos_task_create ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_task_create +
    +
    [Called By]
    • >>   tos_knl_init +
    + +

    knl_is_idle (Thumb, 16 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_idle)) +

    [Called By]

    • >>   task_do_destroy +
    • >>   tos_task_create +
    + +

    knl_is_inirq (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_inirq)) +

    [Called By]

    • >>   tos_task_delay +
    • >>   tos_knl_irq_leave +
    • >>   tos_task_prio_change +
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   tos_mutex_destroy +
    • >>   tos_mutex_create +
    • >>   knl_sched +
    • >>   tos_sem_pend +
    • >>   tos_knl_sched_lock +
    • >>   tos_task_yield +
    • >>   tos_task_destroy +
    • >>   tos_task_create +
    • >>   tos_knl_sched_unlock +
    + +

    knl_is_sched_locked (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_sched_locked)) +

    [Called By]

    • >>   tos_task_delay +
    • >>   tos_knl_irq_leave +
    • >>   tos_mutex_pend_timed +
    • >>   knl_sched +
    • >>   tos_sem_pend +
    • >>   tos_task_destroy +
    • >>   tos_knl_sched_unlock +
    + +

    knl_is_self (Thumb, 18 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_self)) +

    [Called By]

    • >>   tos_knl_irq_leave +
    • >>   tos_task_prio_change +
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   knl_sched +
    • >>   tos_task_destroy +
    + +

    knl_object_alloc_is_static (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_alloc_is_static)) +

    [Called By]

    • >>   tos_ring_q_destroy +
    • >>   tos_chr_fifo_destroy +
    • >>   tos_task_destroy +
    + +

    knl_object_alloc_reset (Thumb, 6 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_alloc_reset)) +

    [Called By]

    • >>   tos_ring_q_destroy +
    • >>   tos_chr_fifo_destroy +
    • >>   task_reset +
    + +

    knl_object_alloc_set_static (Thumb, 6 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_alloc_set_static)) +

    [Called By]

    • >>   tos_ring_q_create +
    • >>   tos_chr_fifo_create +
    • >>   tos_task_create +
    + +

    knl_object_deinit (Thumb, 6 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_deinit)) +

    [Called By]

    • >>   tos_mutex_destroy +
    • >>   tos_ring_q_destroy +
    • >>   tos_chr_fifo_destroy +
    • >>   tos_sem_destroy +
    • >>   task_reset +
    + +

    knl_object_init (Thumb, 4 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_init)) +

    [Called By]

    • >>   tos_mutex_create +
    • >>   tos_ring_q_create +
    • >>   tos_chr_fifo_create +
    • >>   tos_sem_create_max +
    • >>   tos_task_create +
    + +

    knl_object_verify (Thumb, 16 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_verify)) +

    [Called By]

    • >>   tos_task_prio_change +
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   tos_mutex_destroy +
    • >>   tos_ring_q_is_full +
    • >>   tos_ring_q_is_empty +
    • >>   tos_ring_q_enqueue +
    • >>   tos_ring_q_destroy +
    • >>   tos_ring_q_dequeue +
    • >>   tos_chr_fifo_push_stream +
    • >>   tos_chr_fifo_push +
    • >>   tos_chr_fifo_pop_stream +
    • >>   tos_chr_fifo_pop +
    • >>   tos_chr_fifo_destroy +
    • >>   tos_sem_pend +
    • >>   tos_sem_destroy +
    • >>   sem_do_post +
    • >>   tos_task_destroy +
    + +

    knl_sched (Thumb, 78 bytes, Stack size 8 bytes, tos_sys.o(i.knl_sched)) +

    [Stack]

    • Max Depth = 16 + Unknown Stack Size +
    • Call Chain = knl_sched ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_is_self +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    • >>   readyqueue_highest_ready_task_get +
    • >>   cpu_context_switch +
    +
    [Called By]
    • >>   tos_task_delay +
    • >>   tos_task_prio_change +
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   tos_mutex_destroy +
    • >>   tos_sem_pend +
    • >>   tos_sem_destroy +
    • >>   sem_do_post +
    • >>   tos_task_yield +
    • >>   task_do_destroy +
    • >>   tos_task_create +
    • >>   tos_knl_sched_unlock +
    + +

    main (Thumb, 32 bytes, Stack size 8 bytes, main.o(i.main)) +

    [Stack]

    • Max Depth = 296 + Unknown Stack Size +
    • Call Chain = main ⇒ board_init ⇒ SystemClock_Config ⇒ HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   osThreadCreate +
    • >>   osKernelStart +
    • >>   osKernelInitialize +
    • >>   board_init +
    • >>   __2printf +
    +
    [Address Reference Count : 1]
    • entry9a.o(.ARM.Collect$$$$0000000B) +
    +

    mmheap_init_with_pool (Thumb, 20 bytes, Stack size 16 bytes, tos_mmheap.o(i.mmheap_init_with_pool)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = mmheap_init_with_pool ⇒ tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_mmheap_pool_add +
    • >>   mmheap_ctl_init +
    +
    [Called By]
    • >>   tos_knl_init +
    + +

    mqtt_basic_thread (Thumb, 176 bytes, Stack size 80 bytes, mqtt_example.o(i.mqtt_basic_thread)) +

    [Stack]

    • Max Depth = 1496 + Unknown Stack Size +
    • Call Chain = mqtt_basic_thread ⇒ IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   IOT_MQTT_Yield +
    • >>   IOT_MQTT_Destroy +
    • >>   IOT_MQTT_Construct +
    • >>   HAL_Printf +
    • >>   HAL_GetProductKey +
    • >>   HAL_GetDeviceSecret +
    • >>   HAL_GetDeviceName +
    • >>   example_subscribe +
    • >>   example_publish +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   application_entry +
    + +

    mutex_release (Thumb, 20 bytes, Stack size 8 bytes, tos_mutex.o(i.mutex_release)) +

    [Stack]

    • Max Depth = 88 + Unknown Stack Size +
    • Call Chain = mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   mutex_old_owner_release +
    • >>   pend_wakeup_all +
    +
    [Called By]
    • >>   task_mutex_release +
    + +

    osKernelInitialize (Thumb, 14 bytes, Stack size 8 bytes, cmsis_os.o(i.osKernelInitialize)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = osKernelInitialize ⇒ tos_knl_init ⇒ mmheap_init_with_pool ⇒ tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   errno_knl2cmsis +
    • >>   tos_knl_init +
    +
    [Called By]
    • >>   main +
    + +

    osKernelStart (Thumb, 14 bytes, Stack size 8 bytes, cmsis_os.o(i.osKernelStart)) +

    [Stack]

    • Max Depth = 16 + Unknown Stack Size +
    • Call Chain = osKernelStart ⇒ tos_knl_start +
    +
    [Calls]
    • >>   errno_knl2cmsis +
    • >>   tos_knl_start +
    +
    [Called By]
    • >>   main +
    + +

    osThreadCreate (Thumb, 66 bytes, Stack size 40 bytes, cmsis_os.o(i.osThreadCreate)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = osThreadCreate ⇒ tos_task_create ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   priority_cmsis2knl +
    • >>   tos_task_create +
    +
    [Called By]
    • >>   main +
    + +

    pend_highest_pending_prio_get (Thumb, 32 bytes, Stack size 16 bytes, tos_pend.o(i.pend_highest_pending_prio_get)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = pend_highest_pending_prio_get +
    +
    [Calls]
    • >>   tos_list_empty +
    +
    [Called By]
    • >>   tos_mutex_post +
    • >>   task_highest_pending_prio_get +
    + +

    pend_highest_pending_task_get (Thumb, 8 bytes, Stack size 0 bytes, tos_pend.o(i.pend_highest_pending_task_get)) +

    [Called By]

    • >>   tos_mutex_post +
    + +

    pend_is_nopending (Thumb, 12 bytes, Stack size 8 bytes, tos_pend.o(i.pend_is_nopending)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = pend_is_nopending +
    +
    [Calls]
    • >>   tos_list_empty +
    +
    [Called By]
    • >>   tos_mutex_post +
    • >>   tos_mutex_destroy +
    • >>   tos_sem_destroy +
    • >>   sem_do_post +
    + +

    pend_list_adjust (Thumb, 22 bytes, Stack size 8 bytes, tos_pend.o(i.pend_list_adjust)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = pend_list_adjust ⇒ pend_list_add +
    +
    [Calls]
    • >>   tos_list_del +
    • >>   pend_list_add +
    +
    [Called By]
    • >>   tos_task_prio_change +
    + +

    pend_list_remove (Thumb, 30 bytes, Stack size 8 bytes, tos_pend.o(i.pend_list_remove)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = pend_list_remove +
    +
    [Calls]
    • >>   tos_list_del +
    +
    [Called By]
    • >>   pend_task_wakeup +
    • >>   task_do_destroy +
    + +

    pend_object_deinit (Thumb, 12 bytes, Stack size 8 bytes, tos_pend.o(i.pend_object_deinit)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = pend_object_deinit +
    +
    [Calls]
    • >>   tos_list_init +
    +
    [Called By]
    • >>   tos_mutex_destroy +
    • >>   tos_sem_destroy +
    + +

    pend_object_init (Thumb, 12 bytes, Stack size 8 bytes, tos_pend.o(i.pend_object_init)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = pend_object_init +
    +
    [Calls]
    • >>   tos_list_init +
    +
    [Called By]
    • >>   tos_mutex_create +
    • >>   tos_sem_create_max +
    + +

    pend_state2errno (Thumb, 46 bytes, Stack size 0 bytes, tos_pend.o(i.pend_state2errno)) +

    [Called By]

    • >>   tos_mutex_pend_timed +
    • >>   tos_sem_pend +
    + +

    pend_task_block (Thumb, 60 bytes, Stack size 24 bytes, tos_pend.o(i.pend_task_block)) +

    [Stack]

    • Max Depth = 104 + Unknown Stack Size +
    • Call Chain = pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   pend_list_add +
    • >>   tick_list_add +
    • >>   readyqueue_remove +
    +
    [Called By]
    • >>   tos_mutex_pend_timed +
    • >>   tos_sem_pend +
    + +

    pend_task_wakeup (Thumb, 64 bytes, Stack size 16 bytes, tos_pend.o(i.pend_task_wakeup)) +

    [Stack]

    • Max Depth = 56 + Unknown Stack Size +
    • Call Chain = pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tick_list_remove +
    • >>   readyqueue_add +
    • >>   pend_list_remove +
    +
    [Called By]
    • >>   pend_wakeup_one +
    • >>   pend_wakeup_all +
    • >>   tick_update +
    + +

    pend_wakeup (Thumb, 30 bytes, Stack size 16 bytes, tos_pend.o(i.pend_wakeup)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   pend_wakeup_one +
    • >>   pend_wakeup_all +
    +
    [Called By]
    • >>   sem_do_post +
    + +

    pend_wakeup_all (Thumb, 36 bytes, Stack size 24 bytes, tos_pend.o(i.pend_wakeup_all)) +

    [Stack]

    • Max Depth = 80 + Unknown Stack Size +
    • Call Chain = pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   pend_task_wakeup +
    +
    [Called By]
    • >>   tos_mutex_destroy +
    • >>   mutex_release +
    • >>   tos_sem_destroy +
    • >>   pend_wakeup +
    + +

    pend_wakeup_one (Thumb, 20 bytes, Stack size 16 bytes, tos_pend.o(i.pend_wakeup_one)) +

    [Stack]

    • Max Depth = 72 + Unknown Stack Size +
    • Call Chain = pend_wakeup_one ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   pend_task_wakeup +
    +
    [Called By]
    • >>   tos_mutex_post +
    • >>   pend_wakeup +
    + +

    port_systick_config (Thumb, 50 bytes, Stack size 16 bytes, port_c.o(i.port_systick_config)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = port_systick_config ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   __NVIC_SetPriority +
    +
    [Called By]
    • >>   cpu_systick_init +
    + +

    port_systick_priority_set (Thumb, 16 bytes, Stack size 8 bytes, port_c.o(i.port_systick_priority_set)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = port_systick_priority_set ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   __NVIC_SetPriority +
    +
    [Called By]
    • >>   cpu_systick_init +
    + +

    readChar (Thumb, 14 bytes, Stack size 0 bytes, mqttpacket.o(i.readChar)) +

    [Called By]

    • >>   MQTTDeserialize_suback +
    • >>   MQTTDeserialize_publish +
    • >>   MQTTDeserialize_connack +
    • >>   MQTTDeserialize_ack +
    + +

    readInt (Thumb, 26 bytes, Stack size 12 bytes, mqttpacket.o(i.readInt)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = readInt +
    +
    [Called By]
    • >>   readMQTTLenString +
    • >>   MQTTDeserialize_suback +
    • >>   MQTTDeserialize_publish +
    • >>   MQTTDeserialize_ack +
    + +

    readMQTTLenString (Thumb, 58 bytes, Stack size 20 bytes, mqttpacket.o(i.readMQTTLenString)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = readMQTTLenString ⇒ readInt +
    +
    [Calls]
    • >>   readInt +
    +
    [Called By]
    • >>   MQTTDeserialize_publish +
    + +

    readyqueue_add (Thumb, 32 bytes, Stack size 8 bytes, tos_sched.o(i.readyqueue_add)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   readyqueue_add_tail +
    • >>   readyqueue_add_head +
    +
    [Called By]
    • >>   pend_task_wakeup +
    + +

    readyqueue_add_head (Thumb, 48 bytes, Stack size 24 bytes, tos_sched.o(i.readyqueue_add_head)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = readyqueue_add_head +
    +
    [Calls]
    • >>   tos_list_empty +
    • >>   readyqueue_prio_mark +
    • >>   _list_add +
    +
    [Called By]
    • >>   tos_task_prio_change +
    • >>   readyqueue_add +
    + +

    readyqueue_add_tail (Thumb, 38 bytes, Stack size 16 bytes, tos_sched.o(i.readyqueue_add_tail)) +

    [Stack]

    • Max Depth = 32
    • Call Chain = readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_list_empty +
    • >>   tos_list_add_tail +
    • >>   readyqueue_prio_mark +
    +
    [Called By]
    • >>   tos_task_prio_change +
    • >>   readyqueue_add +
    • >>   tos_task_yield +
    • >>   tos_task_create +
    + +

    readyqueue_highest_ready_task_get (Thumb, 18 bytes, Stack size 0 bytes, tos_sched.o(i.readyqueue_highest_ready_task_get)) +

    [Called By]

    • >>   tos_knl_irq_leave +
    • >>   knl_sched +
    • >>   tos_knl_start +
    + +

    readyqueue_init (Thumb, 60 bytes, Stack size 0 bytes, tos_sched.o(i.readyqueue_init)) +

    [Called By]

    • >>   tos_knl_init +
    + +

    readyqueue_remove (Thumb, 94 bytes, Stack size 16 bytes, tos_sched.o(i.readyqueue_remove)) +

    [Stack]

    • Max Depth = 40 + Unknown Stack Size +
    • Call Chain = readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_list_empty +
    • >>   readyqueue_prio_highest_get +
    • >>   _list_del +
    +
    [Called By]
    • >>   tos_task_delay +
    • >>   tos_task_prio_change +
    • >>   pend_task_block +
    • >>   tos_task_yield +
    • >>   task_do_destroy +
    + +

    task_free_all (Thumb, 66 bytes, Stack size 24 bytes, tos_task.o(i.task_free_all)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = task_free_all ⇒ task_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_list_del +
    • >>   task_free +
    +
    [Called By]
    • >>   knl_idle_entry +
    + +

    tick_list_add (Thumb, 72 bytes, Stack size 16 bytes, tos_tick.o(i.tick_list_add)) +

    [Stack]

    • Max Depth = 80 + Unknown Stack Size +
    • Call Chain = tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tick_task_place +
    +
    [Called By]
    • >>   tos_task_delay +
    • >>   pend_task_block +
    + +

    tick_list_remove (Thumb, 24 bytes, Stack size 8 bytes, tos_tick.o(i.tick_list_remove)) +

    [Stack]

    • Max Depth = 32 + Unknown Stack Size +
    • Call Chain = tick_list_remove ⇒ tick_task_takeoff ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tick_task_takeoff +
    +
    [Called By]
    • >>   pend_task_wakeup +
    • >>   task_do_destroy +
    + +

    tick_update (Thumb, 180 bytes, Stack size 32 bytes, tos_tick.o(i.tick_update)) +

    [Stack]

    • Max Depth = 88 + Unknown Stack Size +
    • Call Chain = tick_update ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   pend_task_wakeup +
    • >>   tos_list_empty +
    +
    [Called By]
    • >>   tos_tick_handler +
    + +

    timer_init (Thumb, 4 bytes, Stack size 0 bytes, tos_timer.o(i.timer_init)) +

    [Called By]

    • >>   tos_knl_init +
    + +

    timer_update (Thumb, 118 bytes, Stack size 16 bytes, tos_timer.o(i.timer_update)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = timer_update ⇒ timer_takeoff ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_knl_sched_lock +
    • >>   timer_takeoff +
    • >>   timer_place +
    • >>   tos_knl_sched_unlock +
    +
    [Called By]
    • >>   tos_tick_handler +
    + +

    tos_at_channel_alloc (Thumb, 76 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_channel_alloc)) +

    [Stack]

    • Max Depth = 176 + Unknown Stack Size +
    • Call Chain = tos_at_channel_alloc ⇒ at_channel_construct ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   at_channel_construct +
    +
    [Called By]
    • >>   esp8266_connect +
    + +

    tos_at_channel_free (Thumb, 64 bytes, Stack size 16 bytes, tos_at.o(i.tos_at_channel_free)) +

    [Stack]

    • Max Depth = 120 + Unknown Stack Size +
    • Call Chain = tos_at_channel_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_mmheap_free +
    • >>   tos_mutex_destroy +
    • >>   tos_chr_fifo_destroy +
    • >>   at_channel_get +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   esp8266_connect +
    • >>   esp8266_close +
    + +

    tos_at_channel_is_working (Thumb, 34 bytes, Stack size 16 bytes, tos_at.o(i.tos_at_channel_is_working)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_at_channel_is_working ⇒ at_channel_get +
    +
    [Calls]
    • >>   at_channel_get +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send +
    + +

    tos_at_channel_read_timed (Thumb, 170 bytes, Stack size 56 bytes, tos_at.o(i.tos_at_channel_read_timed)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   tos_chr_fifo_pop_stream +
    • >>   tos_millisec2tick +
    • >>   at_timer_remain +
    • >>   at_timer_is_expired +
    • >>   at_timer_countdown +
    • >>   at_channel_get +
    +
    [Called By]
    • >>   esp8266_recvfrom_timeout +
    • >>   esp8266_recv_timeout +
    + +

    tos_at_channel_set_broken (Thumb, 34 bytes, Stack size 16 bytes, tos_at.o(i.tos_at_channel_set_broken)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_at_channel_set_broken ⇒ at_channel_get +
    +
    [Calls]
    • >>   at_channel_get +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send +
    + +

    tos_at_channel_write (Thumb, 72 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_channel_write)) +

    [Stack]

    • Max Depth = 160 + Unknown Stack Size +
    • Call Chain = tos_at_channel_write ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend +
    • >>   tos_chr_fifo_push_stream +
    • >>   at_channel_get +
    +
    [Called By]
    • >>   esp8266_incoming_data_process +
    + +

    tos_at_cmd_exec (Thumb, 86 bytes, Stack size 48 bytes, tos_at.o(i.tos_at_cmd_exec)) +

    [Stack]

    • Max Depth = 232 + Unknown Stack Size +
    • Call Chain = tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_task_delay +
    • >>   tos_millisec2tick +
    • >>   at_echo_attach +
    • >>   at_cmd_do_exec +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send_mode_set +
    • >>   esp8266_send +
    • >>   esp8266_restore +
    • >>   esp8266_parse_domain +
    • >>   esp8266_net_mode_set +
    • >>   esp8266_multilink_set +
    • >>   esp8266_echo_close +
    • >>   esp8266_close +
    + +

    tos_at_cmd_exec_until (Thumb, 134 bytes, Stack size 48 bytes, tos_at.o(i.tos_at_cmd_exec_until)) +

    [Stack]

    • Max Depth = 232 + Unknown Stack Size +
    • Call Chain = tos_at_cmd_exec_until ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_sem_pend +
    • >>   tos_sem_destroy +
    • >>   tos_sem_create +
    • >>   tos_millisec2tick +
    • >>   at_echo_attach +
    • >>   at_cmd_do_exec +
    +
    [Called By]
    • >>   esp8266_join_ap +
    • >>   esp8266_connect +
    + +

    tos_at_echo_create (Thumb, 52 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_echo_create)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_at_echo_create +
    +
    [Calls]
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   esp8266_join_ap +
    • >>   esp8266_sendto +
    • >>   esp8266_send_mode_set +
    • >>   esp8266_send +
    • >>   esp8266_restore +
    • >>   esp8266_parse_domain +
    • >>   esp8266_net_mode_set +
    • >>   esp8266_multilink_set +
    • >>   esp8266_echo_close +
    • >>   esp8266_connect +
    + +

    tos_at_global_lock_pend (Thumb, 20 bytes, Stack size 8 bytes, tos_at.o(i.tos_at_global_lock_pend)) +

    [Stack]

    • Max Depth = 144 + Unknown Stack Size +
    • Call Chain = tos_at_global_lock_pend ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_pend +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send +
    + +

    tos_at_global_lock_post (Thumb, 20 bytes, Stack size 8 bytes, tos_at.o(i.tos_at_global_lock_post)) +

    [Stack]

    • Max Depth = 120 + Unknown Stack Size +
    • Call Chain = tos_at_global_lock_post ⇒ tos_mutex_post ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_mutex_post +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send +
    + +

    tos_at_init (Thumb, 344 bytes, Stack size 40 bytes, tos_at.o(i.tos_at_init)) +

    [Stack]

    • Max Depth = 176 + Unknown Stack Size +
    • Call Chain = tos_at_init ⇒ at_recv_cache_init ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   tos_mmheap_free +
    • >>   tos_mmheap_alloc +
    • >>   tos_mutex_destroy +
    • >>   tos_mutex_create +
    • >>   tos_chr_fifo_destroy +
    • >>   tos_chr_fifo_create +
    • >>   tos_sem_destroy +
    • >>   tos_sem_create +
    • >>   tos_task_destroy +
    • >>   tos_task_create +
    • >>   at_timer_init +
    • >>   at_recv_cache_init +
    • >>   at_recv_cache_deinit +
    • >>   at_event_table_set +
    • >>   at_channel_init +
    • >>   tos_hal_uart_init +
    • >>   tos_hal_uart_deinit +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   esp8266_sal_init +
    + +

    tos_at_raw_data_send_until (Thumb, 118 bytes, Stack size 32 bytes, tos_at.o(i.tos_at_raw_data_send_until)) +

    [Stack]

    • Max Depth = 192 + Unknown Stack Size +
    • Call Chain = tos_at_raw_data_send_until ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_sem_pend +
    • >>   tos_sem_destroy +
    • >>   tos_sem_create +
    • >>   tos_millisec2tick +
    • >>   at_uart_send +
    • >>   at_echo_attach +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send +
    + +

    tos_at_uart_read (Thumb, 48 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_uart_read)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = tos_at_uart_read ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   at_uart_getchar +
    +
    [Called By]
    • >>   esp8266_incoming_data_process +
    + +

    tos_at_uart_write_byte (Thumb, 24 bytes, Stack size 8 bytes, tos_at.o(i.tos_at_uart_write_byte)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_chr_fifo_push +
    • >>   tos_sem_post +
    +
    [Called By]
    • >>   HAL_UART_RxCpltCallback +
    + +

    tos_chr_fifo_create (Thumb, 92 bytes, Stack size 24 bytes, tos_char_fifo.o(i.tos_chr_fifo_create)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = tos_chr_fifo_create ⇒ tos_ring_q_create +
    +
    [Calls]
    • >>   knl_object_init +
    • >>   knl_object_alloc_set_static +
    • >>   tos_ring_q_create +
    +
    [Called By]
    • >>   at_channel_construct +
    • >>   tos_at_init +
    + +

    tos_chr_fifo_destroy (Thumb, 90 bytes, Stack size 16 bytes, tos_char_fifo.o(i.tos_chr_fifo_destroy)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_chr_fifo_destroy ⇒ tos_ring_q_destroy +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   knl_object_deinit +
    • >>   knl_object_alloc_reset +
    • >>   knl_object_alloc_is_static +
    • >>   tos_ring_q_destroy +
    +
    [Called By]
    • >>   tos_at_init +
    • >>   tos_at_channel_free +
    + +

    tos_chr_fifo_pop (Thumb, 60 bytes, Stack size 16 bytes, tos_char_fifo.o(i.tos_chr_fifo_pop)) +

    [Stack]

    • Max Depth = 72 + Unknown Stack Size +
    • Call Chain = tos_chr_fifo_pop ⇒ tos_ring_q_dequeue ⇒ tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_ring_q_dequeue +
    +
    [Called By]
    • >>   at_uart_getchar +
    + +

    tos_chr_fifo_pop_stream (Thumb, 122 bytes, Stack size 32 bytes, tos_char_fifo.o(i.tos_chr_fifo_pop_stream)) +

    [Stack]

    • Max Depth = 88 + Unknown Stack Size +
    • Call Chain = tos_chr_fifo_pop_stream ⇒ tos_ring_q_dequeue ⇒ tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_ring_q_dequeue +
    +
    [Called By]
    • >>   tos_at_channel_read_timed +
    + +

    tos_chr_fifo_push (Thumb, 58 bytes, Stack size 16 bytes, tos_char_fifo.o(i.tos_chr_fifo_push)) +

    [Stack]

    • Max Depth = 64 + Unknown Stack Size +
    • Call Chain = tos_chr_fifo_push ⇒ tos_ring_q_enqueue ⇒ tos_ring_q_is_full ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_ring_q_enqueue +
    +
    [Called By]
    • >>   tos_at_uart_write_byte +
    + +

    tos_chr_fifo_push_stream (Thumb, 116 bytes, Stack size 32 bytes, tos_char_fifo.o(i.tos_chr_fifo_push_stream)) +

    [Stack]

    • Max Depth = 80 + Unknown Stack Size +
    • Call Chain = tos_chr_fifo_push_stream ⇒ tos_ring_q_enqueue ⇒ tos_ring_q_is_full ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_ring_q_enqueue +
    +
    [Called By]
    • >>   tos_at_channel_write +
    + +

    tos_cpu_clz (Thumb, 12 bytes, Stack size 8 bytes, tos_cpu.o(i.tos_cpu_clz)) +

    [Stack]

    • Max Depth = 8 + Unknown Stack Size +
    • Call Chain = tos_cpu_clz +
    +
    [Calls]
    • >>   port_clz +
    +
    [Called By]
    • >>   generic_fls +
    • >>   readyqueue_prio_highest_get +
    + +

    tos_cpu_cpsr_restore (Thumb, 12 bytes, Stack size 8 bytes, tos_cpu.o(i.tos_cpu_cpsr_restore)) +

    [Stack]

    • Max Depth = 8 + Unknown Stack Size +
    • Call Chain = tos_cpu_cpsr_restore +
    +
    [Calls]
    • >>   port_cpsr_restore +
    +
    [Called By]
    • >>   tos_task_delay +
    • >>   tos_knl_irq_leave +
    • >>   tos_task_prio_change +
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   tos_mutex_destroy +
    • >>   knl_sched +
    • >>   tos_ring_q_is_full +
    • >>   tos_ring_q_is_empty +
    • >>   tos_ring_q_enqueue +
    • >>   tos_ring_q_dequeue +
    • >>   tos_chr_fifo_push_stream +
    • >>   tos_chr_fifo_pop_stream +
    • >>   tos_sem_pend +
    • >>   tos_sem_destroy +
    • >>   sem_do_post +
    • >>   tos_knl_sched_lock +
    • >>   timer_takeoff +
    • >>   timer_place +
    • >>   tos_systick_get +
    • >>   tick_update +
    • >>   tick_task_takeoff +
    • >>   tick_task_place +
    • >>   tos_task_yield +
    • >>   task_do_destroy +
    • >>   tos_task_create +
    • >>   task_free_all +
    • >>   tos_knl_sched_unlock +
    + +

    tos_cpu_cpsr_save (Thumb, 8 bytes, Stack size 8 bytes, tos_cpu.o(i.tos_cpu_cpsr_save)) +

    [Stack]

    • Max Depth = 8 + Unknown Stack Size +
    • Call Chain = tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   port_cpsr_save +
    +
    [Called By]
    • >>   tos_task_delay +
    • >>   tos_knl_irq_leave +
    • >>   tos_task_prio_change +
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   tos_mutex_destroy +
    • >>   knl_sched +
    • >>   tos_ring_q_is_full +
    • >>   tos_ring_q_is_empty +
    • >>   tos_ring_q_enqueue +
    • >>   tos_ring_q_dequeue +
    • >>   tos_chr_fifo_push_stream +
    • >>   tos_chr_fifo_pop_stream +
    • >>   tos_sem_pend +
    • >>   tos_sem_destroy +
    • >>   sem_do_post +
    • >>   tos_knl_sched_lock +
    • >>   timer_takeoff +
    • >>   timer_place +
    • >>   tos_systick_get +
    • >>   tick_update +
    • >>   tick_task_takeoff +
    • >>   tick_task_place +
    • >>   tos_task_yield +
    • >>   task_do_destroy +
    • >>   tos_task_create +
    • >>   task_free_all +
    • >>   tos_knl_sched_unlock +
    + +

    tos_hal_uart_deinit (Thumb, 50 bytes, Stack size 16 bytes, tos_hal_uart.o(i.tos_hal_uart_deinit)) +

    [Stack]

    • Max Depth = 52
    • Call Chain = tos_hal_uart_deinit ⇒ HAL_UART_DeInit ⇒ HAL_UART_MspDeInit ⇒ HAL_GPIO_DeInit +
    +
    [Calls]
    • >>   HAL_UART_MspDeInit +
    • >>   HAL_UART_DeInit +
    +
    [Called By]
    • >>   tos_at_init +
    + +

    tos_hal_uart_init (Thumb, 70 bytes, Stack size 16 bytes, tos_hal_uart.o(i.tos_hal_uart_init)) +

    [Stack]

    • Max Depth = 112
    • Call Chain = tos_hal_uart_init ⇒ MX_USART1_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority +
    +
    [Calls]
    • >>   MX_USART1_UART_Init +
    • >>   MX_LPUART1_UART_Init +
    • >>   MX_USART3_UART_Init +
    • >>   MX_USART2_UART_Init +
    +
    [Called By]
    • >>   tos_at_init +
    + +

    tos_hal_uart_write (Thumb, 64 bytes, Stack size 32 bytes, tos_hal_uart.o(i.tos_hal_uart_write)) +

    [Stack]

    • Max Depth = 88
    • Call Chain = tos_hal_uart_write ⇒ HAL_UART_Transmit ⇒ UART_WaitOnFlagUntilTimeout +
    +
    [Calls]
    • >>   HAL_UART_Transmit +
    +
    [Called By]
    • >>   at_uart_send +
    + +

    tos_knl_init (Thumb, 56 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_init)) +

    [Stack]

    • Max Depth = 120 + Unknown Stack Size +
    • Call Chain = tos_knl_init ⇒ mmheap_init_with_pool ⇒ tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   mmheap_init_with_pool +
    • >>   readyqueue_init +
    • >>   timer_init +
    • >>   cpu_init +
    • >>   knl_idle_init +
    +
    [Called By]
    • >>   osKernelInitialize +
    + +

    tos_knl_irq_enter (Thumb, 42 bytes, Stack size 4 bytes, tos_sys.o(i.tos_knl_irq_enter)) +

    [Stack]

    • Max Depth = 4
    • Call Chain = tos_knl_irq_enter +
    +
    [Calls]
    • >>   tos_knl_is_running +
    +
    [Called By]
    • >>   SysTick_Handler +
    • >>   LPUART1_IRQHandler +
    + +

    tos_knl_irq_leave (Thumb, 134 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_irq_leave)) +

    [Stack]

    • Max Depth = 16 + Unknown Stack Size +
    • Call Chain = tos_knl_irq_leave ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_knl_is_running +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_is_self +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    • >>   readyqueue_highest_ready_task_get +
    • >>   cpu_irq_context_switch +
    +
    [Called By]
    • >>   SysTick_Handler +
    • >>   LPUART1_IRQHandler +
    + +

    tos_knl_is_running (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.tos_knl_is_running)) +

    [Called By]

    • >>   tos_tick_handler +
    • >>   tos_knl_irq_leave +
    • >>   tos_knl_irq_enter +
    • >>   SysTick_Handler +
    • >>   tos_knl_sched_lock +
    • >>   tos_task_create +
    • >>   tos_knl_start +
    • >>   tos_knl_sched_unlock +
    + +

    tos_knl_sched_lock (Thumb, 88 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_sched_lock)) +

    [Stack]

    • Max Depth = 16 + Unknown Stack Size +
    • Call Chain = tos_knl_sched_lock ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_knl_is_running +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   timer_update +
    + +

    tos_knl_sched_unlock (Thumb, 90 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_sched_unlock)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = tos_knl_sched_unlock ⇒ knl_sched ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_knl_is_running +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_sched +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   timer_update +
    + +

    tos_knl_start (Thumb, 44 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_start)) +

    [Stack]

    • Max Depth = 8 + Unknown Stack Size +
    • Call Chain = tos_knl_start +
    +
    [Calls]
    • >>   tos_knl_is_running +
    • >>   readyqueue_highest_ready_task_get +
    • >>   cpu_sched_start +
    +
    [Called By]
    • >>   osKernelStart +
    + +

    tos_millisec2tick (Thumb, 28 bytes, Stack size 16 bytes, tos_time.o(i.tos_millisec2tick)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = tos_millisec2tick ⇒ __aeabi_uldivmod +
    +
    [Calls]
    • >>   __aeabi_uldivmod +
    +
    [Called By]
    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_cmd_exec +
    • >>   tos_at_channel_read_timed +
    + +

    tos_mmheap_alloc (Thumb, 38 bytes, Stack size 16 bytes, tos_mmheap.o(i.tos_mmheap_alloc)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   blk_prepare_used +
    • >>   blk_locate_free +
    • >>   adjust_request_size +
    +
    [Called By]
    • >>   HAL_Malloc +
    • >>   at_recv_cache_init +
    • >>   at_channel_construct +
    • >>   tos_at_init +
    + +

    tos_mmheap_free (Thumb, 48 bytes, Stack size 16 bytes, tos_mmheap.o(i.tos_mmheap_free)) +

    [Stack]

    • Max Depth = 104 + Unknown Stack Size +
    • Call Chain = tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   blk_merge_prev +
    • >>   blk_merge_next +
    • >>   blk_mark_as_free +
    • >>   blk_insert +
    +
    [Called By]
    • >>   HAL_Free +
    • >>   task_free +
    • >>   at_recv_cache_deinit +
    • >>   at_channel_construct +
    • >>   tos_at_init +
    • >>   tos_at_channel_free +
    + +

    tos_mmheap_pool_add (Thumb, 182 bytes, Stack size 24 bytes, tos_mmheap.o(i.tos_mmheap_pool_add)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   offset_to_block +
    • >>   mmheap_pool_is_exist +
    • >>   blk_set_used +
    • >>   blk_set_size +
    • >>   blk_set_prev_used +
    • >>   blk_set_prev_free +
    • >>   blk_set_free +
    • >>   blk_link_next +
    • >>   blk_insert +
    +
    [Called By]
    • >>   mmheap_init_with_pool +
    + +

    tos_mutex_create (Thumb, 88 bytes, Stack size 8 bytes, tos_mutex.o(i.tos_mutex_create)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = tos_mutex_create ⇒ pend_object_init +
    +
    [Calls]
    • >>   knl_object_init +
    • >>   pend_object_init +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   at_channel_construct +
    • >>   tos_at_init +
    • >>   HAL_MutexCreate +
    + +

    tos_mutex_destroy (Thumb, 138 bytes, Stack size 16 bytes, tos_mutex.o(i.tos_mutex_destroy)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = tos_mutex_destroy ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   knl_object_deinit +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   mutex_old_owner_release +
    • >>   pend_wakeup_all +
    • >>   pend_object_deinit +
    • >>   pend_is_nopending +
    • >>   knl_sched +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   tos_at_init +
    • >>   tos_at_channel_free +
    • >>   HAL_MutexDestroy +
    + +

    tos_mutex_pend (Thumb, 18 bytes, Stack size 8 bytes, tos_mutex.o(i.tos_mutex_pend)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_pend_timed +
    +
    [Called By]
    • >>   at_uart_send +
    • >>   at_uart_getchar +
    • >>   at_cmd_do_exec +
    • >>   tos_at_global_lock_pend +
    • >>   tos_at_channel_write +
    • >>   HAL_MutexLock +
    + +

    tos_mutex_pend_timed (Thumb, 288 bytes, Stack size 24 bytes, tos_mutex.o(i.tos_mutex_pend_timed)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_task_prio_change +
    • >>   knl_is_self +
    • >>   mutex_fresh_owner_mark +
    • >>   pend_task_block +
    • >>   pend_state2errno +
    • >>   knl_sched +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   tos_mutex_pend +
    • >>   tos_at_channel_read_timed +
    + +

    tos_mutex_post (Thumb, 238 bytes, Stack size 32 bytes, tos_mutex.o(i.tos_mutex_post)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = tos_mutex_post ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_task_prio_change +
    • >>   pend_wakeup_one +
    • >>   pend_highest_pending_task_get +
    • >>   pend_highest_pending_prio_get +
    • >>   knl_is_self +
    • >>   mutex_old_owner_release +
    • >>   mutex_fresh_owner_mark +
    • >>   pend_is_nopending +
    • >>   knl_sched +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   at_uart_send +
    • >>   at_uart_getchar +
    • >>   at_cmd_do_exec +
    • >>   tos_at_global_lock_post +
    • >>   tos_at_channel_write +
    • >>   tos_at_channel_read_timed +
    • >>   HAL_MutexUnlock +
    + +

    tos_ring_q_create (Thumb, 88 bytes, Stack size 24 bytes, tos_ring_queue.o(i.tos_ring_q_create)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_ring_q_create +
    +
    [Calls]
    • >>   knl_object_init +
    • >>   knl_object_alloc_set_static +
    +
    [Called By]
    • >>   tos_chr_fifo_create +
    + +

    tos_ring_q_dequeue (Thumb, 182 bytes, Stack size 32 bytes, tos_ring_queue.o(i.tos_ring_q_dequeue)) +

    [Stack]

    • Max Depth = 56 + Unknown Stack Size +
    • Call Chain = tos_ring_q_dequeue ⇒ tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_ring_q_is_empty +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   tos_chr_fifo_pop_stream +
    • >>   tos_chr_fifo_pop +
    + +

    tos_ring_q_destroy (Thumb, 90 bytes, Stack size 8 bytes, tos_ring_queue.o(i.tos_ring_q_destroy)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = tos_ring_q_destroy +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   knl_object_deinit +
    • >>   knl_object_alloc_reset +
    • >>   knl_object_alloc_is_static +
    +
    [Called By]
    • >>   tos_chr_fifo_destroy +
    + +

    tos_ring_q_enqueue (Thumb, 184 bytes, Stack size 24 bytes, tos_ring_queue.o(i.tos_ring_q_enqueue)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = tos_ring_q_enqueue ⇒ tos_ring_q_is_full ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_ring_q_is_full +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   tos_chr_fifo_push_stream +
    • >>   tos_chr_fifo_push +
    + +

    tos_ring_q_is_empty (Thumb, 82 bytes, Stack size 16 bytes, tos_ring_queue.o(i.tos_ring_q_is_empty)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    +
    [Called By]
    • >>   tos_ring_q_dequeue +
    + +

    tos_ring_q_is_full (Thumb, 86 bytes, Stack size 16 bytes, tos_ring_queue.o(i.tos_ring_q_is_full)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = tos_ring_q_is_full ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    +
    [Called By]
    • >>   tos_ring_q_enqueue +
    + +

    tos_sal_module_close (Thumb, 36 bytes, Stack size 8 bytes, sal_module_wrapper.o(i.tos_sal_module_close)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = tos_sal_module_close +
    +
    [Called By]
    • >>   HAL_TCP_Destroy +
    + +

    tos_sal_module_connect (Thumb, 44 bytes, Stack size 16 bytes, sal_module_wrapper.o(i.tos_sal_module_connect)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = tos_sal_module_connect +
    +
    [Called By]
    • >>   HAL_TCP_Establish +
    + +

    tos_sal_module_init (Thumb, 32 bytes, Stack size 8 bytes, sal_module_wrapper.o(i.tos_sal_module_init)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = tos_sal_module_init +
    +
    [Called By]
    • >>   esp8266_sal_init +
    • >>   HAL_TCP_Establish +
    + +

    tos_sal_module_recv_timeout (Thumb, 54 bytes, Stack size 24 bytes, sal_module_wrapper.o(i.tos_sal_module_recv_timeout)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_sal_module_recv_timeout +
    +
    [Called By]
    • >>   HAL_TCP_Read +
    + +

    tos_sal_module_register (Thumb, 22 bytes, Stack size 0 bytes, sal_module_wrapper.o(i.tos_sal_module_register)) +

    [Called By]

    • >>   esp8266_sal_init +
    + +

    tos_sal_module_send (Thumb, 44 bytes, Stack size 16 bytes, sal_module_wrapper.o(i.tos_sal_module_send)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = tos_sal_module_send +
    +
    [Called By]
    • >>   HAL_TCP_Write +
    + +

    tos_sem_create (Thumb, 20 bytes, Stack size 16 bytes, tos_sem.o(i.tos_sem_create)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = tos_sem_create ⇒ tos_sem_create_max ⇒ pend_object_init +
    +
    [Calls]
    • >>   tos_sem_create_max +
    +
    [Called By]
    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_init +
    + +

    tos_sem_create_max (Thumb, 52 bytes, Stack size 16 bytes, tos_sem.o(i.tos_sem_create_max)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = tos_sem_create_max ⇒ pend_object_init +
    +
    [Calls]
    • >>   knl_object_init +
    • >>   pend_object_init +
    +
    [Called By]
    • >>   tos_sem_create +
    + +

    tos_sem_destroy (Thumb, 104 bytes, Stack size 16 bytes, tos_sem.o(i.tos_sem_destroy)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = tos_sem_destroy ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   knl_object_deinit +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   pend_wakeup_all +
    • >>   pend_object_deinit +
    • >>   pend_is_nopending +
    • >>   knl_sched +
    +
    [Called By]
    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_init +
    + +

    tos_sem_pend (Thumb, 206 bytes, Stack size 24 bytes, tos_sem.o(i.tos_sem_pend)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = tos_sem_pend ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   pend_task_block +
    • >>   pend_state2errno +
    • >>   knl_sched +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    +
    [Called By]
    • >>   at_uart_getchar +
    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_cmd_exec_until +
    + +

    tos_sem_post (Thumb, 14 bytes, Stack size 8 bytes, tos_sem.o(i.tos_sem_post)) +

    [Stack]

    • Max Depth = 120 + Unknown Stack Size +
    • Call Chain = tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   sem_do_post +
    +
    [Called By]
    • >>   tos_at_uart_write_byte +
    • >>   at_parser +
    + +

    tos_sleep_hmsm (Thumb, 112 bytes, Stack size 40 bytes, tos_time.o(i.tos_sleep_hmsm)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = tos_sleep_hmsm ⇒ tos_task_delay ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_task_delay +
    • >>   __aeabi_uldivmod +
    +
    [Called By]
    • >>   HAL_SleepMs +
    + +

    tos_systick_get (Thumb, 34 bytes, Stack size 16 bytes, tos_time.o(i.tos_systick_get)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    +
    [Called By]
    • >>   at_timer_remain +
    • >>   at_timer_is_expired +
    • >>   at_timer_countdown +
    • >>   at_delay +
    • >>   HAL_UptimeMs +
    + +

    tos_task_create (Thumb, 292 bytes, Stack size 40 bytes, tos_task.o(i.tos_task_create)) +

    [Stack]

    • Max Depth = 72 + Unknown Stack Size +
    • Call Chain = tos_task_create ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_knl_is_running +
    • >>   knl_object_init +
    • >>   knl_object_alloc_set_static +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_sched +
    • >>   knl_is_inirq +
    • >>   readyqueue_add_tail +
    • >>   cpu_task_stk_init +
    • >>   tos_list_add +
    • >>   task_reset +
    • >>   knl_is_idle +
    +
    [Called By]
    • >>   osThreadCreate +
    • >>   knl_idle_init +
    • >>   tos_at_init +
    + +

    tos_task_delay (Thumb, 136 bytes, Stack size 16 bytes, tos_task.o(i.tos_task_delay)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = tos_task_delay ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_sched +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    • >>   tick_list_add +
    • >>   readyqueue_remove +
    • >>   tos_task_yield +
    +
    [Called By]
    • >>   application_entry +
    • >>   tos_sleep_hmsm +
    • >>   tos_at_cmd_exec +
    + +

    tos_task_destroy (Thumb, 106 bytes, Stack size 8 bytes, tos_task.o(i.tos_task_destroy)) +

    [Stack]

    • Max Depth = 128 + Unknown Stack Size +
    • Call Chain = tos_task_destroy ⇒ task_do_destroy ⇒ task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   knl_object_alloc_is_static +
    • >>   knl_is_self +
    • >>   knl_is_sched_locked +
    • >>   knl_is_inirq +
    • >>   task_do_destroy +
    +
    [Called By]
    • >>   task_exit +
    • >>   tos_at_init +
    + +

    tos_task_prio_change (Thumb, 248 bytes, Stack size 24 bytes, tos_task.o(i.tos_task_prio_change)) +

    [Stack]

    • Max Depth = 64 + Unknown Stack Size +
    • Call Chain = tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_is_self +
    • >>   knl_sched +
    • >>   knl_is_inirq +
    • >>   readyqueue_add_tail +
    • >>   readyqueue_add_head +
    • >>   readyqueue_remove +
    • >>   pend_list_adjust +
    • >>   tos_list_empty +
    • >>   task_state_is_ready +
    • >>   task_highest_pending_prio_get +
    +
    [Called By]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    • >>   mutex_old_owner_release +
    + +

    tos_task_yield (Thumb, 56 bytes, Stack size 8 bytes, tos_task.o(i.tos_task_yield)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = tos_task_yield ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_sched +
    • >>   knl_is_inirq +
    • >>   readyqueue_add_tail +
    • >>   readyqueue_remove +
    +
    [Called By]
    • >>   tos_task_delay +
    + +

    tos_tick_handler (Thumb, 34 bytes, Stack size 8 bytes, tos_tick.o(i.tos_tick_handler)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = tos_tick_handler ⇒ tick_update ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   tos_knl_is_running +
    • >>   timer_update +
    • >>   tick_update +
    +
    [Called By]
    • >>   SysTick_Handler +
    + +

    utils_hmac_sha256 (Thumb, 194 bytes, Stack size 264 bytes, infra_sha256.o(i.utils_hmac_sha256)) +

    [Stack]

    • Max Depth = 640
    • Call Chain = utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   utils_sha256_update +
    • >>   utils_sha256_starts +
    • >>   utils_sha256_init +
    • >>   utils_sha256_finish +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   _iotx_generate_sign_string +
    + +

    utils_net_read (Thumb, 62 bytes, Stack size 32 bytes, infra_net.o(i.utils_net_read)) +

    [Stack]

    • Max Depth = 160
    • Call Chain = utils_net_read ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   read_tcp +
    +
    [Address Reference Count : 1]
    • infra_net.o(i.iotx_net_init) +
    +

    utils_net_write (Thumb, 62 bytes, Stack size 32 bytes, infra_net.o(i.utils_net_write)) +

    [Stack]

    • Max Depth = 160
    • Call Chain = utils_net_write ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   write_tcp +
    +
    [Address Reference Count : 1]
    • infra_net.o(i.iotx_net_init) +
    +

    utils_sha256_finish (Thumb, 350 bytes, Stack size 40 bytes, infra_sha256.o(i.utils_sha256_finish)) +

    [Stack]

    • Max Depth = 376
    • Call Chain = utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   utils_sha256_update +
    +
    [Called By]
    • >>   utils_hmac_sha256 +
    + +

    utils_sha256_init (Thumb, 14 bytes, Stack size 8 bytes, infra_sha256.o(i.utils_sha256_init)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = utils_sha256_init +
    +
    [Calls]
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   utils_hmac_sha256 +
    + +

    utils_sha256_process (Thumb, 444 bytes, Stack size 312 bytes, infra_sha256.o(i.utils_sha256_process)) +

    [Stack]

    • Max Depth = 312
    • Call Chain = utils_sha256_process +
    +
    [Called By]
    • >>   utils_sha256_update +
    + +

    utils_sha256_starts (Thumb, 46 bytes, Stack size 0 bytes, infra_sha256.o(i.utils_sha256_starts)) +

    [Called By]

    • >>   utils_hmac_sha256 +
    + +

    utils_sha256_update (Thumb, 124 bytes, Stack size 24 bytes, infra_sha256.o(i.utils_sha256_update)) +

    [Stack]

    • Max Depth = 336
    • Call Chain = utils_sha256_update ⇒ utils_sha256_process +
    +
    [Calls]
    • >>   utils_sha256_process +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   utils_sha256_finish +
    • >>   utils_hmac_sha256 +
    + +

    utils_time_countdown_ms (Thumb, 22 bytes, Stack size 16 bytes, infra_timer.o(i.utils_time_countdown_ms)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = utils_time_countdown_ms ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_UptimeMs +
    +
    [Called By]
    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_keepalive +
    • >>   iotx_mc_handle_reconnect +
    • >>   _mqtt_connect +
    • >>   MQTTSubscribe +
    • >>   MQTTRePublish +
    • >>   MQTTPuback +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   _mqtt_cycle +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    utils_time_is_expired (Thumb, 36 bytes, Stack size 16 bytes, infra_timer.o(i.utils_time_is_expired)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = utils_time_is_expired ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_UptimeMs +
    +
    [Called By]
    • >>   iotx_mc_send_packet +
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_handle_reconnect +
    • >>   iotx_time_left +
    • >>   _mqtt_cycle +
    + +

    utils_time_spend (Thumb, 24 bytes, Stack size 16 bytes, infra_timer.o(i.utils_time_spend)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = utils_time_spend ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_UptimeMs +
    +
    [Called By]
    • >>   MQTTPubInfoProc +
    + +

    wrapper_mqtt_check_state (Thumb, 28 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_check_state)) +

    [Stack]

    • Max Depth = 176 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_check_state ⇒ iotx_mc_get_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_get_client_state +
    +
    [Called By]
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_disconnect +
    • >>   wrapper_mqtt_subscribe +
    • >>   wrapper_mqtt_publish +
    + +

    wrapper_mqtt_connect (Thumb, 202 bytes, Stack size 48 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_connect)) +

    [Stack]

    • Max Depth = 848 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   _mqtt_connect +
    • >>   LITE_syslog +
    • >>   HAL_SleepMs +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    • >>   iotx_mc_attempt_reconnect +
    + +

    wrapper_mqtt_init (Thumb, 152 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_init)) +

    [Stack]

    • Max Depth = 312 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_init ⇒ iotx_mc_init ⇒ iotx_mc_set_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_release +
    • >>   iotx_mc_init +
    • >>   LITE_syslog +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    + +

    wrapper_mqtt_publish (Thumb, 232 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_publish)) +

    [Stack]

    • Max Depth = 280 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_publish ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_get_next_packetid +
    • >>   iotx_mc_get_client_state +
    • >>   iotx_mc_check_topic +
    • >>   wrapper_mqtt_check_state +
    • >>   LITE_syslog +
    • >>   MQTTPublish +
    +
    [Called By]
    • >>   IOT_MQTT_Publish_Simple +
    + +

    wrapper_mqtt_release (Thumb, 148 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_release)) +

    [Stack]

    • Max Depth = 216 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_release ⇒ iotx_mc_disconnect ⇒ MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_pub_wait_list_deinit +
    • >>   iotx_mc_disconnect +
    • >>   LITE_syslog +
    • >>   HAL_SleepMs +
    • >>   HAL_MutexDestroy +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   IOT_MQTT_Destroy +
    • >>   IOT_MQTT_Construct +
    + +

    wrapper_mqtt_subscribe (Thumb, 256 bytes, Stack size 64 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_subscribe)) +

    [Stack]

    • Max Depth = 304 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_get_next_packetid +
    • >>   iotx_mc_get_client_state +
    • >>   iotx_mc_check_topic +
    • >>   MQTTSubscribe +
    • >>   wrapper_mqtt_check_state +
    • >>   LITE_syslog +
    • >>   strlen +
    +
    [Called By]
    • >>   IOT_MQTT_Subscribe +
    • >>   iotx_mqtt_deal_offline_subs +
    + +

    wrapper_mqtt_yield (Thumb, 88 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_yield)) +

    [Stack]

    • Max Depth = 952 + Unknown Stack Size +
    • Call Chain = wrapper_mqtt_yield ⇒ iotx_mc_keepalive ⇒ iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_keepalive +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   _mqtt_cycle +
    +
    [Called By]
    • >>   IOT_MQTT_Yield +
    + +

    writeCString (Thumb, 40 bytes, Stack size 16 bytes, mqttpacket.o(i.writeCString)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = writeCString ⇒ writeInt +
    +
    [Calls]
    • >>   writeInt +
    • >>   strlen +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   writeMQTTString +
    • >>   MQTTSerialize_connect +
    + +

    writeChar (Thumb, 12 bytes, Stack size 0 bytes, mqttpacket.o(i.writeChar)) +

    [Called By]

    • >>   MQTTSerialize_zero +
    • >>   MQTTSerialize_subscribe +
    • >>   MQTTSerialize_publish +
    • >>   MQTTSerialize_connect +
    • >>   MQTTSerialize_ack +
    + +

    writeInt (Thumb, 48 bytes, Stack size 8 bytes, mqttpacket.o(i.writeInt)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = writeInt +
    +
    [Called By]
    • >>   writeMQTTString +
    • >>   writeCString +
    • >>   MQTTSerialize_subscribe +
    • >>   MQTTSerialize_publish +
    • >>   MQTTSerialize_connect +
    • >>   MQTTSerialize_ack +
    + +

    writeMQTTString (Thumb, 62 bytes, Stack size 24 bytes, mqttpacket.o(i.writeMQTTString)) +

    [Stack]

    • Max Depth = 48
    • Call Chain = writeMQTTString ⇒ writeCString ⇒ writeInt +
    +
    [Calls]
    • >>   writeInt +
    • >>   writeCString +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   MQTTSerialize_subscribe +
    • >>   MQTTSerialize_publish +
    • >>   MQTTSerialize_connect +
    +

    +

    +Local Symbols +

    +

    UART_DMAAbortOnError (Thumb, 24 bytes, Stack size 16 bytes, stm32l4xx_hal_uart.o(i.UART_DMAAbortOnError)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = UART_DMAAbortOnError +
    +
    [Calls]
    • >>   HAL_UART_ErrorCallback +
    +
    [Address Reference Count : 1]
    • stm32l4xx_hal_uart.o(i.HAL_UART_IRQHandler) +
    +

    UART_EndRxTransfer (Thumb, 36 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.UART_EndRxTransfer)) +

    [Called By]

    • >>   HAL_UART_IRQHandler +
    + +

    UART_EndTransmit_IT (Thumb, 34 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.UART_EndTransmit_IT)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = UART_EndTransmit_IT +
    +
    [Calls]
    • >>   HAL_UART_TxCpltCallback +
    +
    [Called By]
    • >>   HAL_UART_IRQHandler +
    + +

    UART_RxISR_16BIT (Thumb, 108 bytes, Stack size 24 bytes, stm32l4xx_hal_uart.o(i.UART_RxISR_16BIT)) +

    [Stack]

    • Max Depth = 160 + Unknown Stack Size +
    • Call Chain = UART_RxISR_16BIT ⇒ HAL_UART_RxCpltCallback ⇒ tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   HAL_UART_RxCpltCallback +
    +
    [Address Reference Count : 1]
    • stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT) +
    +

    UART_RxISR_8BIT (Thumb, 102 bytes, Stack size 16 bytes, stm32l4xx_hal_uart.o(i.UART_RxISR_8BIT)) +

    [Stack]

    • Max Depth = 152 + Unknown Stack Size +
    • Call Chain = UART_RxISR_8BIT ⇒ HAL_UART_RxCpltCallback ⇒ tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   HAL_UART_RxCpltCallback +
    +
    [Address Reference Count : 1]
    • stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT) +
    +

    RCC_SetFlashLatencyFromMSIRange (Thumb, 148 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc.o(i.RCC_SetFlashLatencyFromMSIRange)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = RCC_SetFlashLatencyFromMSIRange +
    +
    [Calls]
    • >>   HAL_PWREx_GetVoltageRange +
    +
    [Called By]
    • >>   HAL_RCC_OscConfig +
    + +

    RCCEx_PLLSAI1_Config (Thumb, 376 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc_ex.o(i.RCCEx_PLLSAI1_Config)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = RCCEx_PLLSAI1_Config +
    +
    [Calls]
    • >>   HAL_GetTick +
    +
    [Called By]
    • >>   HAL_RCCEx_PeriphCLKConfig +
    + +

    __NVIC_GetPriorityGrouping (Thumb, 10 bytes, Stack size 0 bytes, stm32l4xx_hal_cortex.o(i.__NVIC_GetPriorityGrouping)) +

    [Called By]

    • >>   HAL_NVIC_SetPriority +
    + +

    __NVIC_SetPriority (Thumb, 32 bytes, Stack size 8 bytes, stm32l4xx_hal_cortex.o(i.__NVIC_SetPriority)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = __NVIC_SetPriority +
    +
    [Called By]
    • >>   HAL_NVIC_SetPriority +
    • >>   HAL_SYSTICK_Config +
    + +

    DHT11_Mode_Out_PP (Thumb, 30 bytes, Stack size 24 bytes, dht11_bus.o(i.DHT11_Mode_Out_PP)) +

    [Stack]

    • Max Depth = 44
    • Call Chain = DHT11_Mode_Out_PP ⇒ HAL_GPIO_Init +
    +
    [Calls]
    • >>   HAL_GPIO_Init +
    +
    [Called By]
    • >>   DHT11_Init +
    + +

    __ffs (Thumb, 20 bytes, Stack size 8 bytes, tos_mmheap.o(i.__ffs)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = __ffs ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   generic_fls +
    +
    [Called By]
    • >>   blk_search_suitable +
    + +

    __fls (Thumb, 14 bytes, Stack size 8 bytes, tos_mmheap.o(i.__fls)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   generic_fls +
    +
    [Called By]
    • >>   mapping_search +
    • >>   mapping_insert +
    + +

    adjust_request_size (Thumb, 46 bytes, Stack size 8 bytes, tos_mmheap.o(i.adjust_request_size)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = adjust_request_size +
    +
    [Called By]
    • >>   tos_mmheap_alloc +
    + +

    blk_absorb (Thumb, 30 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_absorb)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = blk_absorb ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   blk_size +
    • >>   blk_link_next +
    +
    [Called By]
    • >>   blk_merge_prev +
    • >>   blk_merge_next +
    + +

    blk_can_split (Thumb, 28 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_can_split)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = blk_can_split +
    +
    [Calls]
    • >>   blk_size +
    +
    [Called By]
    • >>   blk_trim_free +
    + +

    blk_insert (Thumb, 32 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_insert)) +

    [Stack]

    • Max Depth = 72 + Unknown Stack Size +
    • Call Chain = blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   mapping_insert +
    • >>   insert_free_block +
    • >>   blk_size +
    +
    [Called By]
    • >>   tos_mmheap_free +
    • >>   tos_mmheap_pool_add +
    • >>   blk_trim_free +
    + +

    blk_link_next (Thumb, 18 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_link_next)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   blk_next +
    +
    [Called By]
    • >>   tos_mmheap_pool_add +
    • >>   blk_trim_free +
    • >>   blk_mark_as_free +
    • >>   blk_absorb +
    + +

    blk_locate_free (Thumb, 58 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_locate_free)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = blk_locate_free ⇒ mapping_search ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   remove_free_block +
    • >>   mapping_search +
    • >>   blk_search_suitable +
    +
    [Called By]
    • >>   tos_mmheap_alloc +
    + +

    blk_mark_as_free (Thumb, 26 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_mark_as_free)) +

    [Stack]

    • Max Depth = 56
    • Call Chain = blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   blk_set_prev_free +
    • >>   blk_set_free +
    • >>   blk_link_next +
    +
    [Called By]
    • >>   tos_mmheap_free +
    • >>   blk_split +
    + +

    blk_mark_as_used (Thumb, 26 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_mark_as_used)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = blk_mark_as_used ⇒ blk_next +
    +
    [Calls]
    • >>   blk_set_used +
    • >>   blk_set_prev_used +
    • >>   blk_next +
    +
    [Called By]
    • >>   blk_prepare_used +
    + +

    blk_merge_next (Thumb, 42 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_merge_next)) +

    [Stack]

    • Max Depth = 88 + Unknown Stack Size +
    • Call Chain = blk_merge_next ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   blk_remove +
    • >>   blk_next +
    • >>   blk_absorb +
    +
    [Called By]
    • >>   tos_mmheap_free +
    + +

    blk_merge_prev (Thumb, 40 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_merge_prev)) +

    [Stack]

    • Max Depth = 88 + Unknown Stack Size +
    • Call Chain = blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   blk_remove +
    • >>   blk_absorb +
    +
    [Called By]
    • >>   tos_mmheap_free +
    + +

    blk_next (Thumb, 36 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_next)) +

    [Stack]

    • Max Depth = 24
    • Call Chain = blk_next +
    +
    [Calls]
    • >>   offset_to_block +
    • >>   blk_to_ptr +
    • >>   blk_size +
    +
    [Called By]
    • >>   blk_merge_next +
    • >>   blk_mark_as_used +
    • >>   blk_link_next +
    + +

    blk_prepare_used (Thumb, 34 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_prepare_used)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   blk_trim_free +
    • >>   blk_to_ptr +
    • >>   blk_mark_as_used +
    +
    [Called By]
    • >>   tos_mmheap_alloc +
    + +

    blk_remove (Thumb, 32 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_remove)) +

    [Stack]

    • Max Depth = 72 + Unknown Stack Size +
    • Call Chain = blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   remove_free_block +
    • >>   mapping_insert +
    • >>   blk_size +
    +
    [Called By]
    • >>   blk_merge_prev +
    • >>   blk_merge_next +
    + +

    blk_search_suitable (Thumb, 104 bytes, Stack size 32 bytes, tos_mmheap.o(i.blk_search_suitable)) +

    [Stack]

    • Max Depth = 56 + Unknown Stack Size +
    • Call Chain = blk_search_suitable ⇒ __ffs ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   __ffs +
    +
    [Called By]
    • >>   blk_locate_free +
    + +

    blk_set_free (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_free)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    • >>   blk_mark_as_free +
    + +

    blk_set_prev_free (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_prev_free)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    • >>   blk_trim_free +
    • >>   blk_mark_as_free +
    + +

    blk_set_prev_used (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_prev_used)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    • >>   blk_mark_as_used +
    + +

    blk_set_size (Thumb, 12 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_size)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    • >>   blk_split +
    + +

    blk_set_used (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_used)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    • >>   blk_mark_as_used +
    + +

    blk_size (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_size)) +

    [Called By]

    • >>   blk_split +
    • >>   blk_remove +
    • >>   blk_next +
    • >>   blk_insert +
    • >>   blk_can_split +
    • >>   blk_absorb +
    + +

    blk_split (Thumb, 62 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_split)) +

    [Stack]

    • Max Depth = 80
    • Call Chain = blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   offset_to_block +
    • >>   blk_to_ptr +
    • >>   blk_size +
    • >>   blk_set_size +
    • >>   blk_mark_as_free +
    +
    [Called By]
    • >>   blk_trim_free +
    + +

    blk_to_ptr (Thumb, 8 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_to_ptr)) +

    [Called By]

    • >>   blk_split +
    • >>   blk_prepare_used +
    • >>   blk_next +
    + +

    blk_trim_free (Thumb, 46 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_trim_free)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   blk_split +
    • >>   blk_set_prev_free +
    • >>   blk_link_next +
    • >>   blk_insert +
    • >>   blk_can_split +
    +
    [Called By]
    • >>   blk_prepare_used +
    + +

    generic_fls (Thumb, 16 bytes, Stack size 8 bytes, tos_mmheap.o(i.generic_fls)) +

    [Stack]

    • Max Depth = 16 + Unknown Stack Size +
    • Call Chain = generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_cpu_clz +
    +
    [Called By]
    • >>   __fls +
    • >>   __ffs +
    + +

    insert_free_block (Thumb, 74 bytes, Stack size 12 bytes, tos_mmheap.o(i.insert_free_block)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = insert_free_block +
    +
    [Called By]
    • >>   blk_insert +
    + +

    mapping_insert (Thumb, 58 bytes, Stack size 24 bytes, tos_mmheap.o(i.mapping_insert)) +

    [Stack]

    • Max Depth = 48 + Unknown Stack Size +
    • Call Chain = mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   __fls +
    +
    [Called By]
    • >>   mapping_search +
    • >>   blk_remove +
    • >>   blk_insert +
    + +

    mapping_search (Thumb, 46 bytes, Stack size 24 bytes, tos_mmheap.o(i.mapping_search)) +

    [Stack]

    • Max Depth = 72 + Unknown Stack Size +
    • Call Chain = mapping_search ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   mapping_insert +
    • >>   __fls +
    +
    [Called By]
    • >>   blk_locate_free +
    + +

    mmheap_ctl_init (Thumb, 88 bytes, Stack size 0 bytes, tos_mmheap.o(i.mmheap_ctl_init)) +

    [Called By]

    • >>   mmheap_init_with_pool +
    + +

    mmheap_pool_is_exist (Thumb, 38 bytes, Stack size 0 bytes, tos_mmheap.o(i.mmheap_pool_is_exist)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    + +

    offset_to_block (Thumb, 6 bytes, Stack size 0 bytes, tos_mmheap.o(i.offset_to_block)) +

    [Called By]

    • >>   tos_mmheap_pool_add +
    • >>   blk_split +
    • >>   blk_next +
    + +

    remove_free_block (Thumb, 92 bytes, Stack size 16 bytes, tos_mmheap.o(i.remove_free_block)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = remove_free_block +
    +
    [Called By]
    • >>   blk_remove +
    • >>   blk_locate_free +
    + +

    mutex_fresh_owner_mark (Thumb, 40 bytes, Stack size 8 bytes, tos_mutex.o(i.mutex_fresh_owner_mark)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = mutex_fresh_owner_mark +
    +
    [Called By]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend_timed +
    + +

    mutex_old_owner_release (Thumb, 74 bytes, Stack size 16 bytes, tos_mutex.o(i.mutex_old_owner_release)) +

    [Stack]

    • Max Depth = 80 + Unknown Stack Size +
    • Call Chain = mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_task_prio_change +
    +
    [Called By]
    • >>   tos_mutex_post +
    • >>   tos_mutex_destroy +
    • >>   mutex_release +
    + +

    pend_list_add (Thumb, 68 bytes, Stack size 16 bytes, tos_pend.o(i.pend_list_add)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = pend_list_add +
    +
    [Called By]
    • >>   pend_task_block +
    • >>   pend_list_adjust +
    + +

    tos_list_del (Thumb, 12 bytes, Stack size 0 bytes, tos_pend.o(i.tos_list_del)) +

    [Called By]

    • >>   pend_list_remove +
    • >>   pend_list_adjust +
    + +

    tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_pend.o(i.tos_list_empty)) +

    [Called By]

    • >>   pend_highest_pending_prio_get +
    • >>   pend_is_nopending +
    + +

    tos_list_init (Thumb, 6 bytes, Stack size 0 bytes, tos_pend.o(i.tos_list_init)) +

    [Called By]

    • >>   pend_object_init +
    • >>   pend_object_deinit +
    + +

    _list_add (Thumb, 10 bytes, Stack size 0 bytes, tos_sched.o(i._list_add)) +

    [Called By]

    • >>   readyqueue_add_head +
    • >>   tos_list_add_tail +
    + +

    _list_del (Thumb, 6 bytes, Stack size 0 bytes, tos_sched.o(i._list_del)) +

    [Called By]

    • >>   readyqueue_remove +
    + +

    readyqueue_prio_highest_get (Thumb, 36 bytes, Stack size 16 bytes, tos_sched.o(i.readyqueue_prio_highest_get)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_cpu_clz +
    +
    [Called By]
    • >>   readyqueue_remove +
    + +

    readyqueue_prio_mark (Thumb, 56 bytes, Stack size 0 bytes, tos_sched.o(i.readyqueue_prio_mark)) +

    [Called By]

    • >>   readyqueue_add_tail +
    • >>   readyqueue_add_head +
    + +

    tos_list_add_tail (Thumb, 18 bytes, Stack size 16 bytes, tos_sched.o(i.tos_list_add_tail)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = tos_list_add_tail +
    +
    [Calls]
    • >>   _list_add +
    +
    [Called By]
    • >>   readyqueue_add_tail +
    + +

    tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_sched.o(i.tos_list_empty)) +

    [Called By]

    • >>   readyqueue_add_tail +
    • >>   readyqueue_add_head +
    • >>   readyqueue_remove +
    + +

    sem_do_post (Thumb, 140 bytes, Stack size 16 bytes, tos_sem.o(i.sem_do_post)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail +
    +
    [Calls]
    • >>   knl_object_verify +
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   pend_is_nopending +
    • >>   knl_sched +
    • >>   pend_wakeup +
    +
    [Called By]
    • >>   tos_sem_post +
    + +

    knl_idle_entry (Thumb, 10 bytes, Stack size 0 bytes, tos_sys.o(i.knl_idle_entry)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = knl_idle_entry ⇒ task_free_all ⇒ task_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   task_free_all +
    +
    [Address Reference Count : 1]
    • tos_sys.o(i.knl_idle_init) +
    +

    task_do_destroy (Thumb, 132 bytes, Stack size 16 bytes, tos_task.o(i.task_do_destroy)) +

    [Stack]

    • Max Depth = 120 + Unknown Stack Size +
    • Call Chain = task_do_destroy ⇒ task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   knl_sched +
    • >>   tick_list_remove +
    • >>   readyqueue_remove +
    • >>   pend_list_remove +
    • >>   tos_list_empty +
    • >>   tos_list_del +
    • >>   task_state_is_ready +
    • >>   task_reset +
    • >>   task_mutex_release +
    • >>   knl_is_idle +
    +
    [Called By]
    • >>   tos_task_destroy +
    + +

    task_exit (Thumb, 10 bytes, Stack size 8 bytes, tos_task.o(i.task_exit)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = task_exit ⇒ tos_task_destroy ⇒ task_do_destroy ⇒ task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_task_destroy +
    +
    [Address Reference Count : 1]
    • tos_task.o(i.tos_task_create) +
    +

    task_free (Thumb, 18 bytes, Stack size 8 bytes, tos_task.o(i.task_free)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = task_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_mmheap_free +
    +
    [Called By]
    • >>   task_free_all +
    + +

    task_highest_pending_prio_get (Thumb, 48 bytes, Stack size 24 bytes, tos_task.o(i.task_highest_pending_prio_get)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = task_highest_pending_prio_get ⇒ pend_highest_pending_prio_get +
    +
    [Calls]
    • >>   pend_highest_pending_prio_get +
    +
    [Called By]
    • >>   tos_task_prio_change +
    + +

    task_mutex_release (Thumb, 32 bytes, Stack size 16 bytes, tos_task.o(i.task_mutex_release)) +

    [Stack]

    • Max Depth = 104 + Unknown Stack Size +
    • Call Chain = task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   mutex_release +
    +
    [Called By]
    • >>   task_do_destroy +
    + +

    task_reset (Thumb, 78 bytes, Stack size 8 bytes, tos_task.o(i.task_reset)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = task_reset +
    +
    [Calls]
    • >>   knl_object_deinit +
    • >>   knl_object_alloc_reset +
    • >>   tos_list_init +
    +
    [Called By]
    • >>   task_do_destroy +
    • >>   tos_task_create +
    + +

    task_state_is_ready (Thumb, 14 bytes, Stack size 0 bytes, tos_task.o(i.task_state_is_ready)) +

    [Called By]

    • >>   tos_task_prio_change +
    • >>   task_do_destroy +
    + +

    tos_list_add (Thumb, 14 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_add)) +

    [Called By]

    • >>   tos_task_create +
    + +

    tos_list_del (Thumb, 12 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_del)) +

    [Called By]

    • >>   task_do_destroy +
    • >>   task_free_all +
    + +

    tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_empty)) +

    [Called By]

    • >>   tos_task_prio_change +
    • >>   task_do_destroy +
    + +

    tos_list_init (Thumb, 6 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_init)) +

    [Called By]

    • >>   task_reset +
    + +

    tick_task_place (Thumb, 184 bytes, Stack size 56 bytes, tos_tick.o(i.tick_task_place)) +

    [Stack]

    • Max Depth = 64 + Unknown Stack Size +
    • Call Chain = tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    +
    [Called By]
    • >>   tick_list_add +
    + +

    tick_task_takeoff (Thumb, 126 bytes, Stack size 16 bytes, tos_tick.o(i.tick_task_takeoff)) +

    [Stack]

    • Max Depth = 24 + Unknown Stack Size +
    • Call Chain = tick_task_takeoff ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    • >>   tos_list_empty +
    +
    [Called By]
    • >>   tick_list_remove +
    + +

    tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_tick.o(i.tos_list_empty)) +

    [Called By]

    • >>   tick_update +
    • >>   tick_task_takeoff +
    + +

    timer_place (Thumb, 130 bytes, Stack size 24 bytes, tos_timer.o(i.timer_place)) +

    [Stack]

    • Max Depth = 32 + Unknown Stack Size +
    • Call Chain = timer_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    +
    [Called By]
    • >>   timer_update +
    + +

    timer_takeoff (Thumb, 110 bytes, Stack size 24 bytes, tos_timer.o(i.timer_takeoff)) +

    [Stack]

    • Max Depth = 32 + Unknown Stack Size +
    • Call Chain = timer_takeoff ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_cpu_cpsr_save +
    • >>   tos_cpu_cpsr_restore +
    +
    [Called By]
    • >>   timer_update +
    + +

    __NVIC_SetPriority (Thumb, 32 bytes, Stack size 8 bytes, port_c.o(i.__NVIC_SetPriority)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = __NVIC_SetPriority +
    +
    [Called By]
    • >>   port_systick_priority_set +
    • >>   port_systick_config +
    + +

    errno_knl2cmsis (Thumb, 12 bytes, Stack size 0 bytes, cmsis_os.o(i.errno_knl2cmsis)) +

    [Called By]

    • >>   osKernelStart +
    • >>   osKernelInitialize +
    + +

    priority_cmsis2knl (Thumb, 18 bytes, Stack size 0 bytes, cmsis_os.o(i.priority_cmsis2knl)) +

    [Called By]

    • >>   osThreadCreate +
    + +

    esp8266_close (Thumb, 28 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_close)) +

    [Stack]

    • Max Depth = 240 + Unknown Stack Size +
    • Call Chain = esp8266_close ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_cmd_exec +
    • >>   tos_at_channel_free +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_connect (Thumb, 100 bytes, Stack size 80 bytes, esp8266.o(i.esp8266_connect)) +

    [Stack]

    • Max Depth = 376 + Unknown Stack Size +
    • Call Chain = esp8266_connect ⇒ esp8266_reconnect_init ⇒ esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_channel_alloc +
    • >>   esp8266_reconnect_init +
    • >>   tos_at_echo_create +
    • >>   tos_at_channel_free +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_echo_close (Thumb, 48 bytes, Stack size 48 bytes, esp8266.o(i.esp8266_echo_close)) +

    [Stack]

    • Max Depth = 280 + Unknown Stack Size +
    • Call Chain = esp8266_echo_close ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Called By]
    • >>   esp8266_reconnect_init +
    • >>   esp8266_init +
    + +

    esp8266_incoming_data_process (Thumb, 132 bytes, Stack size 16 bytes, esp8266.o(i.esp8266_incoming_data_process)) +

    [Stack]

    • Max Depth = 200 + Unknown Stack Size +
    • Call Chain = esp8266_incoming_data_process ⇒ tos_at_uart_read ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_uart_read +
    • >>   tos_at_channel_write +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_init (Thumb, 114 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_init)) +

    [Stack]

    • Max Depth = 304 + Unknown Stack Size +
    • Call Chain = esp8266_init ⇒ esp8266_net_mode_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   esp8266_send_mode_set +
    • >>   esp8266_restore +
    • >>   esp8266_net_mode_set +
    • >>   esp8266_multilink_set +
    • >>   esp8266_echo_close +
    • >>   __2printf +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_is_link_broken (Thumb, 32 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_is_link_broken)) +

    [Stack]

    • Max Depth = 20
    • Call Chain = esp8266_is_link_broken ⇒ strstr +
    +
    [Calls]
    • >>   strstr +
    +
    [Called By]
    • >>   esp8266_sendto +
    • >>   esp8266_send +
    + +

    esp8266_multilink_set (Thumb, 80 bytes, Stack size 56 bytes, esp8266.o(i.esp8266_multilink_set)) +

    [Stack]

    • Max Depth = 288 + Unknown Stack Size +
    • Call Chain = esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Called By]
    • >>   esp8266_reconnect_init +
    • >>   esp8266_init +
    + +

    esp8266_net_mode_set (Thumb, 104 bytes, Stack size 64 bytes, esp8266.o(i.esp8266_net_mode_set)) +

    [Stack]

    • Max Depth = 296 + Unknown Stack Size +
    • Call Chain = esp8266_net_mode_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Called By]
    • >>   esp8266_init +
    + +

    esp8266_parse_domain (Thumb, 102 bytes, Stack size 128 bytes, esp8266.o(i.esp8266_parse_domain)) +

    [Stack]

    • Max Depth = 424 + Unknown Stack Size +
    • Call Chain = esp8266_parse_domain ⇒ esp8266_reconnect_init ⇒ esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   esp8266_reconnect_init +
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    • >>   strstr +
    • >>   __0sscanf +
    • >>   __2printf +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_reconnect_init (Thumb, 44 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_reconnect_init)) +

    [Stack]

    • Max Depth = 296 + Unknown Stack Size +
    • Call Chain = esp8266_reconnect_init ⇒ esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   esp8266_multilink_set +
    • >>   esp8266_echo_close +
    • >>   __2printf +
    +
    [Called By]
    • >>   esp8266_parse_domain +
    • >>   esp8266_connect +
    + +

    esp8266_recv (Thumb, 24 bytes, Stack size 16 bytes, esp8266.o(i.esp8266_recv)) +

    [Stack]

    • Max Depth = 224 + Unknown Stack Size +
    • Call Chain = esp8266_recv ⇒ esp8266_recv_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   esp8266_recv_timeout +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_recv_timeout (Thumb, 28 bytes, Stack size 24 bytes, esp8266.o(i.esp8266_recv_timeout)) +

    [Stack]

    • Max Depth = 208 + Unknown Stack Size +
    • Call Chain = esp8266_recv_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_channel_read_timed +
    +
    [Called By]
    • >>   esp8266_recv +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_recvfrom (Thumb, 24 bytes, Stack size 16 bytes, esp8266.o(i.esp8266_recvfrom)) +

    [Stack]

    • Max Depth = 224 + Unknown Stack Size +
    • Call Chain = esp8266_recvfrom ⇒ esp8266_recvfrom_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   esp8266_recvfrom_timeout +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_recvfrom_timeout (Thumb, 28 bytes, Stack size 24 bytes, esp8266.o(i.esp8266_recvfrom_timeout)) +

    [Stack]

    • Max Depth = 208 + Unknown Stack Size +
    • Call Chain = esp8266_recvfrom_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_channel_read_timed +
    +
    [Called By]
    • >>   esp8266_recvfrom +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_restore (Thumb, 60 bytes, Stack size 56 bytes, esp8266.o(i.esp8266_restore)) +

    [Stack]

    • Max Depth = 288 + Unknown Stack Size +
    • Call Chain = esp8266_restore ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Called By]
    • >>   esp8266_init +
    + +

    esp8266_send (Thumb, 172 bytes, Stack size 128 bytes, esp8266.o(i.esp8266_send)) +

    [Stack]

    • Max Depth = 360 + Unknown Stack Size +
    • Call Chain = esp8266_send ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_channel_set_broken +
    • >>   tos_at_channel_is_working +
    • >>   esp8266_is_link_broken +
    • >>   tos_at_global_lock_post +
    • >>   tos_at_global_lock_pend +
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    esp8266_send_mode_set (Thumb, 72 bytes, Stack size 56 bytes, esp8266.o(i.esp8266_send_mode_set)) +

    [Stack]

    • Max Depth = 288 + Unknown Stack Size +
    • Call Chain = esp8266_send_mode_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Called By]
    • >>   esp8266_init +
    + +

    esp8266_sendto (Thumb, 204 bytes, Stack size 144 bytes, esp8266.o(i.esp8266_sendto)) +

    [Stack]

    • Max Depth = 376 + Unknown Stack Size +
    • Call Chain = esp8266_sendto ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_channel_set_broken +
    • >>   tos_at_channel_is_working +
    • >>   esp8266_is_link_broken +
    • >>   tos_at_global_lock_post +
    • >>   tos_at_global_lock_pend +
    • >>   tos_at_echo_create +
    • >>   tos_at_cmd_exec +
    +
    [Address Reference Count : 1]
    • esp8266.o(.data) +
    +

    at_channel_construct (Thumb, 88 bytes, Stack size 24 bytes, tos_at.o(i.at_channel_construct)) +

    [Stack]

    • Max Depth = 152 + Unknown Stack Size +
    • Call Chain = at_channel_construct ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   tos_mmheap_free +
    • >>   tos_mmheap_alloc +
    • >>   tos_mutex_create +
    • >>   tos_chr_fifo_create +
    +
    [Called By]
    • >>   tos_at_channel_alloc +
    + +

    at_channel_get (Thumb, 52 bytes, Stack size 8 bytes, tos_at.o(i.at_channel_get)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = at_channel_get +
    +
    [Called By]
    • >>   tos_at_channel_set_broken +
    • >>   tos_at_channel_is_working +
    • >>   tos_at_channel_write +
    • >>   tos_at_channel_read_timed +
    • >>   tos_at_channel_free +
    + +

    at_channel_init (Thumb, 58 bytes, Stack size 8 bytes, tos_at.o(i.at_channel_init)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = at_channel_init +
    +
    [Calls]
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   tos_at_init +
    + +

    at_cmd_do_exec (Thumb, 76 bytes, Stack size 24 bytes, tos_at.o(i.at_cmd_do_exec)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend +
    • >>   at_uart_send +
    • >>   vsnprintf +
    • >>   __2printf +
    +
    [Called By]
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_cmd_exec +
    + +

    at_echo_attach (Thumb, 20 bytes, Stack size 0 bytes, tos_at.o(i.at_echo_attach)) +

    [Called By]

    • >>   tos_at_raw_data_send_until +
    • >>   tos_at_cmd_exec_until +
    • >>   tos_at_cmd_exec +
    + +

    at_echo_buffer_copy (Thumb, 74 bytes, Stack size 32 bytes, tos_at.o(i.at_echo_buffer_copy)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = at_echo_buffer_copy ⇒ __aeabi_memcpy +
    +
    [Calls]
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   at_parser +
    + +

    at_echo_status_set (Thumb, 56 bytes, Stack size 16 bytes, tos_at.o(i.at_echo_status_set)) +

    [Stack]

    • Max Depth = 28
    • Call Chain = at_echo_status_set ⇒ strstr +
    +
    [Calls]
    • >>   strstr +
    +
    [Called By]
    • >>   at_parser +
    + +

    at_event_do_get (Thumb, 78 bytes, Stack size 32 bytes, tos_at.o(i.at_event_do_get)) +

    [Stack]

    • Max Depth = 44
    • Call Chain = at_event_do_get ⇒ strncmp +
    +
    [Calls]
    • >>   strncmp +
    • >>   strlen +
    +
    [Called By]
    • >>   at_get_event +
    + +

    at_event_table_set (Thumb, 12 bytes, Stack size 0 bytes, tos_at.o(i.at_event_table_set)) +

    [Called By]

    • >>   tos_at_init +
    + +

    at_get_event (Thumb, 20 bytes, Stack size 16 bytes, tos_at.o(i.at_get_event)) +

    [Stack]

    • Max Depth = 60
    • Call Chain = at_get_event ⇒ at_event_do_get ⇒ strncmp +
    +
    [Calls]
    • >>   at_event_do_get +
    +
    [Called By]
    • >>   at_uart_line_parse +
    • >>   at_parser +
    + +

    at_is_echo_expect (Thumb, 76 bytes, Stack size 32 bytes, tos_at.o(i.at_is_echo_expect)) +

    [Stack]

    • Max Depth = 44
    • Call Chain = at_is_echo_expect ⇒ strncmp +
    +
    [Calls]
    • >>   strncmp +
    • >>   strlen +
    +
    [Called By]
    • >>   at_uart_line_parse +
    + +

    at_parser (Thumb, 114 bytes, Stack size 0 bytes, tos_at.o(i.at_parser)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = at_parser ⇒ at_uart_line_parse ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_sem_post +
    • >>   at_uart_line_parse +
    • >>   at_get_event +
    • >>   at_echo_status_set +
    • >>   at_echo_buffer_copy +
    • >>   __2printf +
    +
    [Address Reference Count : 1]
    • tos_at.o(i.tos_at_init) +
    +

    at_recv_cache_deinit (Thumb, 40 bytes, Stack size 8 bytes, tos_at.o(i.at_recv_cache_deinit)) +

    [Stack]

    • Max Depth = 112 + Unknown Stack Size +
    • Call Chain = at_recv_cache_deinit ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   tos_mmheap_free +
    +
    [Called By]
    • >>   tos_at_init +
    + +

    at_recv_cache_init (Thumb, 52 bytes, Stack size 8 bytes, tos_at.o(i.at_recv_cache_init)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = at_recv_cache_init ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   tos_mmheap_alloc +
    +
    [Called By]
    • >>   tos_at_init +
    + +

    at_uart_getchar (Thumb, 86 bytes, Stack size 24 bytes, tos_at.o(i.at_uart_getchar)) +

    [Stack]

    • Max Depth = 160 + Unknown Stack Size +
    • Call Chain = at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend +
    • >>   tos_chr_fifo_pop +
    • >>   tos_sem_pend +
    • >>   at_delay +
    +
    [Called By]
    • >>   at_uart_line_parse +
    • >>   tos_at_uart_read +
    + +

    at_uart_line_parse (Thumb, 154 bytes, Stack size 24 bytes, tos_at.o(i.at_uart_line_parse)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = at_uart_line_parse ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   at_uart_getchar +
    • >>   at_is_echo_expect +
    • >>   at_get_event +
    • >>   __aeabi_memclr +
    +
    [Called By]
    • >>   at_parser +
    + +

    at_uart_send (Thumb, 44 bytes, Stack size 24 bytes, tos_at.o(i.at_uart_send)) +

    [Stack]

    • Max Depth = 160 + Unknown Stack Size +
    • Call Chain = at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   tos_mutex_post +
    • >>   tos_mutex_pend +
    • >>   tos_hal_uart_write +
    +
    [Called By]
    • >>   at_cmd_do_exec +
    • >>   tos_at_raw_data_send_until +
    + +

    _offline_subs_list_deinit (Thumb, 30 bytes, Stack size 8 bytes, mqtt_api.o(i._offline_subs_list_deinit)) +

    [Stack]

    • Max Depth = 136 + Unknown Stack Size +
    • Call Chain = _offline_subs_list_deinit ⇒ HAL_MutexDestroy ⇒ HAL_Free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz +
    +
    [Calls]
    • >>   HAL_MutexDestroy +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   iotx_mqtt_deal_offline_subs +
    + +

    _offline_subs_list_init (Thumb, 40 bytes, Stack size 8 bytes, mqtt_api.o(i._offline_subs_list_init)) +

    [Stack]

    • Max Depth = 152 + Unknown Stack Size +
    • Call Chain = _offline_subs_list_init ⇒ HAL_MutexCreate ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   HAL_MutexCreate +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   iotx_mqtt_offline_subscribe +
    + +

    iotx_mqtt_deal_offline_subs (Thumb, 144 bytes, Stack size 24 bytes, mqtt_api.o(i.iotx_mqtt_deal_offline_subs)) +

    [Stack]

    • Max Depth = 328 + Unknown Stack Size +
    • Call Chain = iotx_mqtt_deal_offline_subs ⇒ wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   wrapper_mqtt_subscribe +
    • >>   _offline_subs_list_deinit +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    +
    [Called By]
    • >>   iotx_mqtt_report_funcs +
    + +

    iotx_mqtt_offline_subscribe (Thumb, 362 bytes, Stack size 32 bytes, mqtt_api.o(i.iotx_mqtt_offline_subscribe)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = iotx_mqtt_offline_subscribe ⇒ _offline_subs_list_init ⇒ HAL_MutexCreate ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next +
    +
    [Calls]
    • >>   _offline_subs_list_init +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   memcmp +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   IOT_MQTT_Subscribe +
    + +

    iotx_mqtt_report_funcs (Thumb, 100 bytes, Stack size 16 bytes, mqtt_api.o(i.iotx_mqtt_report_funcs)) +

    [Stack]

    • Max Depth = 472 + Unknown Stack Size +
    • Call Chain = iotx_mqtt_report_funcs ⇒ iotx_report_firmware_version ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   iotx_set_report_func +
    • >>   iotx_report_mid +
    • >>   iotx_report_firmware_version +
    • >>   iotx_report_devinfo +
    • >>   LITE_syslog +
    • >>   iotx_mqtt_deal_offline_subs +
    +
    [Called By]
    • >>   IOT_MQTT_Construct +
    + +

    MQTTDisconnect (Thumb, 120 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.MQTTDisconnect)) +

    [Stack]

    • Max Depth = 176 + Unknown Stack Size +
    • Call Chain = MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   _reset_send_buffer +
    • >>   _alloc_send_buffer +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    • >>   MQTTSerialize_disconnect +
    +
    [Called By]
    • >>   iotx_mc_disconnect +
    + +

    MQTTKeepalive (Thumb, 226 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.MQTTKeepalive)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = MQTTKeepalive ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   _reset_send_buffer +
    • >>   _alloc_send_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    • >>   MQTTSerialize_pingreq +
    +
    [Called By]
    • >>   iotx_mc_keepalive_sub +
    + +

    MQTTPubInfoProc (Thumb, 226 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.MQTTPubInfoProc)) +

    [Stack]

    • Max Depth = 200 + Unknown Stack Size +
    • Call Chain = MQTTPubInfoProc ⇒ MQTTRePublish ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_get_client_state +
    • >>   MQTTRePublish +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_spend +
    • >>   iotx_time_start +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   _mqtt_cycle +
    + +

    MQTTPuback (Thumb, 206 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.MQTTPuback)) +

    [Stack]

    • Max Depth = 184 + Unknown Stack Size +
    • Call Chain = MQTTPuback ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   _reset_send_buffer +
    • >>   _alloc_send_buffer +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    • >>   MQTTSerialize_ack +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_PUBLISH +
    + +

    MQTTRePublish (Thumb, 76 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.MQTTRePublish)) +

    [Stack]

    • Max Depth = 176 + Unknown Stack Size +
    • Call Chain = MQTTRePublish ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    +
    [Called By]
    • >>   MQTTPubInfoProc +
    + +

    MQTTSubscribe (Thumb, 610 bytes, Stack size 80 bytes, iotx_mqtt_client.o(i.MQTTSubscribe)) +

    [Stack]

    • Max Depth = 232 + Unknown Stack Size +
    • Call Chain = MQTTSubscribe ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_send_packet +
    • >>   iotx_mc_check_handle_is_identical +
    • >>   _reset_send_buffer +
    • >>   _alloc_send_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    • >>   MQTTSerialize_subscribe +
    • >>   strlen +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   wrapper_mqtt_subscribe +
    + +

    _alloc_recv_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._alloc_recv_buffer)) +

    [Called By]

    • >>   iotx_mc_read_packet +
    + +

    _alloc_send_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._alloc_send_buffer)) +

    [Called By]

    • >>   MQTTSubscribe +
    • >>   MQTTPuback +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    _get_connect_length (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._get_connect_length)) +

    [Called By]

    • >>   MQTTConnect +
    + +

    _handle_event (Thumb, 46 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i._handle_event)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = _handle_event +
    +
    [Called By]
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_handle_recv_UNSUBACK +
    • >>   iotx_mc_handle_recv_SUBACK +
    • >>   iotx_mc_handle_recv_PUBACK +
    • >>   iotx_mc_deliver_message +
    + +

    _iotx_mqtt_event_handle_sub (Thumb, 118 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i._iotx_mqtt_event_handle_sub)) +

    [Stack]

    • Max Depth = 192 + Unknown Stack Size +
    • Call Chain = _iotx_mqtt_event_handle_sub ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_SUBACK +
    + +

    _mqtt_connect (Thumb, 396 bytes, Stack size 48 bytes, iotx_mqtt_client.o(i._mqtt_connect)) +

    [Stack]

    • Max Depth = 800 + Unknown Stack Size +
    • Call Chain = _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_set_client_state +
    • >>   LITE_syslog +
    • >>   HAL_SleepMs +
    • >>   utils_time_countdown_ms +
    • >>   MQTTConnect +
    +
    [Called By]
    • >>   wrapper_mqtt_connect +
    + +

    _reset_recv_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._reset_recv_buffer)) +

    [Called By]

    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_cycle +
    + +

    _reset_send_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._reset_send_buffer)) +

    [Called By]

    • >>   MQTTSubscribe +
    • >>   MQTTPuback +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    iotx_mc_attempt_reconnect (Thumb, 116 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_attempt_reconnect)) +

    [Stack]

    • Max Depth = 880 + Unknown Stack Size +
    • Call Chain = iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   wrapper_mqtt_connect +
    • >>   LITE_syslog +
    +
    [Called By]
    • >>   iotx_mc_handle_reconnect +
    + +

    iotx_mc_check_handle_is_identical (Thumb, 48 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_check_handle_is_identical)) +

    [Stack]

    • Max Depth = 44
    • Call Chain = iotx_mc_check_handle_is_identical ⇒ iotx_mc_check_handle_is_identical_ex ⇒ strncmp +
    +
    [Calls]
    • >>   iotx_mc_check_handle_is_identical_ex +
    +
    [Called By]
    • >>   MQTTSubscribe +
    + +

    iotx_mc_check_handle_is_identical_ex (Thumb, 82 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_check_handle_is_identical_ex)) +

    [Stack]

    • Max Depth = 28
    • Call Chain = iotx_mc_check_handle_is_identical_ex ⇒ strncmp +
    +
    [Calls]
    • >>   strncmp +
    • >>   strlen +
    +
    [Called By]
    • >>   iotx_mc_check_handle_is_identical +
    + +

    iotx_mc_check_rule (Thumb, 154 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_check_rule)) +

    [Stack]

    • Max Depth = 152
    • Call Chain = iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   strlen +
    +
    [Called By]
    • >>   iotx_mc_check_topic +
    + +

    iotx_mc_check_topic (Thumb, 228 bytes, Stack size 88 bytes, iotx_mqtt_client.o(i.iotx_mc_check_topic)) +

    [Stack]

    • Max Depth = 240
    • Call Chain = iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   iotx_mc_check_rule +
    • >>   LITE_syslog +
    • >>   infra_strtok +
    • >>   strlen +
    • >>   strncpy +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   wrapper_mqtt_subscribe +
    • >>   wrapper_mqtt_publish +
    + +

    iotx_mc_cycle (Thumb, 562 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_cycle)) +

    [Stack]

    • Max Depth = 752 + Unknown Stack Size +
    • Call Chain = iotx_mc_cycle ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_handle_recv_UNSUBACK +
    • >>   iotx_mc_handle_recv_SUBACK +
    • >>   iotx_mc_handle_recv_PUBLISH +
    • >>   iotx_mc_handle_recv_PUBACK +
    • >>   iotx_mc_get_client_state +
    • >>   _reset_recv_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    +
    [Called By]
    • >>   _mqtt_cycle +
    + +

    iotx_mc_decode_packet (Thumb, 140 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.iotx_mc_decode_packet)) +

    [Stack]

    • Max Depth = 40
    • Call Chain = iotx_mc_decode_packet +
    +
    [Called By]
    • >>   iotx_mc_read_packet +
    + +

    iotx_mc_deliver_message (Thumb, 268 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.iotx_mc_deliver_message)) +

    [Stack]

    • Max Depth = 192 + Unknown Stack Size +
    • Call Chain = iotx_mc_deliver_message ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_is_topic_matched +
    • >>   _handle_event +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   MQTTPacket_equals +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_PUBLISH +
    + +

    iotx_mc_disconnect (Thumb, 94 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_disconnect)) +

    [Stack]

    • Max Depth = 200 + Unknown Stack Size +
    • Call Chain = iotx_mc_disconnect ⇒ MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   MQTTDisconnect +
    • >>   wrapper_mqtt_check_state +
    • >>   LITE_syslog +
    +
    [Called By]
    • >>   wrapper_mqtt_release +
    + +

    iotx_mc_disconnect_callback (Thumb, 46 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_disconnect_callback)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = iotx_mc_disconnect_callback +
    +
    [Called By]
    • >>   iotx_mc_keepalive +
    + +

    iotx_mc_get_client_state (Thumb, 24 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_get_client_state)) +

    [Stack]

    • Max Depth = 168 + Unknown Stack Size +
    • Call Chain = iotx_mc_get_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    +
    [Called By]
    • >>   iotx_mc_keepalive +
    • >>   iotx_mc_cycle +
    • >>   MQTTPubInfoProc +
    • >>   wrapper_mqtt_subscribe +
    • >>   wrapper_mqtt_publish +
    • >>   wrapper_mqtt_check_state +
    + +

    iotx_mc_get_next_packetid (Thumb, 50 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_get_next_packetid)) +

    [Stack]

    • Max Depth = 168 + Unknown Stack Size +
    • Call Chain = iotx_mc_get_next_packetid ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    +
    [Called By]
    • >>   wrapper_mqtt_subscribe +
    • >>   wrapper_mqtt_publish +
    + +

    iotx_mc_handle_reconnect (Thumb, 196 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_reconnect)) +

    [Stack]

    • Max Depth = 904 + Unknown Stack Size +
    • Call Chain = iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_attempt_reconnect +
    • >>   LITE_syslog +
    • >>   HAL_SleepMs +
    • >>   utils_time_is_expired +
    • >>   utils_time_countdown_ms +
    +
    [Called By]
    • >>   iotx_mc_keepalive +
    + +

    iotx_mc_handle_recv_CONNACK (Thumb, 126 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_CONNACK)) +

    [Stack]

    • Max Depth = 152
    • Call Chain = iotx_mc_handle_recv_CONNACK ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   MQTTDeserialize_connack +
    +
    [Called By]
    • >>   iotx_mc_wait_CONNACK +
    + +

    iotx_mc_handle_recv_PUBACK (Thumb, 98 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_PUBACK)) +

    [Stack]

    • Max Depth = 128
    • Call Chain = iotx_mc_handle_recv_PUBACK ⇒ MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   iotx_mc_mask_pubInfo_from +
    • >>   _handle_event +
    • >>   MQTTDeserialize_ack +
    +
    [Called By]
    • >>   iotx_mc_cycle +
    + +

    iotx_mc_handle_recv_PUBLISH (Thumb, 404 bytes, Stack size 72 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_PUBLISH)) +

    [Stack]

    • Max Depth = 264 + Unknown Stack Size +
    • Call Chain = iotx_mc_handle_recv_PUBLISH ⇒ iotx_mc_deliver_message ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_deliver_message +
    • >>   MQTTPuback +
    • >>   LITE_syslog +
    • >>   MQTTDeserialize_publish +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   iotx_mc_cycle +
    + +

    iotx_mc_handle_recv_SUBACK (Thumb, 322 bytes, Stack size 80 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_SUBACK)) +

    [Stack]

    • Max Depth = 272 + Unknown Stack Size +
    • Call Chain = iotx_mc_handle_recv_SUBACK ⇒ _iotx_mqtt_event_handle_sub ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   _iotx_mqtt_event_handle_sub +
    • >>   _handle_event +
    • >>   LITE_syslog +
    • >>   MQTTDeserialize_suback +
    +
    [Called By]
    • >>   iotx_mc_cycle +
    + +

    iotx_mc_handle_recv_UNSUBACK (Thumb, 76 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_UNSUBACK)) +

    [Stack]

    • Max Depth = 152
    • Call Chain = iotx_mc_handle_recv_UNSUBACK ⇒ MQTTDeserialize_unsuback ⇒ MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode +
    +
    [Calls]
    • >>   _handle_event +
    • >>   MQTTDeserialize_unsuback +
    +
    [Called By]
    • >>   iotx_mc_cycle +
    + +

    iotx_mc_init (Thumb, 452 bytes, Stack size 112 bytes, iotx_mqtt_client.o(i.iotx_mc_init)) +

    [Stack]

    • Max Depth = 280 + Unknown Stack Size +
    • Call Chain = iotx_mc_init ⇒ iotx_mc_set_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_connect_params +
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_pub_wait_list_init +
    • >>   LITE_syslog +
    • >>   HAL_MutexDestroy +
    • >>   HAL_MutexCreate +
    • >>   iotx_time_init +
    • >>   iotx_net_init +
    • >>   __aeabi_memclr4 +
    • >>   __aeabi_memcpy4 +
    +
    [Called By]
    • >>   wrapper_mqtt_init +
    + +

    iotx_mc_is_topic_matched (Thumb, 126 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_is_topic_matched)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = iotx_mc_is_topic_matched +
    +
    [Called By]
    • >>   iotx_mc_deliver_message +
    + +

    iotx_mc_keepalive (Thumb, 206 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_keepalive)) +

    [Stack]

    • Max Depth = 928 + Unknown Stack Size +
    • Call Chain = iotx_mc_keepalive ⇒ iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   iotx_mc_reconnect_callback +
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_handle_reconnect +
    • >>   iotx_mc_get_client_state +
    • >>   iotx_mc_disconnect_callback +
    • >>   LITE_syslog +
    • >>   utils_time_countdown_ms +
    +
    [Called By]
    • >>   wrapper_mqtt_yield +
    + +

    iotx_mc_keepalive_sub (Thumb, 148 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_keepalive_sub)) +

    [Stack]

    • Max Depth = 208 + Unknown Stack Size +
    • Call Chain = iotx_mc_keepalive_sub ⇒ MQTTKeepalive ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_set_client_state +
    • >>   MQTTKeepalive +
    • >>   wrapper_mqtt_check_state +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_is_expired +
    • >>   utils_time_countdown_ms +
    +
    [Called By]
    • >>   iotx_mc_keepalive +
    + +

    iotx_mc_mask_pubInfo_from (Thumb, 72 bytes, Stack size 12 bytes, iotx_mqtt_client.o(i.iotx_mc_mask_pubInfo_from)) +

    [Stack]

    • Max Depth = 12
    • Call Chain = iotx_mc_mask_pubInfo_from +
    +
    [Called By]
    • >>   iotx_mc_handle_recv_PUBACK +
    + +

    iotx_mc_pub_wait_list_deinit (Thumb, 18 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.iotx_mc_pub_wait_list_deinit)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = iotx_mc_pub_wait_list_deinit +
    +
    [Calls]
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   wrapper_mqtt_release +
    + +

    iotx_mc_pub_wait_list_init (Thumb, 18 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.iotx_mc_pub_wait_list_init)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = iotx_mc_pub_wait_list_init +
    +
    [Calls]
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   iotx_mc_init +
    + +

    iotx_mc_push_pubInfo_to (Thumb, 286 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.iotx_mc_push_pubInfo_to)) +

    [Stack]

    • Max Depth = 168 + Unknown Stack Size +
    • Call Chain = iotx_mc_push_pubInfo_to ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   iotx_time_start +
    • >>   __aeabi_memcpy +
    +
    [Called By]
    • >>   MQTTPublish +
    + +

    iotx_mc_read_packet (Thumb, 892 bytes, Stack size 568 bytes, iotx_mqtt_client.o(i.iotx_mc_read_packet)) +

    [Stack]

    • Max Depth = 720 + Unknown Stack Size +
    • Call Chain = iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_decode_packet +
    • >>   _handle_event +
    • >>   _alloc_recv_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   iotx_time_left +
    • >>   MQTTPacket_encode +
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   iotx_mc_wait_CONNACK +
    • >>   iotx_mc_cycle +
    + +

    iotx_mc_reconnect_callback (Thumb, 46 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_reconnect_callback)) +

    [Stack]

    • Max Depth = 16
    • Call Chain = iotx_mc_reconnect_callback +
    +
    [Called By]
    • >>   iotx_mc_keepalive +
    + +

    iotx_mc_release (Thumb, 16 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.iotx_mc_release)) +

    [Stack]

    • Max Depth = 8
    • Call Chain = iotx_mc_release +
    +
    [Calls]
    • >>   __aeabi_memclr4 +
    +
    [Called By]
    • >>   wrapper_mqtt_init +
    + +

    iotx_mc_send_packet (Thumb, 126 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_send_packet)) +

    [Stack]

    • Max Depth = 96 + Unknown Stack Size +
    • Call Chain = iotx_mc_send_packet ⇒ iotx_time_left ⇒ utils_time_is_expired ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   utils_time_is_expired +
    • >>   iotx_time_left +
    +
    [Called By]
    • >>   MQTTSubscribe +
    • >>   MQTTRePublish +
    • >>   MQTTPuback +
    • >>   MQTTKeepalive +
    • >>   MQTTDisconnect +
    • >>   MQTTPublish +
    • >>   MQTTConnect +
    + +

    iotx_mc_set_client_state (Thumb, 24 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_set_client_state)) +

    [Stack]

    • Max Depth = 168 + Unknown Stack Size +
    • Call Chain = iotx_mc_set_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    +
    [Called By]
    • >>   iotx_mc_keepalive_sub +
    • >>   iotx_mc_keepalive +
    • >>   iotx_mc_init +
    • >>   iotx_mc_handle_reconnect +
    • >>   iotx_mc_disconnect +
    • >>   iotx_mc_cycle +
    • >>   _mqtt_connect +
    • >>   MQTTPubInfoProc +
    • >>   wrapper_mqtt_subscribe +
    • >>   wrapper_mqtt_release +
    • >>   wrapper_mqtt_publish +
    + +

    iotx_mc_set_connect_params (Thumb, 300 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_set_connect_params)) +

    [Stack]

    • Max Depth = 152
    • Call Chain = iotx_mc_set_connect_params ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    +
    [Called By]
    • >>   iotx_mc_init +
    + +

    iotx_mc_wait_CONNACK (Thumb, 226 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_wait_CONNACK)) +

    [Stack]

    • Max Depth = 752 + Unknown Stack Size +
    • Call Chain = iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save +
    +
    [Calls]
    • >>   iotx_mc_read_packet +
    • >>   iotx_mc_handle_recv_CONNACK +
    • >>   _reset_recv_buffer +
    • >>   LITE_syslog +
    • >>   HAL_MutexUnlock +
    • >>   HAL_MutexLock +
    • >>   utils_time_countdown_ms +
    • >>   iotx_time_init +
    +
    [Called By]
    • >>   _mqtt_connect +
    + +

    connect_tcp (Thumb, 52 bytes, Stack size 16 bytes, infra_net.o(i.connect_tcp)) +

    [Stack]

    • Max Depth = 144
    • Call Chain = connect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   HAL_TCP_Establish +
    +
    [Called By]
    • >>   iotx_net_connect +
    + +

    disconnect_tcp (Thumb, 48 bytes, Stack size 16 bytes, infra_net.o(i.disconnect_tcp)) +

    [Stack]

    • Max Depth = 144
    • Call Chain = disconnect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf +
    +
    [Calls]
    • >>   LITE_syslog +
    • >>   HAL_TCP_Destroy +
    +
    [Called By]
    • >>   iotx_net_disconnect +
    + +

    read_tcp (Thumb, 28 bytes, Stack size 24 bytes, infra_net.o(i.read_tcp)) +

    [Stack]

    • Max Depth = 72
    • Call Chain = read_tcp ⇒ HAL_TCP_Read ⇒ tos_sal_module_recv_timeout +
    +
    [Calls]
    • >>   HAL_TCP_Read +
    +
    [Called By]
    • >>   utils_net_read +
    + +

    write_tcp (Thumb, 28 bytes, Stack size 24 bytes, infra_net.o(i.write_tcp)) +

    [Stack]

    • Max Depth = 64
    • Call Chain = write_tcp ⇒ HAL_TCP_Write ⇒ tos_sal_module_send +
    +
    [Calls]
    • >>   HAL_TCP_Write +
    +
    [Called By]
    • >>   utils_net_write +
    + +

    _hex2str (Thumb, 58 bytes, Stack size 20 bytes, dev_sign_mqtt.o(i._hex2str)) +

    [Stack]

    • Max Depth = 20
    • Call Chain = _hex2str +
    +
    [Called By]
    • >>   _iotx_generate_sign_string +
    + +

    _fp_digits (Thumb, 366 bytes, Stack size 64 bytes, printfa.o(i._fp_digits), UNUSED) +

    [Calls]

    • >>   __aeabi_ddiv +
    • >>   __aeabi_uldivmod +
    • >>   __aeabi_dmul +
    • >>   __aeabi_dadd +
    • >>   __aeabi_d2ulz +
    • >>   __aeabi_cdrcmple +
    +
    [Called By]
    • >>   _printf_core +
    + +

    _printf_core (Thumb, 1744 bytes, Stack size 136 bytes, printfa.o(i._printf_core), UNUSED) +

    [Calls]

    • >>   __aeabi_uldivmod +
    • >>   __aeabi_uidivmod +
    • >>   _printf_pre_padding +
    • >>   _printf_post_padding +
    • >>   _fp_digits +
    +
    [Called By]
    • >>   __0vsnprintf +
    • >>   __0vprintf +
    • >>   __0snprintf +
    • >>   __0printf +
    + +

    _printf_post_padding (Thumb, 36 bytes, Stack size 24 bytes, printfa.o(i._printf_post_padding), UNUSED) +

    [Called By]

    • >>   _printf_core +
    + +

    _printf_pre_padding (Thumb, 46 bytes, Stack size 24 bytes, printfa.o(i._printf_pre_padding), UNUSED) +

    [Called By]

    • >>   _printf_core +
    + +

    _snputc (Thumb, 22 bytes, Stack size 0 bytes, printfa.o(i._snputc)) +
    [Address Reference Count : 2]

    • printfa.o(i.__0snprintf) +
    • printfa.o(i.__0vsnprintf) +
    +

    _scanf_char_input (Thumb, 12 bytes, Stack size 0 bytes, scanf_char.o(.text)) +
    [Address Reference Count : 1]

    • scanf_char.o(.text) +

    +

    +Undefined Global Symbols +


    diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.sct b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.sct new file mode 100644 index 00000000..66acf7f8 --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.sct @@ -0,0 +1,16 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + .ANY (+XO) + } + RW_IRAM1 0x20000000 0x00010000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/startup_stm32l431xx.s b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/startup_stm32l431xx.s new file mode 100644 index 00000000..6a5c15a5 --- /dev/null +++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/startup_stm32l431xx.s @@ -0,0 +1,404 @@ +;********************** COPYRIGHT(c) 2017 STMicroelectronics ****************** +;* File Name : startup_stm32l431xx.s +;* Author : MCD Application Team +;* Description : STM32L431xx Ultra Low Power devices vector table for MDK-ARM toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the Cortex-M4 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;* <<< Use Configuration Wizard in Context Menu >>> +;******************************************************************************* +;* +;* Redistribution and use in source and binary forms, with or without modification, +;* are permitted provided that the following conditions are met: +;* 1. Redistributions of source code must retain the above copyright notice, +;* this list of conditions and the following disclaimer. +;* 2. Redistributions in binary form must reproduce the above copyright notice, +;* this list of conditions and the following disclaimer in the documentation +;* and/or other materials provided with the distribution. +;* 3. Neither the name of STMicroelectronics nor the names of its contributors +;* may be used to endorse or promote products derived from this software +;* without specific prior written permission. +;* +;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;* +;******************************************************************************* +; +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x100 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x100 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window WatchDog + DCD PVD_PVM_IRQHandler ; PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection + DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line + DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line + DCD FLASH_IRQHandler ; FLASH + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line0 + DCD EXTI1_IRQHandler ; EXTI Line1 + DCD EXTI2_IRQHandler ; EXTI Line2 + DCD EXTI3_IRQHandler ; EXTI Line3 + DCD EXTI4_IRQHandler ; EXTI Line4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_IRQHandler ; ADC1 + DCD CAN1_TX_IRQHandler ; CAN1 TX + DCD CAN1_RX0_IRQHandler ; CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; External Line[9:5]s + DCD TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15 + DCD TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16 + DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; External Line[15:10] + DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SDMMC1_IRQHandler ; SDMMC1 + DCD 0 ; Reserved + DCD SPI3_IRQHandler ; SPI3 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel 1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel 2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel 3 + DCD DMA2_Channel4_IRQHandler ; DMA2 Channel 4 + DCD DMA2_Channel5_IRQHandler ; DMA2 Channel 5 + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD COMP_IRQHandler ; COMP Interrupt + DCD LPTIM1_IRQHandler ; LP TIM1 interrupt + DCD LPTIM2_IRQHandler ; LP TIM2 interrupt + DCD 0 ; Reserved + DCD DMA2_Channel6_IRQHandler ; DMA2 Channel 6 + DCD DMA2_Channel7_IRQHandler ; DMA2 Channel 7 + DCD LPUART1_IRQHandler ; LP UART1 interrupt + DCD QUADSPI_IRQHandler ; Quad SPI global interrupt + DCD I2C3_EV_IRQHandler ; I2C3 event + DCD I2C3_ER_IRQHandler ; I2C3 error + DCD SAI1_IRQHandler ; Serial Audio Interface 1 global interrupt + DCD 0 ; Reserved + DCD SWPMI1_IRQHandler ; Serial Wire Interface 1 global interrupt + DCD TSC_IRQHandler ; Touch Sense Controller global interrupt + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD RNG_IRQHandler ; RNG global interrupt + DCD FPU_IRQHandler ; FPU + DCD CRS_IRQHandler ; CRS interrupt + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_PVM_IRQHandler [WEAK] + EXPORT TAMP_STAMP_IRQHandler [WEAK] + EXPORT RTC_WKUP_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM15_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM16_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT SDMMC1_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT TIM6_DAC_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Channel1_IRQHandler [WEAK] + EXPORT DMA2_Channel2_IRQHandler [WEAK] + EXPORT DMA2_Channel3_IRQHandler [WEAK] + EXPORT DMA2_Channel4_IRQHandler [WEAK] + EXPORT DMA2_Channel5_IRQHandler [WEAK] + EXPORT COMP_IRQHandler [WEAK] + EXPORT LPTIM1_IRQHandler [WEAK] + EXPORT LPTIM2_IRQHandler [WEAK] + EXPORT DMA2_Channel6_IRQHandler [WEAK] + EXPORT DMA2_Channel7_IRQHandler [WEAK] + EXPORT LPUART1_IRQHandler [WEAK] + EXPORT QUADSPI_IRQHandler [WEAK] + EXPORT I2C3_EV_IRQHandler [WEAK] + EXPORT I2C3_ER_IRQHandler [WEAK] + EXPORT SAI1_IRQHandler [WEAK] + EXPORT SWPMI1_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT RNG_IRQHandler [WEAK] + EXPORT FPU_IRQHandler [WEAK] + EXPORT CRS_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_PVM_IRQHandler +TAMP_STAMP_IRQHandler +RTC_WKUP_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM15_IRQHandler +TIM1_UP_TIM16_IRQHandler +TIM1_TRG_COM_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTC_Alarm_IRQHandler +SDMMC1_IRQHandler +SPI3_IRQHandler +TIM6_DAC_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_IRQHandler +DMA2_Channel5_IRQHandler +COMP_IRQHandler +LPTIM1_IRQHandler +LPTIM2_IRQHandler +DMA2_Channel6_IRQHandler +DMA2_Channel7_IRQHandler +LPUART1_IRQHandler +QUADSPI_IRQHandler +I2C3_EV_IRQHandler +I2C3_ER_IRQHandler +SAI1_IRQHandler +SWPMI1_IRQHandler +TSC_IRQHandler +RNG_IRQHandler +FPU_IRQHandler +CRS_IRQHandler + + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + +;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE***** diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/.gitignore b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/.gitignore new file mode 100644 index 00000000..32f060b5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/.gitignore @@ -0,0 +1,32 @@ +.settings/ +*.cproject +*.project +*.o +*.d +*.lo +*.gcno +*.gcda +/INSTALL +cscope.* +*.swp +*.swo +ltmain.sh +*.kv +*.bak +/Default/ +.O/ +.config +output/ +ota.bin +src/packages/*.git/hooks/*.sample +vs_build/ +.vs/ +doc/html/ +compile.log +CMakeLists.txt.user +qt_build/ +.vscode/ +GPATH +GRTAGS +GTAGS +iotx-sdk-c-test/ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/LICENSE b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/LICENSE new file mode 100644 index 00000000..57bc88a1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/README.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/README.md new file mode 100644 index 00000000..dbe1b157 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/README.md @@ -0,0 +1,26 @@ +# 用户手册 + +https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/Linkkit_User_Manual + +# C-SDK 简介 + +è®¾å¤‡åŽ‚å•†åœ¨è®¾å¤‡ä¸Šé›†æˆ `C-SDK` åŽ, å¯ä»¥å°†è®¾å¤‡å®‰å…¨çš„æŽ¥å…¥åˆ°é˜¿é‡Œäº‘IoT物è”网平å°, 从而使设备å¯ä»¥è¢«é˜¿é‡Œäº‘IoT物è”网平å°è¿›è¡Œç®¡ç† + +è®¾å¤‡éœ€è¦æ”¯æŒTCP/IPå议栈或串å£é€šä¿¡, 以åŠC99标准的C库æ‰èƒ½é›†æˆSDK, zigbee/433/KNX这样的éžIP设备需è¦é€šè¿‡ç½‘关设备接入到阿里云IoT物è”网平å°, 网关设备需è¦é›†æˆC-SDK + + +# 快速开始 + +用户å¯ä»¥é€šè¿‡[快速的体验C-SDK](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Quick_Start)感å—如何将设备连接到阿里云物è”网平å°, 并如何将设备的数æ®å‘é€åˆ°å¹³å°/以åŠå¦‚何从物è”ç½‘å¹³å°æŽ¥æ”¶æ•°æ® + + +# ç§»æ¤è¯´æ˜Ž +C-SDK与OS/ç¡¬ä»¶å¹³å°æ— å…³, 全部部分用C编写, 它定义了HAL层æ¥å¯¹æŽ¥ä¸Žç¡¬ä»¶ç›¸å…³çš„功能, 因此在使用C-SDK时用户需è¦åŽ»å®žçŽ°ç›¸å…³çš„HAL函数 + +ç›®å‰C-SDK已实现了在Linux/Windows/AliOS上HAL的实现, åŒæ—¶å¯¹äºŽä¸€äº›å¸¸è§çš„OS或者模组也进行了适é…, å¯ä»¥[访问此处](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Port_Guide/Porting_Overview)查看如何在相应平å°ä¸Šè¿›è¡ŒSDKçš„ç¼–è¯‘ä¸Žé›†æˆ + + +# 编程文档 + +SDKæä¾›äº†ä¸€ç³»åˆ—çš„ç¼–ç¨‹æ–‡æ¡£æ¥æè¿°å¦‚ä½•ä½¿ç”¨SDKæä¾›çš„软件功能, 请[访问此处](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/Linkkit_User_Manual)进行了解 + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/iot.mk new file mode 100644 index 00000000..48d6a9c6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/iot.mk @@ -0,0 +1 @@ +LIBA_TARGET := libiot_cert.a diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/root_ca.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/root_ca.c new file mode 100644 index 00000000..4881a944 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/root_ca.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include + +const char *iotx_ca_crt = \ +{ + \ + "-----BEGIN CERTIFICATE-----\r\n" + "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" \ + "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" \ + "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n" \ + "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n" \ + "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n" \ + "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n" \ + "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n" \ + "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n" \ + "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n" \ + "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n" \ + "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n" \ + "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n" \ + "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n" \ + "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n" \ + "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n" \ + "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n" \ + "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n" \ + "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n" \ + "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \ + "-----END CERTIFICATE-----" +}; diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/config.bat b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/config.bat new file mode 100644 index 00000000..944b58ef --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/.gitignore b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/.gitignore new file mode 100644 index 00000000..bf67d02e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/.gitignore @@ -0,0 +1,4 @@ +Makefile +*.sln +*.vcxproj +mbedtls/check_config diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/aes.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/aes.h new file mode 100644 index 00000000..115db985 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/aes.h @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 +#define MBEDTLS_AES_DECRYPT 0 + +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_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(MBEDTLS_AES_ALT) +// Regular implementation +// + +#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 */ +} +mbedtls_aes_context; + +/** + * \brief Initialize AES context + * + * \param ctx AES context to be initialized + */ +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); + +/** + * \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 MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aes_setkey_enc(mbedtls_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 MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +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) +/** + * \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 MBEDTLS_AES_ENCRYPT or MBEDTLS_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 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); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_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 + * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_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 MBEDTLS_AES_ENCRYPT or MBEDTLS_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 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. + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_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 MBEDTLS_AES_ENCRYPT or MBEDTLS_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 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) +/** + * \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 + * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_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 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 */ + +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see MBEDTLS_AES_ENCRYPT_ALT) + * + * \param ctx AES context + * \param input Plaintext block + * \param output Output (ciphertext) block + * + * \return 0 if successful + */ +int mbedtls_internal_aes_encrypt(mbedtls_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 MBEDTLS_AES_DECRYPT_ALT) + * + * \param ctx AES context + * \param input Ciphertext block + * \param output Output (plaintext) block + * + * \return 0 if successful + */ +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) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see MBEDTLS_AES_ENCRYPT_ALT) + * + * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0 + * + * \param ctx AES context + * \param input Plaintext block + * \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_internal_aes_encrypt(ctx, input, output); +} + +/** + * \brief Internal AES block decryption function + * (Only exposed to allow overriding it, + * see MBEDTLS_AES_DECRYPT_ALT) + * + * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0 + * + * \param ctx AES context + * \param input Ciphertext block + * \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_internal_aes_decrypt(ctx, input, output); +} + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_aes_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/asn1.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/asn1.h new file mode 100644 index 00000000..b561b49a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/asn1.h @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) + #include "bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with DER encoded the ANS1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * '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 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +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. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +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 */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +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. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +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. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching + * 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); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \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); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \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); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \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); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \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); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \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); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \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); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \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); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \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); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \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); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \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); + +/** + * \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); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list + * Head will be set to NULL + * + * \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); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/base64.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/base64.h new file mode 100644 index 00000000..ef2cd0bd --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/base64.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \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); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \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); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bignum.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bignum.h new file mode 100644 index 00000000..4781c6b7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bignum.h @@ -0,0 +1,701 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) + #include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#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. */ +#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. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes) + * by defining MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM + */ +#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; +#else +#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 */ +#endif /* !MBEDTLS_HAVE_INT32 && _MSC_VER && _M_AMD64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct { + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mbedtls_mpi_init(mbedtls_mpi *X); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mbedtls_mpi_free(mbedtls_mpi *X); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * 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); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mbedtls_mpi value + * \param Y Second mbedtls_mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * 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); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +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 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * 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); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_lsb(const mbedtls_mpi *X); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +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); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \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); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param buf Buffer to write the string to + * \param buflen Length of buf + * \param olen Length of the string written, including final NUL byte + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \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); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read X from an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if + * 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); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * + * \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); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \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); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \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); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -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); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than 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); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -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); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \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); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand 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); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand 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); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand 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); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \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); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \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); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \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); + +/** + * \brief Baseline multiplication: X = A * b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The unsigned integer value to multiply with + * + * \note b is unsigned + * + * \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); + +/** + * \brief Division by mbedtls_mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \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); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \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); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * 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); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination mbedtls_mpi_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * 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); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * 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); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \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); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \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); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * 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); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * 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); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * 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); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bn_mul.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bn_mul.h new file mode 100644 index 00000000..30b487ae --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bn_mul.h @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#include "bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * gcc -O0 by default uses r7 for the frame pointer, so it complains about our + * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, + * passing that option is not easy when building with yotta. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/check_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/check_config.h new file mode 100644 index 00000000..6d600fe9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/check_config.h @@ -0,0 +1,644 @@ +/* + * 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. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.pl. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher.h new file mode 100644 index 00000000..763ed439 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher.h @@ -0,0 +1,699 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + #define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + #define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) + #define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) + #define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, + MBEDTLS_CIPHER_ID_NULL, + MBEDTLS_CIPHER_ID_AES, + MBEDTLS_CIPHER_ID_DES, + MBEDTLS_CIPHER_ID_3DES, + MBEDTLS_CIPHER_ID_CAMELLIA, + MBEDTLS_CIPHER_ID_BLOWFISH, + MBEDTLS_CIPHER_ID_ARC4, +} mbedtls_cipher_id_t; + +typedef enum { + MBEDTLS_CIPHER_NONE = 0, + MBEDTLS_CIPHER_NULL, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_CIPHER_CAMELLIA_256_CCM, +} mbedtls_cipher_type_t; + +typedef enum { + MBEDTLS_MODE_NONE = 0, + MBEDTLS_MODE_ECB, + MBEDTLS_MODE_CBC, + MBEDTLS_MODE_CFB, + MBEDTLS_MODE_OFB, /* Unused! */ + MBEDTLS_MODE_CTR, + MBEDTLS_MODE_GCM, + MBEDTLS_MODE_STREAM, + MBEDTLS_MODE_CCM, +} mbedtls_cipher_mode_t; + +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ + MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible!) */ + MBEDTLS_PADDING_NONE, /**< never pad (full blocks only) */ +} mbedtls_cipher_padding_t; + +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length, in bits (including parity), for DES in two key EDE */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length, in bits (including parity), for DES in three-key EDE */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in bytes */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in bytes */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows cipher functions to be called in a generic way. + */ +typedef struct { + /** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */ + mbedtls_cipher_type_t type; + + /** Cipher mode (e.g. MBEDTLS_MODE_CBC) */ + mbedtls_cipher_mode_t mode; + + /** Cipher key length, in bits (default length for variable sized ciphers) + * (Includes parity bits for ciphers like DES) */ + unsigned int key_bitlen; + + /** Name of the cipher */ + const char *name; + + /** IV/NONCE size, in bytes. + * For cipher that accept many sizes: recommended size */ + unsigned int iv_size; + + /** Flags for variable IV size, variable key size, etc. */ + int flags; + + /** block size, in bytes */ + unsigned int block_size; + + /** Base cipher information and functions */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct { + /** Information about the associated cipher */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use */ + int key_bitlen; + + /** Operation that the context's key has been initialised for */ + mbedtls_operation_t operation; + +#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); +#endif + + /** Buffer for data that hasn't been encrypted yet */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of bytes that still need processing */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in bytes (for ciphers with variable-length IVs) */ + size_t iv_size; + + /** Cipher-specific context */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC Specific context */ + mbedtls_cmac_context_t *cmac_ctx; +#endif +} mbedtls_cipher_context_t; + +/** + * \brief Returns the list of ciphers supported by the generic cipher module. + * + * \return a statically allocated array of ciphers, the last entry + * is 0. + */ +const int *mbedtls_cipher_list(void); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \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); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \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); + +/** + * \brief Returns the cipher information structure associated + * with the given cipher id, key size and mode. + * + * \param cipher_id Id of the cipher to search for + * (e.g. MBEDTLS_CIPHER_ID_AES) + * \param key_bitlen Length of the key in bits + * \param mode Cipher mode (e.g. MBEDTLS_MODE_CBC) + * + * \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); + +/** + * \brief Initialize a cipher_context (as NONE) + */ +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); + +/** + * \brief Initialises and fills the cipher context structure with + * the appropriate values. + * + * \note Currently also clears structure. In future versions you + * will be required to call mbedtls_cipher_init() on the structure + * first. + * + * \param ctx context to initialise. May not be NULL. + * \param cipher_info cipher to use. + * + * \return 0 on success, + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, + * 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); + +/** + * \brief Returns the block size of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \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) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return 0; + } + + return ctx->cipher_info->block_size; +} + +/** + * \brief Returns the mode of operation for the cipher. + * (e.g. MBEDTLS_MODE_CBC) + * + * \param ctx cipher's context. Must have been initialised. + * + * \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) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return MBEDTLS_MODE_NONE; + } + + return ctx->cipher_info->mode; +} + +/** + * \brief Returns the size of the cipher's IV/NONCE in bytes. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return If IV has not been set yet: (recommended) IV size + * (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) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return 0; + } + + if (ctx->iv_size != 0) { + return (int) ctx->iv_size; + } + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief Returns the type of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \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) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return MBEDTLS_CIPHER_NONE; + } + + return ctx->cipher_info->type; +} + +/** + * \brief Returns the name of the given cipher, as a string. + * + * \param ctx cipher's context. Must have been initialised. + * + * \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) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return 0; + } + + return ctx->cipher_info->name; +} + +/** + * \brief Returns the key length of the cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return cipher's key length, in bits, or + * MBEDTLS_KEY_LENGTH_NONE if ctx has not been + * initialised. + */ +static inline int mbedtls_cipher_get_key_bitlen(const mbedtls_cipher_context_t *ctx) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return MBEDTLS_KEY_LENGTH_NONE; + } + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief Returns the operation of the given cipher. + * + * \param ctx cipher's context. Must have been initialised. + * + * \return operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT), + * 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) +{ + if (NULL == ctx || NULL == ctx->cipher_info) { + return MBEDTLS_OPERATION_NONE; + } + + return ctx->operation; +} + +/** + * \brief Set the key to use with the given context. + * + * \param ctx generic cipher context. May not be NULL. Must have been + * initialised using cipher_context_from_type or + * cipher_context_from_string. + * \param key The key to use. + * \param key_bitlen key length to use, in bits. + * \param operation Operation that the key will be used for, either + * MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT. + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * 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); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief Set padding mode, for cipher modes that use padding. + * (Default: PKCS7 padding.) + * + * \param ctx generic cipher context + * \param mode padding mode + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if selected padding mode is not supported, or + * 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); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief Set the initialization vector (IV) or nonce + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * + * \returns 0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * + * \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); + +/** + * \brief Finish preparation of the given context + * + * \param ctx generic cipher context + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief Add additional data (for AEAD ciphers). + * Currently only supported with GCM. + * Must be called exactly once, after mbedtls_cipher_reset(). + * + * \param ctx generic cipher context + * \param ad Additional data to use. + * \param ad_len Length of ad. + * + * \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); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief Generic cipher update function. Encrypts/decrypts + * using the given cipher context. Writes as many block + * size'd blocks of data as possible to output. Any data + * that cannot be written immediately will either be added + * to the next block, or flushed when cipher_final is + * called. + * Exception: for MBEDTLS_MODE_ECB, expects single block + * in size (e.g. 16 bytes for AES) + * + * \param ctx generic cipher context + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher or a cipher specific + * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * 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); + +/** + * \brief Generic cipher finalisation function. If data still + * needs to be flushed from an incomplete block, data + * contained within it will be padded with the size of + * the last block, and written to the output buffer. + * + * \param ctx Generic cipher context + * \param output buffer to write data to. Needs block_size available. + * \param olen length of the data written to the output buffer. + * + * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if + * parameter verification fails, + * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, + * 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); + +#if defined(MBEDTLS_GCM_C) +/** + * \brief Write tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag buffer to write the tag + * \param tag_len Length of the tag to write + * + * \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); + +/** + * \brief Check tag for AEAD ciphers. + * Currently only supported with GCM. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx Generic cipher context + * \param tag Buffer holding the tag + * \param tag_len Length of the tag to check + * + * \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); +#endif /* MBEDTLS_GCM_C */ + +/** + * \brief Generic all-in-one encryption/decryption + * (for all ciphers except AEAD constructs). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. Should be able to hold at + * least ilen + block_size. Cannot be the same buffer as + * input! + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, use iv = NULL and iv_len = 0. + * + * \returns 0 on success, or + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption + * expected a full block but was not provided one, or + * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * 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); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief Generic autenticated encryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to authenticate. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer for the authentication tag + * \param tag_len desired tag length + * + * \returns 0 on success, or + * 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); + +/** + * \brief Generic autenticated decryption (AEAD ciphers). + * + * \param ctx generic cipher context + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. + * \param ad Additional data to be authenticated. + * \param ad_len Length of ad. + * \param input buffer holding the input data + * \param ilen length of the input data + * \param output buffer for the output data. + * Should be able to hold at least ilen. + * \param olen length of the output data, will be filled with the + * actual number of bytes written. + * \param tag buffer holding the authentication tag + * \param tag_len length of the authentication tag + * + * \returns 0 on success, or + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or + * MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic, + * or a cipher specific error code. + * + * \note If the data is not authentic, then the output buffer + * 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); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher_internal.h new file mode 100644 index 00000000..db57b2e7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher_internal.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/config.h new file mode 100644 index 00000000..cc1763c9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/config.h @@ -0,0 +1,2640 @@ +/* + * 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 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_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 MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_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 MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_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 MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_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 MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT + +/** + * \def MBEDTLS_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 MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} 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 MBEDTLS_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 MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__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 MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_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. + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_XTEA_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +/* + * 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 MBEDTLS__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. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__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 MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_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 + * MBEDTLS_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. + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_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 MBEDTLS_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 MBEDTLS_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 MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_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 */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_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 MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_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 MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Store the AES tables in ROM. + * + * Uncomment this macro to store the AES tables in ROM. + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_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 MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_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 MBEDTLS_CIPHER_PADDING_PKCS7 +//#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +//#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_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: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_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 MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_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 + */ +//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +//#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +//#define MBEDTLS_ECP_DP_BP256R1_ENABLED +//#define MBEDTLS_ECP_DP_BP384R1_ENABLED +//#define MBEDTLS_ECP_DP_BP512R1_ENABLED +//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_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: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_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): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_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: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_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 MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_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: MBEDTLS_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 MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_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: MBEDTLS_ENTROPY_C, MBEDTLS_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 (MBEDTLS_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 MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_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 MBEDTLS_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. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_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: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_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. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_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 MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_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. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_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: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +//#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_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: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +//#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_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 + */ +//#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_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 MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +//#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_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. + */ +//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_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: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_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: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_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 MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_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 + */ +//#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +//#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_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: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +//#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_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 MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_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 MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_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 + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_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): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_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): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_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 MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_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 + */ +//#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_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 MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_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 MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_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): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +//#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_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 MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_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): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_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 + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_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: MBEDTLS_ECP_C + */ +//#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_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: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +//#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_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: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_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: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +//#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +//#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_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: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_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. + */ +// #define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_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: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_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 MBEDTLS_NET_C + +/** + * \def MBEDTLS_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 MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_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: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_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: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +//#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_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: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_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 MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_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: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_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 MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_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 MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_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. + */ +//#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_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 MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_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 MBEDTLS_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 MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +//#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_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: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_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: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} 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 */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * 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. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations */ +//#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 +#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_MBEDTLS_USER_CONFIG_FILE) + #include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE +#elif defined(MBEDTLS_USER_CONFIG_FILE) + #include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ctr_drbg.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ctr_drbg.h new file mode 100644 index 00000000..7b78285d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ctr_drbg.h @@ -0,0 +1,273 @@ +/* + * 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" +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ +#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) */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#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 +#endif + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) + #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 */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) + #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 */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CTR_DRBG context structure + */ +typedef struct { + unsigned char counter[16]; /*!< counter (V) */ + int reseed_counter; /*!< reseed counter */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + size_t entropy_len; /*!< amount of entropy grabbed on each + (re)seed */ + int reseed_interval; /*!< reseed interval */ + + mbedtls_aes_context aes_ctx; /*!< AES context */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief CTR_DRBG context initialization + * Makes the context ready for mbedtls_ctr_drbg_seed() or + * mbedtls_ctr_drbg_free(). + * + * \param ctx CTR_DRBG context to be initialized + */ +void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx); + +/** + * \brief CTR_DRBG initial seeding + * Seed and setup entropy source for future reseeds. + * + * Note: Personalization data can be provided in addition to the more generic + * entropy source to make this instantiation as unique as possible. + * + * \param ctx CTR_DRBG context to be seeded + * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer + * length) + * \param p_entropy Entropy context + * \param custom Personalization data (Device specific identifiers) + * (Can be NULL) + * \param len Length of personalization data + * + * \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); + +/** + * \brief Clear CTR_CRBG context data + * + * \param ctx CTR_DRBG context to clear + */ +void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx); + +/** + * \brief Enable / disable prediction resistance (Default: Off) + * + * Note: If enabled, entropy is used for ctx->entropy_len before each call! + * Only use this if you have ample supply of good entropy! + * + * \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); + +/** + * \brief Set the amount of entropy grabbed on each (re)seed + * (Default: MBEDTLS_CTR_DRBG_ENTROPY_LEN) + * + * \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); + +/** + * \brief Set the reseed interval + * (Default: MBEDTLS_CTR_DRBG_RESEED_INTERVAL) + * + * \param ctx CTR_DRBG context + * \param interval Reseed interval + */ +void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, + int interval); + +/** + * \brief CTR_DRBG reseeding (extracts data from entropy source) + * + * \param ctx CTR_DRBG context + * \param additional Additional data to add to state (Can be NULL) + * \param len Length of additional data + * + * \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); + +/** + * \brief CTR_DRBG update state + * + * \param ctx CTR_DRBG context + * \param additional Additional data to update state with + * \param add_len Length of additional data + * + * \note If add_len is greater than MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, + * 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); + +/** + * \brief CTR_DRBG generate random with additional update input + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * \param additional Additional data to update with (Can be NULL) + * \param add_len Length of additional data + * + * \return 0 if successful, or + * 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); + +/** + * \brief CTR_DRBG generate random + * + * Note: Automatically reseeds if reseed_counter is reached. + * + * \param p_rng CTR_DRBG context + * \param output Buffer to fill + * \param output_len Length of the buffer + * + * \return 0 if successful, or + * 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); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * 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); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance + * + * \param ctx CTR_DRBG context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, + * 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); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +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); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/debug.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/debug.h new file mode 100644 index 00000000..e62f6764 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/debug.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#define tls_info(...) log_info("tls", __VA_ARGS__) + +#if defined(MBEDTLS_ECP_C) + #include "ecp.h" +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold(int threshold); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \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, ...); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \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); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \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); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \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); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \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); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \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); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/des.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/des.h new file mode 100644 index 00000000..a2ce8824 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/des.h @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief DES context structure + */ +typedef struct { + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct { + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + */ +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); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +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); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + */ +void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \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]); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \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]); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + */ +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) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +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) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +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) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +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) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8]); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \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 DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_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 + */ +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 */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8]); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \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 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_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 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); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + */ +void mbedtls_des_setkey(uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE]); +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ecp.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ecp.h new file mode 100644 index 00000000..da8699c9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ecp.h @@ -0,0 +1,663 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#include "bignum.h" + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain parameters (curve, subgroup and generator) identifiers. + * + * Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only well-known domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum { + MBEDTLS_ECP_DP_NONE = 0, + MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ + MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ + MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ + MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ + MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ + MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ + MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ + MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ +} mbedtls_ecp_group_id; + +/** + * Number of supported curves (plus one for NONE). + * + * (Montgomery curves excluded for now.) + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/** + * Curve information for use by other modules + */ +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 */ + const char *name; /*!< Human-friendly name */ +} mbedtls_ecp_curve_info; + +/** + * \brief ECP point structure (jacobian coordinates) + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or Z == 1. (Other + * values of Z are used by internal functions only.) + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, X and Y are its standard (affine) coordinates. + */ +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 */ +} +mbedtls_ecp_point; + +/** + * \brief ECP group structure + * + * We consider two types of curves equations: + * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) + * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) + * In both cases, a generator G for a prime-order subgroup is fixed. In the + * short weierstrass, this subgroup is actually the whole curve, and its + * cardinal is denoted by N. + * + * In the case of Short Weierstrass curves, our code requires that N is an odd + * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) + * + * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is + * the quantity actually used in the formulas. Also, nbits is not the size of N + * but the required size for private keys. + * + * If modp is NULL, reduction modulo P is done using a generic algorithm. + * Otherwise, it must point to a function that takes an mbedtls_mpi in the range + * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more + * than pbits, so that the integer may be efficiently brought in the 0..P-1 + * range by a few additions or substractions. It must return 0 on success and + * non-zero on failure. + */ +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 */ + mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ + mbedtls_ecp_point G; /*!< generator of the (sub)group used */ + mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ + size_t pbits; /*!< number of bits in P */ + size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ + unsigned int h; /*!< internal: 1 if the constants are static */ + int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ + void *t_data; /*!< unused */ + mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ + size_t T_size; /*!< number for pre-computed points */ +} +mbedtls_ecp_group; + +/** + * \brief ECP key pair structure + * + * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * + * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. + */ +typedef struct { + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * Maximum size of the groups (that is, of N and P) + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ + +/** + * \brief Get the list of supported curves in order of preferrence + * (full information) + * + * \return A statically allocated array, the last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void); + +/** + * \brief Get the list of supported curves in order of preferrence + * (grp_id only) + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void); + +/** + * \brief Get curve information from an internal group identifier + * + * \param grp_id A MBEDTLS_ECP_DP_XXX value + * + * \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); + +/** + * \brief Get curve information from a TLS NamedCurve value + * + * \param tls_id A MBEDTLS_ECP_DP_XXX value + * + * \return The associated curve information or NULL + */ +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 + * + * \param name The name + * + * \return The associated curve information or NULL + */ +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); + +/** + * \brief Initialize a group (to something meaningless) + */ +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); + +/** + * \brief Free the components of a point + */ +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); + +/** + * \brief Free the components of a key pair + */ +void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key); + +/** + * \brief Copy the contents of point Q into P + * + * \param P Destination point + * \param Q Source point + * + * \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); + +/** + * \brief Copy the contents of a group object + * + * \param dst Destination group + * \param src Source group + * + * \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); + +/** + * \brief Set a point to zero + * + * \param pt Destination point + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt); + +/** + * \brief Tell if a point is zero + * + * \param pt Point to test + * + * \return 1 if point is zero, 0 otherwise + */ +int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt); + +/** + * \brief Compare two points + * + * \note This assumes the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P First point to compare + * \param Q Second point to compare + * + * \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); + +/** + * \brief Import a non-zero point from two ASCII strings + * + * \param P Destination point + * \param radix Input numeric base + * \param x First affine coordinate as a null-terminated string + * \param y Second affine coordinate as a null-terminated string + * + * \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); + +/** + * \brief Export a point into unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to export + * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro + * \param olen Length of the actual output + * \param buf Output buffer + * \param buflen Length of the output buffer + * + * \return 0 if successful, + * 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); + +/** + * \brief Import a point from unsigned binary data + * + * \param grp Group to which the point should belong + * \param P Point to import + * \param buf Input buffer + * \param ilen Actual length of input + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + * \note This function does NOT check that the point actually + * 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); + +/** + * \brief Import a point from a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Destination point + * \param buf $(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after the ECPoint on exit + * + * \return 0 if successful, + * 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); + +/** + * \brief Export a point as a TLS ECPoint record + * + * \param grp ECP group used + * \param pt Point to export + * \param format Export format + * \param olen length of data written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \return 0 if successful, + * 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); + +/** + * \brief Set a group using well-known domain parameters + * + * \param grp Destination group + * \param index Index in the list of well-known domain parameters + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_XXX if initialization failed + * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * + * \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); + +/** + * \brief Set a group from a TLS ECParameters record + * + * \param grp Destination group + * \param buf &(Start of input buffer) + * \param len Buffer length + * + * \note buf is updated to point right after ECParameters on exit + * + * \return 0 if successful, + * 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); + +/** + * \brief Write the TLS ECParameters record for a group + * + * \param grp ECP group used + * \param olen Number of bytes actually written + * \param buf Buffer to write to + * \param blen Buffer length + * + * \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); + +/** + * \brief Multiplication by an integer: R = m * P + * (Not thread-safe to use same group in multiple threads) + * + * \note In order to prevent timing attacks, this function + * executes the exact same sequence of (base field) + * operations for any valid m. It avoids any if-branch or + * array index depending on the value of m. + * + * \note If f_rng is not NULL, it is used to randomize intermediate + * results in order to prevent potential timing attacks + * targeting these results. It is recommended to always + * provide a non-NULL f_rng (the overhead is negligible). + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey + * 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); + +/** + * \brief Multiplication and addition of two points by integers: + * R = m * P + n * Q + * (Not thread-safe to use same group in multiple threads) + * + * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee + * a constant execution flow and timing. + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply P + * \param P Point to multiply by m + * \param n Integer by which to multiply Q + * \param Q Point to be multiplied by n + * + * \return 0 if successful, + * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey + * 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); + +/** + * \brief Check that a point is a valid public key on this curve + * + * \param grp Curve/group the point should belong to + * \param pt Point to check + * + * \return 0 if point is a valid public key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note This function only checks the point is non-zero, has valid + * coordinates and lies on the curve, but not that it is + * indeed a multiple of G. This is additional check is more + * expensive, isn't required by standards, and shouldn't be + * necessary if the group used has a small cofactor. In + * particular, it is useless for the NIST groups which all + * have a cofactor of 1. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * 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); + +/** + * \brief Check that an mbedtls_mpi is a valid private key for this curve + * + * \param grp Group used + * \param d Integer to check + * + * \return 0 if point is a valid private key, + * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * 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); + +/** + * \brief Generate a keypair with configurable base point + * + * \param grp ECP group + * \param G Chosen base point + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * 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); + +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * + * \note Uses bare components rather than an mbedtls_ecp_keypair structure + * 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); + +/** + * \brief Generate a keypair + * + * \param grp_id ECP group identifier + * \param key Destination keypair + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \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); + +/** + * \brief Check a public-private key pair + * + * \param pub Keypair structure holding a public key + * \param prv Keypair structure holding a private (plus public) key + * + * \return 0 if successful (keys are valid and match), or + * 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); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecp_self_test(int verbose); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#endif /* ecp.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy.h new file mode 100644 index 00000000..1aa97f2a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy.h @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) + #include "sha512.h" + #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else + #if defined(MBEDTLS_SHA256_C) + #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR + #include "sha256.h" + #endif +#endif + +#if defined(MBEDTLS_THREADING_C) + #include "threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) + #include "havege.h" +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) + #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 */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + #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) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct { + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + 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? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +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); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTSL_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \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); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather(mbedtls_entropy_context *ctx); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func(void *data, unsigned char *output, size_t len); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * 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); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * 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); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test(int verbose); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test(int verbose); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy_poll.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy_poll.h new file mode 100644 index 00000000..85cdfee5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy_poll.h @@ -0,0 +1,93 @@ +/* + * 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" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \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); +#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); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +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); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll(void *data, + unsigned char *output, size_t len, size_t *olen); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \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); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/error.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/error.h new file mode 100644 index 00000000..09e0de79 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/error.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#include +#include "config.h" + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 2 0x0012-0x0014 + * BLOWFISH 2 0x0016-0x0018 + * THREADING 3 0x001A-0x001E + * AES 2 0x0020-0x0022 + * CAMELLIA 2 0x0024-0x0026 + * XTEA 1 0x0028-0x0028 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 1 0x0032-0x0032 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 11 0x0042-0x0052 0x0043-0x0045 + * ASN1 7 0x0060-0x006C + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 2 0x000D-0x000F + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 19 + * PKCS5 2 4 (Started from top) + * DHM 3 9 + * PK 3 14 (Started from top) + * RSA 4 9 + * ECP 4 8 (Started from top) + * MD 5 4 + * CIPHER 6 6 + * SSL 6 17 (Started from top) + * SSL 7 31 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror(int errnum, char *buffer, size_t buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md.h new file mode 100644 index 00000000..c7c3b566 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md.h @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + MBEDTLS_MD_NONE = 0, + MBEDTLS_MD_MD2, + MBEDTLS_MD_MD4, + MBEDTLS_MD_MD5, + MBEDTLS_MD_SHA1, + MBEDTLS_MD_SHA224, + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_SHA512, + MBEDTLS_MD_RIPEMD160, +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Opaque struct defined in md_internal.h + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * Generic message digest context. + */ +typedef struct { + /** Information about the associated message digest */ + const mbedtls_md_info_t *md_info; + + /** Digest-specific context */ + void *md_ctx; + + /** HMAC part of the context */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief Returns the list of digests supported by the generic digest module. + * + * \return a statically allocated array of digests, the last entry + * is 0. + */ +const int *mbedtls_md_list(void); + +/** + * \brief Returns the message digest information associated with the + * given digest name. + * + * \param md_name Name of the digest to search for. + * + * \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); + +/** + * \brief Returns the message digest information associated with the + * given digest type. + * + * \param md_type type of digest to search for. + * + * \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); + +/** + * \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); + +/** + * \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); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Select MD to use and allocate internal structures. + * Should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx Context to set up. + * \param md_info Message digest to use. + * + * \returns \c 0 on success, + * \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; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Select MD to use and allocate internal structures. + * Should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \param ctx Context to set up. + * \param md_info Message digest to use. + * \param hmac 0 to save some memory if HMAC will not be used, + * non-zero is HMAC is going to be used with this context. + * + * \returns \c 0 on success, + * \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); + +/** + * \brief Clone the state of an MD context + * + * \note The two contexts must have been setup to the same type + * (cloning from SHA-256 to SHA-512 make no sense). + * + * \warning Only clones the MD state, not the HMAC state! (for now) + * + * \param dst The destination context + * \param src The context to be cloned + * + * \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); + +/** + * \brief Returns the size of the message digest output. + * + * \param md_info message digest info + * + * \return size of the message digest output in bytes. + */ +unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info); + +/** + * \brief Returns the type of the message digest output. + * + * \param md_info message digest info + * + * \return type of the message digest output. + */ +mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); + +/** + * \brief Returns the name of the message digest output. + * + * \param md_info message digest info + * + * \return name of the message digest output. + */ +const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); + +/** + * \brief Prepare the context to digest a new message. + * Generally called after mbedtls_md_setup() or mbedtls_md_finish(). + * Followed by mbedtls_md_update(). + * + * \param ctx generic message digest context. + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_starts(mbedtls_md_context_t *ctx); + +/** + * \brief Generic message digest process buffer + * Called between mbedtls_md_starts() and mbedtls_md_finish(). + * May be called repeatedly. + * + * \param ctx Generic message digest context + * \param input buffer holding the datal + * \param ilen length of the input data + * + * \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); + +/** + * \brief Generic message digest final digest + * Called after mbedtls_md_update(). + * Usually followed by mbedtls_md_free() or mbedtls_md_starts(). + * + * \param ctx Generic message digest context + * \param output Generic message digest checksum result + * + * \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); + +/** + * \brief Output = message_digest( input buffer ) + * + * \param md_info message digest info + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic message digest checksum result + * + * \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); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Output = message_digest( file contents ) + * + * \param md_info message digest info + * \param path input file name + * \param output generic message digest checksum result + * + * \return 0 if successful, + * 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); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Set HMAC key and prepare to authenticate a new message. + * Usually called after mbedtls_md_setup() or mbedtls_md_hmac_finish(). + * + * \param ctx HMAC context + * \param key HMAC secret key + * \param keylen length of the HMAC key in bytes + * + * \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); + +/** + * \brief Generic HMAC process buffer. + * Called between mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * and mbedtls_md_hmac_finish(). + * May be called repeatedly. + * + * \param ctx HMAC context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \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); + +/** + * \brief Output HMAC. + * Called after mbedtls_md_hmac_update(). + * Usually followed by mbedtls_md_hmac_reset(), + * mbedtls_md_hmac_starts(), or mbedtls_md_free(). + * + * \param ctx HMAC context + * \param output Generic HMAC checksum result + * + * \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); + +/** + * \brief Prepare to authenticate a new message with the same key. + * Called after mbedtls_md_hmac_finish() and before + * mbedtls_md_hmac_update(). + * + * \param ctx HMAC context to be reset + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx); + +/** + * \brief Output = Generic_HMAC( hmac key, input buffer ) + * + * \param md_info message digest info + * \param key HMAC secret key + * \param keylen length of the HMAC key in bytes + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic HMAC-result + * + * \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); + +/* Internal use */ +int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md5.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md5.h new file mode 100644 index 00000000..1ef52a07 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md5.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MD5 context structure + */ +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 */ +} +mbedtls_md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + */ +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); + +/** + * \brief Clone (the state of) an MD5 context + * + * \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); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_md5_starts(mbedtls_md5_context *ctx); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_md5_update(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +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]); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \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]); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_md5_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md_internal.h new file mode 100644 index 00000000..5f5ca6c8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md_internal.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function in bytes */ + int size; + + /** Block length of the digest function in bytes */ + int block_size; + + /** Digest initialisation function */ + void (*starts_func)( void *ctx ); + + /** Digest update function */ + void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + void (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + void (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Clone state from a context */ + void (*clone_func)( void *dst, const void *src ); + + /** Internal use only */ + void (*process_func)( void *ctx, const unsigned char *input ); +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net.h new file mode 100644 index 00000000..4ad82238 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net_sockets.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net_sockets.h new file mode 100644 index 00000000..cf3eb9c8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net_sockets.h @@ -0,0 +1,208 @@ +/* + * 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" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct { + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init(mbedtls_net_context *ctx); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \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); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \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); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * 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); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block(mbedtls_net_context *ctx); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock(mbedtls_net_context *ctx); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep(unsigned long usec); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * 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); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * 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); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return the number of bytes received, + * or a non-zero error code: + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * 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); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free(mbedtls_net_context *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/oid.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/oid.h new file mode 100644 index 00000000..e1f58de6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/oid.h @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) + #include "cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) + #include "md.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + #include "x509.h" +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#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)} */ +#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 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ + +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct { + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \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); + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \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); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \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); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \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); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \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); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \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); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \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); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \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); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \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); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \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); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \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); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \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); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \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); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \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); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \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); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pem.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pem.h new file mode 100644 index 00000000..589fbf8f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pem.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct { + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init(mbedtls_pem_context *ctx); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \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); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free(mbedtls_pem_context *ctx); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * 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); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk.h new file mode 100644 index 00000000..a25e358f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk.h @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_RSA_C) + #include "rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) + #include "ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) + #include "ecdsa.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) + #define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE = 0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct { + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum { + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct { + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +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 */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \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) +{ + return ((mbedtls_rsa_context *)(pk).pk_ctx); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \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) +{ + return ((mbedtls_ecp_keypair *)(pk).pk_ctx); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \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); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \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); + +/** + * \brief Initialize a mbedtls_pk_context (as NONE) + */ +void mbedtls_pk_init(mbedtls_pk_context *ctx); + +/** + * \brief Free a mbedtls_pk_context + */ +void mbedtls_pk_free(mbedtls_pk_context *ctx); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \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); + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \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); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) +{ + return ((mbedtls_pk_get_bitlen(ctx) + 7) / 8); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \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); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \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); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is + * valid but its actual length is less than sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * 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); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use - must hold a private key + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \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); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use - must hold a private key + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \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); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \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); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \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); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \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); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or MBEDTLS_PK_NONE + */ +mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \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); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \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); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \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); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \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); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \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); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \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); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \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); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \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); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \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); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \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); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk_internal.h new file mode 100644 index 00000000..f1868251 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk_internal.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *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 ); + + /** Decrypt message */ + int (*decrypt_func)( void *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 ); + + /** Encrypt message */ + int (*encrypt_func)( void *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 ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + 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; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/platform.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/platform.h new file mode 100644 index 00000000..640094f0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/platform.h @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) + #include "mbedtls/platform_time.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(_WIN32) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< Default exit value to use */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *(*mbedtls_calloc)(size_t n, size_t size); +extern void (*mbedtls_free)(void *ptr); + +/** + * \brief Set your own memory implementation function pointers + * + * \param calloc_func the calloc function implementation + * \param free_func the free function implementation + * + * \return 0 if successful + */ +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 +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...); + +/** + * \brief Set your own fprintf function pointer + * + * \param fprintf_func the fprintf function implementation + * + * \return 0 + */ +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 +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)(const char *format, ...); + +/** + * \brief Set your own printf function pointer + * + * \param printf_func the printf function implementation + * + * \return 0 + */ +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 +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#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, ...); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...); + +/** + * \brief Set your own snprintf function pointer + * + * \param snprintf_func the snprintf function implementation + * + * \return 0 + */ +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 +#else +#define mbedtls_snprintf snprintf +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)(int status); + +/** + * \brief Set your own exit function pointer + * + * \param exit_func the exit function implementation + * + * \return 0 + */ +int mbedtls_platform_set_exit(void (*exit_func)(int status)); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#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); +#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); + +/** + * \brief Set your own seed file writing/reading functions + * + * \param nv_seed_read_func the seed reading function implementation + * \param nv_seed_write_func the seed writing function implementation + * + * \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) +); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/rsa.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/rsa.h new file mode 100644 index 00000000..4c9cee03 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/rsa.h @@ -0,0 +1,635 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) + #include "threading.h" +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the library's validity check. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 +#define MBEDTLS_RSA_PRIVATE 1 + +#define MBEDTLS_RSA_PKCS_V15 0 +#define MBEDTLS_RSA_PKCS_V21 1 + +#define MBEDTLS_RSA_SIGN 1 +#define MBEDTLS_RSA_CRYPT 2 + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ +#if defined(MBEDTLS_RSA_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief RSA context structure + */ +typedef struct { + int ver; /*!< always 0 */ + size_t len; /*!< size(N) in chars */ + + mbedtls_mpi N; /*!< public modulus */ + mbedtls_mpi E; /*!< public exponent */ + + mbedtls_mpi D; /*!< private exponent */ + mbedtls_mpi P; /*!< 1st prime factor */ + mbedtls_mpi Q; /*!< 2nd prime factor */ + mbedtls_mpi DP; /*!< D % (P - 1) */ + mbedtls_mpi DQ; /*!< D % (Q - 1) */ + mbedtls_mpi QP; /*!< 1 / (Q % P) */ + + mbedtls_mpi RN; /*!< cached R^2 mod N */ + mbedtls_mpi RP; /*!< cached R^2 mod P */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q */ + + mbedtls_mpi Vi; /*!< cached blinding value */ + mbedtls_mpi Vf; /*!< cached un-blinding value */ + + int padding; /*!< MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + MBEDTLS_RSA_PKCS_v21 for OAEP/PSS */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t as + specified in the mbedtls_md.h header file + for the EME-OAEP and EMSA-PSS + encoding */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex */ +#endif +} +mbedtls_rsa_context; + +/** + * \brief Initialize an RSA context + * + * Note: Set padding to MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \param ctx RSA context to be initialized + * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 + * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier + * + * \note The hash_id parameter is actually ignored + * when using MBEDTLS_RSA_PKCS_V15 padding. + * + * \note Choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it's merely + * a default value, which can be overriden by calling specific + * rsa_rsaes_xxx or rsa_rsassa_xxx functions. + * + * \note The chosen hash is always used for OEAP encryption. + * For PSS signatures, it's always used for making signatures, + * 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); + +/** + * \brief Set padding for an already initialized RSA context + * See \c mbedtls_rsa_init() for details. + * + * \param ctx RSA context to be set + * \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); + +/** + * \brief Generate an RSA keypair + * + * \param ctx RSA context that will hold the key + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param nbits size of the public key in bits + * \param exponent public exponent (e.g., 65537) + * + * \note mbedtls_rsa_init() must be called beforehand to setup + * the RSA context. + * + * \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); + +/** + * \brief Check a public RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + */ +int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx); + +/** + * \brief Check a private RSA key + * + * \param ctx RSA context to be checked + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + */ +int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx); + +/** + * \brief Check a public-private RSA key pair. + * Check each of the contexts, and make sure they match. + * + * \param pub RSA context holding the public key + * \param prv RSA context holding the private key + * + * \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); + +/** + * \brief Do an RSA public key operation + * + * \param ctx RSA context + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note This function does NOT take care of message + * padding. Also, be sure to set input[0] = 0 or ensure that + * input is smaller than N. + * + * \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); + +/** + * \brief Do an RSA private key operation + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for blinding) + * \param p_rng RNG parameter + * \param input input buffer + * \param output output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \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); + +/** + * \brief Generic wrapper to perform a PKCS#1 encryption using the + * mode from the context. Add the message padding, then do an + * RSA operation. + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding + * and MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \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); + +/** + * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \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); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding + * and MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param ilen contains the plaintext length + * \param input buffer holding the data to be encrypted + * \param output buffer that will hold the ciphertext + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \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); + +/** + * \brief Generic wrapper to perform a PKCS#1 decryption using the + * mode from the context. Do an RSA operation, then remove + * the message padding + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * 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); + +/** + * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * 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); + +/** + * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param label buffer holding the custom label to use + * \param label_len contains the label length + * \param olen will contain the plaintext length + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * 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); + +/** + * \brief Generic wrapper to perform a PKCS#1 signature using the + * mode from the context. Do a private RSA operation to sign + * a message digest + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for + * MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \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); + +/** + * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \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); + +/** + * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) + * + * \param ctx RSA context + * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for + * MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is the one used for the + * encoding. md_alg in the function call is the type of hash + * 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); + +/** + * \brief Generic wrapper to perform a PKCS#1 verification using the + * mode from the context. Do a public RSA operation and check + * the message digest + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \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); + +/** + * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \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); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * (This is the "simple" version.) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \note The hash_id in the RSA context is the one used for the + * verification. md_alg in the function call is the type of + * hash that is verified. According to RFC 3447 it is advised to + * 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); + +/** + * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) + * (This is the version with "full" options.) + * + * \param ctx points to an RSA public key + * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) + * \param p_rng RNG parameter + * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param mgf1_hash_id message digest used for mask generation + * \param expected_salt_len Length of the salt used in padding, use + * MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length + * \param sig buffer holding the ciphertext + * + * \return 0 if the verify operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * + * \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); + +/** + * \brief Copy the components of an RSA context + * + * \param dst Destination context + * \param src Source context + * + * \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); + +/** + * \brief Free the components of an RSA key + * + * \param ctx RSA Context to free + */ +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); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_RSA_C */ + +#endif /* rsa.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha1.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha1.h new file mode 100644 index 00000000..3c247a63 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha1.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_sha1_context; + +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +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); + +/** + * \brief Clone (the state of) a SHA-1 context + * + * \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); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_sha1_starts(mbedtls_sha1_context *ctx); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +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]); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void 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); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha256.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha256.h new file mode 100644 index 00000000..38f1272c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha256.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-256 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} +mbedtls_sha256_context; + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +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); + +/** + * \brief Clone (the state of) a SHA-256 context + * + * \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); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \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); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +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]); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \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); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_sha256_self_test(int verbose); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl.h new file mode 100644 index 00000000..e3503412 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl.h @@ -0,0 +1,2573 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "ecp.h" + +#include "ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + #include "x509_crt.h" + #include "x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) + #include "dhm.h" +#endif + +#if defined(MBEDTLS_ECDH_C) + #include "ecdh.h" +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + #include "zlib.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) + #include "mbedtls/platform_time.h" +#endif + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) + #define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maxium fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * 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 */ +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else + #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) + #define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret { +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum { + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \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); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * 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); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * 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); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * 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); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t(void *ctx); + + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +/* + * This structure is used for storing current session data. + */ +struct mbedtls_ssl_session { +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config { + /* Group items by size (largest first) to minimize padding overhead */ + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#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); + /** Callback to verify validity of a ClientHello cookie */ + 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 *); + /** Callback to parse a session ticket into a session structure */ + 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); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< pre-shared key */ + size_t psk_len; /*!< length of the pre-shared key */ + unsigned char *psk_identity; /*!< identity for PSK negotiation */ + size_t psk_identity_len;/*!< length of identity */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + + /* + * Numerical settings (int then char) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (bitfields) + */ + + unsigned int endpoint : 1; /*!< 0: client, 1: server */ + unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned int mfl_code : 3; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + unsigned int anti_replay : 1; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + unsigned int session_tickets : 1; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + unsigned int fallback : 1; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +}; + + +struct mbedtls_ssl_context { + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif + + 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 */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + int record_read; /*!< record is already present */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already splitted? */ +#endif + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif +}; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 +#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); +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); +extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); +extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Returns the list of ciphersuites supported by the SSL/TLS module. + * + * \return a statically allocated array of ciphersuites, the last + * entry is 0. + */ +const int *mbedtls_ssl_list_ciphersuites(void); + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init(mbedtls_ssl_context *ssl); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning Modifying the conf structure after it has been used in this + * function is unsupported! + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \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); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); + +/** + * \brief Set the current endpoint type + * + * \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); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * 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); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the verify callback is called for each + * certificate in the chain. For implementation + * information, please see \c x509parse_verify() + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \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); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \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); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_sent_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \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); + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \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); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \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); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \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); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \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); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * 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); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a 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, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \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, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \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); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \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); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \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); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * 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); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * 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); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +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) +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * 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); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \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 *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *)); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, + const int *ciphersuites); + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \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); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \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); + +/** + * \brief Set the data required to verify peer certificate + * + * \param conf SSL configuration + * \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); + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case mutliple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \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); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +/** + * \brief Set the Pre Shared Key (PSK) and the expected identity name + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note Currently clients can only register one pre-shared key. + * In other words, the servers' identity hint is ignored. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature but + * feedback is welcomed. + * + * \param conf SSL configuration + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * \param psk_identity pointer to the pre-shared key identity + * \param psk_identity_len identity key length + * + * \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); + + +/** + * \brief Set the Pre Shared Key (PSK) for the current handshake + * + * \note This should only be called inside the PSK callback, + * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \param ssl SSL context + * \param psk pointer to the pre-shared key + * \param psk_len pre-shared key length + * + * \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); + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: (void *parameter, + * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, + * size_t identity_len) + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the + * correct PSK and return 0. + * Any other return value will result in a denied PSK identity. + * + * \note If you set a PSK callback using this function, then you + * don't need to set a PSK key and identity using + * \c mbedtls_ssl_conf_psk(). + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default: MBEDTLS_DHM_RFC5114_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \return 0 if successful + */ +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, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +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) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \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); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * (Default: all available hashes except MD5.) + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the hostname to check against the received server + * certificate. It sets the ServerName TLS extension too, + * if the extension is enabled. + * (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname + * + * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +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) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \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); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \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); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \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); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \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); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_ALPN */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * 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); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * 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); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \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); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \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); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \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); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will likely be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \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); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate + * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \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); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \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); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * 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); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or ingoing) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \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]); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Return the number of data bytes available to read + * + * \param ssl SSL context + * + * \return how many bytes are available in the read buffer + */ +size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl SSL context + * + * \return 0 if successful, + * -1 if result is not available (eg because the handshake was + * aborted too early), or + * a combination of BADCERT_xxx and BADCRL_xxx flags, see + * x509.h + */ +uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * 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); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes). + * This is the value negotiated with peer if any, + * or the locally configured value. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \param ssl SSL context + * + * \return Current maximum fragment length. + */ +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) +/** + * \brief Return the peer certificate from the current connection + * + * Note: Can be NULL in case no certificate was sent during + * the handshake. Different calls for the same connection can + * return the same or different pointers for the same + * certificate and even a different certificate altogether. + * The peer cert CAN change in a single connection if + * renegotiation is performed. + * + * \param ssl SSL context + * + * \return the current peer certificate + */ +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) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * \warning Currently, peer certificate is lost in the operation. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or + * a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * 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); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after execution of this function. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \param ssl SSL context + * + * \return 0 if successful, or + * 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); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \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); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return the number of bytes read, or + * 0 for EOF, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or + * another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has beeen reset internally). Either way, you + * should make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * 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); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return the number of bytes actually written (may be less than len), + * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, + * or another negative error code. + * + * \note If this function returns something other than a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context + * becomes unusable, and you should either free it or call + * \c mbedtls_ssl_session_reset() on it before re-using it for + * a new connection; the current connection must be closed. + * + * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a positive value. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \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); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \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); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context + * becomes unusable, and you should either free it or call + * \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); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free(mbedtls_ssl_context *ssl); + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevent fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init(mbedtls_ssl_config *conf); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \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); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +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); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \param session SSL session + */ +void mbedtls_ssl_session_free(mbedtls_ssl_session *session); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 00000000..9551b952 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + +#include "pk.h" +#include "cipher.h" +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#endif + +/* Key exchanges using a ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t { + int id; + const char *name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +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); + +#if defined(MBEDTLS_PK_C) +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); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_cookie.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_cookie.h new file mode 100644 index 00000000..27768f61 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_cookie.h @@ -0,0 +1,91 @@ +/* + * 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" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#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 */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +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 */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +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); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +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); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_internal.h new file mode 100644 index 00000000..3e97a1e7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_internal.h @@ -0,0 +1,485 @@ +/* + * 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" +#endif + +#if defined(MBEDTLS_SHA1_C) + #include "sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) + #include "sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) + #include "sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + #include "ecjpake.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) + #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 + #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 + #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 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + #define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else + #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 */ + #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 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + #define MBEDTLS_SSL_PADDING_ADD 256 +#else + #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 \ + ) + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params { + /* + * Handshake specific crypto variables + */ + int sig_alg; /*!< Hash algorithm for signature */ + int verify_sig_alg; /*!< Signature algorithm for verify */ +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + int sni_authmode; /*!< authmode from SNI callback */ + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + unsigned char *hs_msg; /*!< Reassembled handshake message */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + unsigned char retransmit_state; /*!< Retransmission state */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ +#endif + + /* + * Checksum contexts + */ +#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; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context fin_sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context fin_sha512; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + 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); + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif +}; + +/* + * This structure contains a full set of runtime transform parameters + * either in negotiation or active. + */ +struct mbedtls_ssl_transform { + /* + * Session specific crypto layer + */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + /*!< Chosen cipersuite_info */ + unsigned int keylen; /*!< symmetric key length (bytes) */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC length */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif +}; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +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 */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +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 */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param handshake SSL handshake context + */ +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_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); + +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_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_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); + +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); +#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); +#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); + +#if defined(MBEDTLS_ECP_C) +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); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +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) { + key_cert = ssl->handshake->key_cert; + } else { + key_cert = ssl->conf->key_cert; + } + + return (key_cert == NULL ? NULL : key_cert->key); +} + +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) { + key_cert = ssl->handshake->key_cert; + } else { + key_cert = ssl->conf->key_cert; + } + + return (key_cert == NULL ? NULL : key_cert->cert); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * 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); +#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]); + +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); + } +#else + ((void) ssl); +#endif + return (5); +} + +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); + } +#else + ((void) ssl); +#endif + 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); +#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); +#endif + +/* constant-time buffer comparison */ +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++) { + diff |= A[i] ^ B[i]; + } + + return (diff); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_internal.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/timing.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/timing.h new file mode 100644 index 00000000..776a6eba --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/timing.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time { + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct { + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + */ +unsigned long mbedtls_timing_hardclock(void); + +/** + * \brief Return the elapsed time in milliseconds + * + * \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); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm(int seconds); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * \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); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0) + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay(void *data); + +#ifdef __cplusplus +} +#endif + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test(int verbose); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509.h new file mode 100644 index 00000000..7fa899b4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509.h @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) + #include "config.h" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(MBEDTLS_RSA_C) + #include "rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#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 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) + +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time { + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \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); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \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); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param time mbedtls_x509_time to check + * + * \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); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param time mbedtls_x509_time to check + * + * \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); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +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); +#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); +#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); + +#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 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crl.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crl.h new file mode 100644 index 00000000..75172d9e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crl.h @@ -0,0 +1,157 @@ +/* + * 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" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry { + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +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. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + 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 */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \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); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \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); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \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); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \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); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +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); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crt.h new file mode 100644 index 00000000..c7ea581f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crt.h @@ -0,0 +1,637 @@ +/* + * 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" +#else + #include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" +#include "x509_crl.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +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. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + 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 */ + 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. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +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 */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert { + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \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); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \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); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \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); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \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); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \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); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \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); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything but a fatal error. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs (see note above) + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * 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); + +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * 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); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (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); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extentedJeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \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); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \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); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +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); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \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); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \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); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \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); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \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); + +/** + * \brief Set the subject public key for the certificate + * + * \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); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \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); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \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); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \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); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \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); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \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); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \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); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * 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); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * 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); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/iot.mk new file mode 100644 index 00000000..5a90afd9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/.gitignore b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/.gitignore new file mode 100644 index 00000000..3a63a63a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/.gitignore @@ -0,0 +1,4 @@ +*.o +libmbed* +*.sln +*.vcxproj diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/Makefile b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/Makefile new file mode 100644 index 00000000..28f92315 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/Makefile @@ -0,0 +1,169 @@ + +# Also see "include/mbedtls/config.h" + +CFLAGS ?= -O2 +WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement +LDFLAGS ?= + +LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_LDFLAGS = + +ifdef DEBUG +LOCAL_CFLAGS += -g3 +endif + +# MicroBlaze specific options: +# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift + +# To compile on Plan9: +# CFLAGS += -D_BSD_EXTENSION + +# if were running on Windows build for Windows +ifdef WINDOWS +WINDOWS_BUILD=1 +endif + +# To compile as a shared library: +ifdef SHARED +# all code is position-indep with mingw, avoid warning about useless flag +ifndef WINDOWS_BUILD +LOCAL_CFLAGS += -fPIC -fpic +endif +endif + +SOEXT_TLS=so.10 +SOEXT_X509=so.0 +SOEXT_CRYPTO=so.0 + +DLEXT=so +# OSX shared library extension: +# DLEXT=dylib + +# Windows shared library extension: +ifdef WINDOWS_BUILD +DLEXT=dll +endif + +OBJS_CRYPTO= aes.o aesni.o arc4.o \ + asn1parse.o asn1write.o base64.o \ + bignum.o blowfish.o camellia.o \ + ccm.o cipher.o cipher_wrap.o \ + cmac.o ctr_drbg.o des.o \ + dhm.o ecdh.o ecdsa.o \ + ecjpake.o ecp.o \ + ecp_curves.o entropy.o entropy_poll.o \ + error.o gcm.o havege.o \ + hmac_drbg.o md.o md2.o \ + md4.o md5.o md_wrap.o \ + memory_buffer_alloc.o oid.o \ + padlock.o pem.o pk.o \ + pk_wrap.o pkcs12.o pkcs5.o \ + pkparse.o pkwrite.o platform.o \ + ripemd160.o rsa.o sha1.o \ + sha256.o sha512.o threading.o \ + timing.o version.o \ + version_features.o xtea.o + +OBJS_X509= certs.o pkcs11.o x509.o \ + x509_create.o x509_crl.o x509_crt.o \ + x509_csr.o x509write_crt.o x509write_csr.o + +OBJS_TLS= debug.o net_sockets.o \ + ssl_cache.o ssl_ciphersuites.o \ + ssl_cli.o ssl_cookie.o \ + ssl_srv.o ssl_ticket.o \ + ssl_tls.o + +.SILENT: + +.PHONY: all static shared clean + +ifndef SHARED +all: static +else +all: shared static +endif + +static: libmbedcrypto.a libmbedx509.a libmbedtls.a + +shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT) + +# tls +libmbedtls.a: $(OBJS_TLS) + echo " AR $@" + $(AR) -rc $@ $(OBJS_TLS) + echo " RL $@" + $(AR) -s $@ + +libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.so: libmbedtls.$(SOEXT_TLS) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedtls.dylib: $(OBJS_TLS) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -lmbedx509 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# x509 +libmbedx509.a: $(OBJS_X509) + echo " AR $@" + $(AR) -rc $@ $(OBJS_X509) + echo " RL $@" + $(AR) -s $@ + +libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.so: libmbedx509.$(SOEXT_X509) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedx509.dylib: $(OBJS_X509) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# crypto +libmbedcrypto.a: $(OBJS_CRYPTO) + echo " AR $@" + $(AR) -rc $@ $(OBJS_CRYPTO) + echo " RL $@" + $(AR) -s $@ + +libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedcrypto.dylib: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.dll: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +.c.o: + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< + +clean: +ifndef WINDOWS + rm -f *.o libmbed* +else + del /Q /F *.o libmbed* +endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/aes.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/aes.c new file mode 100644 index 00000000..d944aa40 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/aes.c @@ -0,0 +1,1481 @@ +/* + * 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 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include "mbedtls/debug.h" +#define mbedtls_printf tls_info +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_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(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_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 /* MBEDTLS_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 /* MBEDTLS_AES_ROM_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(MBEDTLS_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( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_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 /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_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: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_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(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_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 /* !MBEDTLS_AES_ENCRYPT_ALT */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_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 /* !MBEDTLS_AES_DECRYPT_ALT */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +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 i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_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 == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_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] ); + + mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +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 c; + size_t n = *iv_off; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_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 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_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 mbedtls_aes_crypt_cfb8( mbedtls_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 ); + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +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 c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_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 /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + int len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( v == MBEDTLS_AES_DECRYPT ) + { + mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); + + if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( v == MBEDTLS_AES_DECRYPT ) + { + mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[16]; + + mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); + + offset = 0; + mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + if( v == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_aes_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_AES_DECRYPT ) + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_ct[u], len ); + + mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + else + { + len = aes_test_ctr_len[u]; + memcpy( buf, aes_test_ctr_pt[u], len ); + + mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/asn1parse.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/asn1parse.c new file mode 100644 index 00000000..8a1a55ea --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/asn1parse.c @@ -0,0 +1,379 @@ +/* + * 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_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + mbedtls_asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if( *p < end ) + { + cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, + sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/base64.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/base64.c new file mode 100644 index 00000000..b31531f2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/base64.c @@ -0,0 +1,281 @@ +/* + * 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_BASE64_C) + +#include "mbedtls/base64.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( ( i + 1 ) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = j = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + x = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( x != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= j; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/bignum.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/bignum.c new file mode 100644 index 00000000..da75c466 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/bignum.c @@ -0,0 +1,2436 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { + volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; +} + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +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; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +{ + int ret; + mbedtls_mpi_uint r; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + + if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + /* + * Round up the buffer length to an even value to ensure that there is + * enough room for hexadecimal values that can be represented in an odd + * number of digits. + */ + n += 3 + ( ( n + 1 ) & 1 ); + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( --p >= s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j, n; + + for( n = 0; n < buflen; n++ ) + if( buf[n] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > n; i--, j++ ) + X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mbedtls_mpi_size( X ); + + if( buflen < n ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mbedtls_mpi subtraction + */ +static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret; + size_t n; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + mbedtls_mpi_init( &TB ); + + if( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi TA, TB; + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i++; j > 0; j-- ) + mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + if( T->n < N->n + 1 || T->p == NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); + + return( 0 ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + return( mpi_montmul( A, &U, N, mm, T ) ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( neg ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t lz, lzt; + mbedtls_mpi TG, TA, TB; + + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( size > MBEDTLS_MPI_MAX_SIZE ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, n, s; + mbedtls_mpi W, R, T, A, RR; + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + i = mbedtls_mpi_bitlen( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi XX; + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); +} + +/* + * Prime number generation + */ +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 ret; + size_t k, n; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mbedtls_mpi_bitlen( X ); + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); + + mbedtls_mpi_set_bit( X, nbits-1, 1 ); + + X->p[0] |= 1; + + if( dh_flag == 0 ) + { + while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); + } + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + { + break; + } + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher.c new file mode 100644 index 00000000..70967d4e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher.c @@ -0,0 +1,894 @@ +/* + * 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_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" + +#include +#include + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +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_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + } + + if( MBEDTLS_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) +{ + size_t actual_iv_size; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + size_t block_size = 0; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + + if ( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + copy_len = ilen % block_size; + if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) + copy_len = block_size; + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0xFF; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) +{ + if( NULL == ctx || + MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || + MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +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 ret; + size_t finish_olen; + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +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 ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +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 ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher_wrap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher_wrap.c new file mode 100644 index 00000000..2ff10638 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher_wrap.c @@ -0,0 +1,1433 @@ +/* + * 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_CIPHER_C) + +#include "mbedtls/cipher_internal.h" + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 16, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 16, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 8, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 8, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 8, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ctr_drbg.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ctr_drbg.c new file mode 100644 index 00000000..6b282c24 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ctr_drbg.c @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * The NIST SP 800-90 DRBGs are described in the following publucation. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow + * NIST tests to succeed (which require known length fixed entropy) + */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len, + size_t entropy_len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->entropy_len = entropy_len; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +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 ) +{ + return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, + MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ); + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + mbedtls_aes_free( &aes_ctx ); + + return( 0 ); +} + +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ); + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + return( 0 ); +} + +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + + if( add_len > 0 ) + { + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + 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 < 0) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* + * Gather entropy_len bytes of entropy to seed state + */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, + ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len; + + /* + * Add additional data + */ + if( additional && len ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* + * Reduce to 384 bits + */ + block_cipher_df( seed, seed, seedlen ); + + /* + * Update state + */ + ctr_drbg_update_internal( ctx, seed ); + ctx->reseed_counter = 1; + + return( 0 ); +} + +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 ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; + } + + if( add_len > 0 ) + { + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ); + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : + output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + ctr_drbg_update_internal( ctx, add_input ); + + ctx->reseed_counter++; + + return( 0 ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + fclose( f ); + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + } + + fclose( f ); + + mbedtls_ctr_drbg_update( ctx, buf, n ); + + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char entropy_source_pr[96] = + { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, + 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, + 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, + 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, + 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, + 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, + 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, + 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, + 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, + 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, + 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, + 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; + +static const unsigned char entropy_source_nopr[64] = + { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, + 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, + 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, + 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, + 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, + 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, + 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, + 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; + +static const unsigned char nonce_pers_pr[16] = + { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, + 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; + +static const unsigned char nonce_pers_nopr[16] = + { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, + 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; + +static const unsigned char result_pr[16] = + { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, + 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; + +static const unsigned char result_nopr[16] = + { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, + 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[16]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/debug.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/debug.c new file mode 100644 index 00000000..a5e3062a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy.c new file mode 100644 index 00000000..97381dbb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy.c @@ -0,0 +1,643 @@ +/* + * 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_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + memset( ctx, 0, sizeof(mbedtls_entropy_context) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_starts( &ctx->accumulator, 0 ); +#else + mbedtls_sha256_starts( &ctx->accumulator, 0 ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); +} + +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 index, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + index = ctx->source_count; + if( index >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[index].f_source = f_source; + ctx->source[index].p_source = p_source; + ctx->source[index].threshold = threshold; + ctx->source[index].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512( data, len, tmp, 0 ); +#else + mbedtls_sha256( data, len, tmp, 0 ); +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_update( &ctx->accumulator, header, 2 ); + mbedtls_sha512_update( &ctx->accumulator, p, use_len ); +#else + mbedtls_sha256_update( &ctx->accumulator, header, 2 ); + mbedtls_sha256_update( &ctx->accumulator, p, use_len ); +#endif + + return( 0 ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret, i, have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + return( ret ); + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + entropy_update( ctx, (unsigned char) i, buf, olen ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); + + return( 0 ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, done; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + done = 1; + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size < ctx->source[i].threshold ) + done = 0; + } + while( ! done ); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_finish( &ctx->accumulator, buf ); + + /* + * Reset accumulator and counters and recycle existing entropy + */ + memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); + mbedtls_sha512_starts( &ctx->accumulator, 0 ); + mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + /* + * Perform second SHA-512 on entropy + */ + mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + mbedtls_sha256_finish( &ctx->accumulator, buf ); + + /* + * Reset accumulator and counters and recycle existing entropy + */ + memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); + mbedtls_sha256_starts( &ctx->accumulator, 0 ); + mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + /* + * Perform second SHA-256 on entropy + */ + mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + { + fclose( f ); + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + } + + fclose( f ); + + mbedtls_entropy_update_manual( ctx, buf, n ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy_poll.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy_poll.c new file mode 100644 index 00000000..33d114d2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy_poll.c @@ -0,0 +1,254 @@ +/* + * 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_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include +/* Check if version is at least 3.17.0 */ +static int check_version_3_17_plus( void ) +{ + int minor; + struct utsname un; + const char *ver; + + /* Get version information */ + uname(&un); + ver = un.release; + + /* Check major version; assume a single digit */ + if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) + return( -1 ); + + if( ver[0] - '0' > 3 ) + return( 0 ); + + /* Ok, so now we know major == 3, check minor. + * Assume 1 or 2 digits. */ + if( ver[2] < '0' || ver[2] > '9' ) + return( -1 ); + + minor = ver[2] - '0'; + + if( ver[3] >= '0' && ver[3] <= '9' ) + minor = 10 * minor + ver[3] - '0'; + else if( ver [3] != '.' ) + return( -1 ); + + if( minor < 17 ) + return( -1 ); + + return( 0 ); +} +static int has_getrandom = -1; +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + ((void) data); + +#if defined(HAVE_GETRANDOM) + if( has_getrandom == -1 ) + has_getrandom = ( check_version_3_17_plus() == 0 ); + + if( has_getrandom ) + { + int ret; + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/error.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/error.c new file mode 100644 index 00000000..e2d84898 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/error.c @@ -0,0 +1,693 @@ +/* + * 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_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) +#include "mbedtls/error.h" +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#define mbedtls_time_t time_t +#endif + +#if defined(MBEDTLS_ERROR_C) + +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_CIPHER_C) + if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "DHM - Read/write of file failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); + if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) + mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) + mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) + mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) + mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) + mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) + mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) + mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) + mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) + mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) + mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) + mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) + mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) + mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) + mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) + mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) + mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) + mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) + mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) + mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) + mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_AES_C) + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) + mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); + if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); + if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); + if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_GCM_C) + if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_NET_C) + if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) + mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); + if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) + mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); + if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) + mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_THREADING_C) + if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) + mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); +#endif /* MBEDTLS_XTEA_C */ + // END generated code + + if( strlen( buf ) != 0 ) + return; + + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#else /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ + +#endif /* MBEDTLS_ERROR_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md.c new file mode 100644 index 00000000..0034b10f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md.c @@ -0,0 +1,453 @@ +/* + * 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_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + md_info->ctx_free_func( ctx->md_ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + ctx->md_info = md_info; + + return( 0 ); +} + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->starts_func( ctx->md_ctx ); + + return( 0 ); +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + md_info->digest_func( input, ilen, output ); + + return( 0 ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + md_info->starts_func( ctx.md_ctx ); + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + md_info->update_func( ctx.md_ctx, buf, n ); + + if( ferror( f ) != 0 ) + { + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + goto cleanup; + } + + md_info->finish_func( ctx.md_ctx, output ); + +cleanup: + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, key, keylen ); + ctx->md_info->finish_func( ctx->md_ctx, sum ); + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + mbedtls_zeroize( sum, sizeof( sum ) ); + + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); + + return( 0 ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->update_func( ctx->md_ctx, input, ilen ); + + return( 0 ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + ctx->md_info->finish_func( ctx->md_ctx, tmp ); + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); + ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); + ctx->md_info->finish_func( ctx->md_ctx, output ); + + return( 0 ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + ctx->md_info->starts_func( ctx->md_ctx ); + ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); + + return( 0 ); +} + +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 ) +{ + mbedtls_md_context_t ctx; + int ret; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &ctx, key, keylen ); + mbedtls_md_hmac_update( &ctx, input, ilen ); + mbedtls_md_hmac_finish( &ctx, output ); + + mbedtls_md_free( &ctx ); + + return( 0 ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info->process_func( ctx->md_ctx, data ); + + return( 0 ); +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md_wrap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md_wrap.c new file mode 100644 index 00000000..e3bfba01 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md_wrap.c @@ -0,0 +1,557 @@ +/* + * 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_MD_C) + +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_MD2_C) + +static void md2_starts_wrap( void *ctx ) +{ + mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); +} + +static void md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); +} + +static void md2_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); +} + +static void *md2_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); + + if( ctx != NULL ) + mbedtls_md2_init( (mbedtls_md2_context *) ctx ); + + return( ctx ); +} + +static void md2_ctx_free( void *ctx ) +{ + mbedtls_md2_free( (mbedtls_md2_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md2_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md2_clone( (mbedtls_md2_context *) dst, + (const mbedtls_md2_context *) src ); +} + +static void md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + mbedtls_md2_process( (mbedtls_md2_context *) ctx ); +} + +const mbedtls_md_info_t mbedtls_md2_info = { + MBEDTLS_MD_MD2, + "MD2", + 16, + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + mbedtls_md2, + md2_ctx_alloc, + md2_ctx_free, + md2_clone_wrap, + md2_process_wrap, +}; + +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + +static void md4_starts_wrap( void *ctx ) +{ + mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); +} + +static void md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); +} + +static void md4_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); +} + +static void *md4_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); + + if( ctx != NULL ) + mbedtls_md4_init( (mbedtls_md4_context *) ctx ); + + return( ctx ); +} + +static void md4_ctx_free( void *ctx ) +{ + mbedtls_md4_free( (mbedtls_md4_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md4_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md4_clone( (mbedtls_md4_context *) dst, + (const mbedtls_md4_context *) src ); +} + +static void md4_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_md4_info = { + MBEDTLS_MD_MD4, + "MD4", + 16, + 64, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + mbedtls_md4, + md4_ctx_alloc, + md4_ctx_free, + md4_clone_wrap, + md4_process_wrap, +}; + +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + +static void md5_starts_wrap( void *ctx ) +{ + mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); +} + +static void md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); +} + +static void md5_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); +} + +static void *md5_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); + + if( ctx != NULL ) + mbedtls_md5_init( (mbedtls_md5_context *) ctx ); + + return( ctx ); +} + +static void md5_ctx_free( void *ctx ) +{ + mbedtls_md5_free( (mbedtls_md5_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md5_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md5_clone( (mbedtls_md5_context *) dst, + (const mbedtls_md5_context *) src ); +} + +static void md5_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_md5_info = { + MBEDTLS_MD_MD5, + "MD5", + 16, + 64, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + mbedtls_md5, + md5_ctx_alloc, + md5_ctx_free, + md5_clone_wrap, + md5_process_wrap, +}; + +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + +static void ripemd160_starts_wrap( void *ctx ) +{ + mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); +} + +static void ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); +} + +static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); +} + +static void *ripemd160_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); + + if( ctx != NULL ) + mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); + mbedtls_free( ctx ); +} + +static void ripemd160_clone_wrap( void *dst, const void *src ) +{ + mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, + (const mbedtls_ripemd160_context *) src ); +} + +static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_ripemd160_info = { + MBEDTLS_MD_RIPEMD160, + "RIPEMD160", + 20, + 64, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + mbedtls_ripemd160, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_clone_wrap, + ripemd160_process_wrap, +}; + +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + +static void sha1_starts_wrap( void *ctx ) +{ + mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); +} + +static void sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); +} + +static void sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); +} + +static void *sha1_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); + + if( ctx != NULL ) + mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); + + return( ctx ); +} + +static void sha1_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, + (const mbedtls_sha1_context *) src ); +} + +static void sha1_ctx_free( void *ctx ) +{ + mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_sha1_info = { + MBEDTLS_MD_SHA1, + "SHA1", + 20, + 64, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + mbedtls_sha1, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_clone_wrap, + sha1_process_wrap, +}; + +#endif /* MBEDTLS_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(MBEDTLS_SHA256_C) + +static void sha224_starts_wrap( void *ctx ) +{ + mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); +} + +static void sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); +} + +static void sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); +} + +static void sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha256( input, ilen, output, 1 ); +} + +static void *sha224_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); + + if( ctx != NULL ) + mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); + + return( ctx ); +} + +static void sha224_ctx_free( void *ctx ) +{ + mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha224_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, + (const mbedtls_sha256_context *) src ); +} + +static void sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_sha224_info = { + MBEDTLS_MD_SHA224, + "SHA224", + 28, + 64, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +static void sha256_starts_wrap( void *ctx ) +{ + mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); +} + +static void sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha256( input, ilen, output, 0 ); +} + +const mbedtls_md_info_t mbedtls_sha256_info = { + MBEDTLS_MD_SHA256, + "SHA256", + 32, + 64, + sha256_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha256_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + +static void sha384_starts_wrap( void *ctx ) +{ + mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); +} + +static void sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); +} + +static void sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); +} + +static void sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha512( input, ilen, output, 1 ); +} + +static void *sha384_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); + + if( ctx != NULL ) + mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); + + return( ctx ); +} + +static void sha384_ctx_free( void *ctx ) +{ + mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha384_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, + (const mbedtls_sha512_context *) src ); +} + +static void sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); +} + +const mbedtls_md_info_t mbedtls_sha384_info = { + MBEDTLS_MD_SHA384, + "SHA384", + 48, + 128, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +static void sha512_starts_wrap( void *ctx ) +{ + mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); +} + +static void sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_sha512( input, ilen, output, 0 ); +} + +const mbedtls_md_info_t mbedtls_sha512_info = { + MBEDTLS_MD_SHA512, + "SHA512", + 64, + 128, + sha512_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha512_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +#endif /* MBEDTLS_SHA512_C */ + +#endif /* MBEDTLS_MD_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/net_sockets.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/net_sockets.c new file mode 100644 index 00000000..e035430b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/net_sockets.c @@ -0,0 +1,572 @@ +/* + * 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_NET_C) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/net_sockets.h" + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#include + +#include +#include + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0) +#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard fucntions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ + int ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + return( 0 ); + + switch( errno ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +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 ret; + int type; + + struct sockaddr_storage client_addr; + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { + struct sockaddr_storage local_addr; + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_storage ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/oid.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/oid.c new file mode 100644 index 00000000..ab461713 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/oid.c @@ -0,0 +1,694 @@ +/* + * 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_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ +static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ +{ \ + const TYPE_T *p = LIST; \ + const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + *ATTR2 = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_X509_EXT_NS_CERT_TYPE, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%d", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pem.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pem.c new file mode 100644 index 00000000..89f3b5a8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pem.c @@ -0,0 +1,435 @@ +/* + * 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_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static void pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + mbedtls_md5_starts( &md5_ctx ); + mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); + mbedtls_md5_update( &md5_ctx, iv, 8 ); + mbedtls_md5_finish( &md5_ctx, md5sum ); + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + + mbedtls_md5_free( &md5_ctx ); + mbedtls_zeroize( md5sum, 16 ); + return; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + mbedtls_md5_starts( &md5_ctx ); + mbedtls_md5_update( &md5_ctx, md5sum, 16 ); + mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); + mbedtls_md5_update( &md5_ctx, iv, 8 ); + mbedtls_md5_finish( &md5_ctx, md5sum ); + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + + mbedtls_md5_free( &md5_ctx ); + mbedtls_zeroize( md5sum, 16 ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static void pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + + mbedtls_des_init( &des_ctx ); + + pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); + + mbedtls_des_setkey_dec( &des_ctx, des_key ); + mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + + mbedtls_des_free( &des_ctx ); + mbedtls_zeroize( des_key, 8 ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static void pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + + mbedtls_des3_init( &des3_ctx ); + + pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); + + mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); + mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + + mbedtls_des3_free( &des3_ctx ); + mbedtls_zeroize( des3_key, 24 ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + + mbedtls_aes_init( &aes_ctx ); + + pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); + + mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); + mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + + mbedtls_aes_free( &aes_ctx ); + mbedtls_zeroize( aes_key, keylen ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +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 ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as heurisitic to try detecting password mismatchs. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + mbedtls_free( ctx->buf ); + mbedtls_free( ctx->info ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +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 ret; + unsigned char *encode_buf, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk.c new file mode 100644 index 00000000..24ee3c51 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk.c @@ -0,0 +1,369 @@ +/* + * 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_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#include "mbedtls/bignum.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return; + + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +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 ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* null or NONE context can't do anything */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +/* + * Verify a signature + */ +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 ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature with options + */ +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 ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if defined(MBEDTLS_HAVE_INT64) + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature + */ +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 ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Decrypt message + */ +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 ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +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 ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + if( pub == NULL || pub->pk_info == NULL || + prv == NULL || prv->pk_info == NULL || + prv->pk_info->check_pair_func == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* MBEDTLS_PK_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk_wrap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk_wrap.c new file mode 100644 index 00000000..952349b1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk_wrap.c @@ -0,0 +1,499 @@ +/* + * 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_PK_C) +#include "mbedtls/pk_internal.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + return( 8 * ((const mbedtls_rsa_context *) ctx)->len ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + +#if defined(MBEDTLS_HAVE_INT64) + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + + if( sig_len < ((mbedtls_rsa_context *) ctx)->len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + if( sig_len > ((mbedtls_rsa_context *) ctx)->len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *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 ) +{ +#if defined(MBEDTLS_HAVE_INT64) + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + + *sig_len = ((mbedtls_rsa_context *) ctx)->len; + + return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *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 ) +{ + if( ilen != ((mbedtls_rsa_context *) ctx)->len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *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 ) +{ + *olen = ((mbedtls_rsa_context *) ctx)->len; + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx, + f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *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 ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *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 ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#else + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *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 ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *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 ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if defined(MBEDTLS_HAVE_INT64) + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* MBEDTLS_HAVE_INT64 */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *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 ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#endif /* MBEDTLS_PK_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pkparse.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pkparse.c new file mode 100644 index 00000000..d4e7f9b6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pkparse.c @@ -0,0 +1,1279 @@ +/* + * 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_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_FS_IO) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + mbedtls_free( *buf ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret; + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + rsa->len = mbedtls_mpi_size( &rsa->N ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret; + size_t len; + unsigned char *p, *end; + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( rsa->ver != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) + { + mbedtls_rsa_free( rsa ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + rsa->len = mbedtls_mpi_size( &rsa->N ); + + if( p != end ) + { + mbedtls_rsa_free( rsa ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) + { + mbedtls_rsa_free( rsa ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char buf[2048]; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + memset( buf, 0, sizeof( buf ) ); + + p = (unsigned char *) key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len > sizeof( buf ) ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* + * Decrypt EncryptedData with appropriate PDE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const mbedtls_pk_info_t *pk_info; + +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) ret); + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, + pwd, pwdlen ) ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + key = pem.buf; + keylen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/platform.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/platform.c new file mode 100644 index 00000000..32523f5a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/platform.c @@ -0,0 +1,293 @@ +/* + * 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_PLATFORM_C) + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc = calloc_func; + mbedtls_free = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY */ + +#if defined(_WIN32) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret; + va_list argp; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + + va_start( argp, fmt ); +#if defined(_TRUNCATE) + ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); +#else + ret = _vsnprintf( s, n, fmt, argp ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return -1; + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +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 ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/rsa.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/rsa.c new file mode 100644 index 00000000..0c983d69 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/rsa.c @@ -0,0 +1,1846 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) +{ + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + */ +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 ret; + mbedtls_mpi P1, Q1, H, G; + + if( f_rng == NULL || nbits < 128 || exponent < 3 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( nbits % 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); + + /* + * find primes P and Q with Q < P so that: + * GCD( E, (P-1)*(Q-1) ) == 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, + f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, + f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + continue; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) + continue; + + if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + } + while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); + + /* + * D = E^-1 mod ((P-1)*(Q-1)) + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); + + ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; + +cleanup: + + mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + if( !ctx->N.p || !ctx->E.p ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( ( ctx->N.p[0] & 1 ) == 0 || + ( ctx->E.p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || + mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + return( 0 ); +} + +/* + * Check a private RSA key + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + int ret; + mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; + + if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) + return( ret ); + + if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); + mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); + mbedtls_mpi_init( &QP ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); + /* + * Check for a valid PKCS1v2 private key + */ + if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || + mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || + mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || + mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || + mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || + mbedtls_mpi_cmp_int( &I, 1 ) != 0 || + mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + +cleanup: + mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); + mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); + mbedtls_mpi_free( &QP ); + + if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + return( ret ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) +{ + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +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 ret; + size_t olen; + mbedtls_mpi T, T1, T2; + mbedtls_mpi P1, Q1, R; +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi D_blind; + mbedtls_mpi *D = &ctx->D; +#else + mbedtls_mpi DP_blind, DQ_blind; + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#endif + + /* Make sure we have private key info, prevent possible misuse */ + if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); + + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * T1 = input ^ dP mod P + * T2 = input ^ dQ mod Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (T1 - T2) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); + + /* + * T = T2 + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, src, slen ); + mbedtls_md_update( md_ctx, counter, 4 ); + mbedtls_md_finish( md_ctx, mask ); + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + + mbedtls_zeroize( mask, sizeof( mask ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +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 ) +{ + size_t olen; + int ret; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + /* Construct DB */ + mbedtls_md( md_info, label, label_len, p ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + return( ret ); + } + + /* maskedDB: Apply dbMask to DB */ + mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ); + + /* maskedSeed: Apply seedMask to seed */ + mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ); + + mbedtls_md_free( &md_ctx ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +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 ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + // We don't check p_rng because it won't be dereferenced here + if( f_rng == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +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 ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +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 ret; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + + /* Generate lHash */ + mbedtls_md( md_info, label, label_len, lhash ); + + /* seed: Apply seedMask to maskedSeed */ + mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ); + + /* DB: Apply dbMask to maskedDB */ + mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ); + + mbedtls_md_free( &md_ctx ); + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +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 ret; + size_t ilen, pad_count = 0, i; + unsigned char *p, bad, pad_done = 0; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + p = buf; + bad = 0; + + /* + * Check and get padding len in "constant-time" + */ + bad |= *p++; /* First byte must be 0 */ + + /* This test does not depend on secret data */ + if( mode == MBEDTLS_RSA_PRIVATE ) + { + bad |= *p++ ^ MBEDTLS_RSA_CRYPT; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + else + { + bad |= *p++ ^ MBEDTLS_RSA_SIGN; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ( p[i] != 0xFF ); + pad_count += ( pad_done == 0 ); + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + + bad |= ( pad_count < 8 ); + + if( bad ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +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) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +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 ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + /* No need to zeroize salt: we didn't use it. */ + return( ret ); + } + + /* Generate H = Hash( M' ) */ + mbedtls_md_starts( &md_ctx ); + mbedtls_md_update( &md_ctx, p, 8 ); + mbedtls_md_update( &md_ctx, hash, hashlen ); + mbedtls_md_update( &md_ctx, salt, slen ); + mbedtls_md_finish( &md_ctx, p ); + mbedtls_zeroize( salt, sizeof( salt ) ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); + + mbedtls_md_free( &md_ctx ); + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ +/* + * Do an RSA operation to sign the message digest + */ +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 ) +{ + size_t nb_pad, olen, oid_size = 0; + unsigned char *p = sig; + const char *oid = NULL; + unsigned char *sig_try = NULL, *verif = NULL; + size_t i; + unsigned char diff; + volatile unsigned char diff_no_optimize; + int ret; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + nb_pad = olen - 3; + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= 10 + oid_size; + + hashlen = mbedtls_md_get_size( md_info ); + } + + nb_pad -= hashlen; + + if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + } + else + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + memcpy( p, hash, hashlen ); + } + + if( mode == MBEDTLS_RSA_PUBLIC ) + return( mbedtls_rsa_public( ctx, sig, sig ) ); + + /* + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + /* Compare in constant time just in case */ + for( diff = 0, i = 0; i < ctx->len; i++ ) + diff |= verif[i] ^ sig[i]; + diff_no_optimize = diff; + + if( diff_no_optimize != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +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 ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +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 ret; + size_t siglen; + unsigned char *p; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t slen, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + slen = siglen - hlen - 1; /* Currently length of salt + padding */ + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + return( ret ); + } + + mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < buf + siglen && *p == 0 ) + p++; + + if( p == buf + siglen || + *p++ != 0x01 ) + { + mbedtls_md_free( &md_ctx ); + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } + + /* Actual salt len */ + slen -= p - buf; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + slen != (size_t) expected_salt_len ) + { + mbedtls_md_free( &md_ctx ); + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } + + /* + * Generate H = Hash( M' ) + */ + mbedtls_md_starts( &md_ctx ); + mbedtls_md_update( &md_ctx, zeros, 8 ); + mbedtls_md_update( &md_ctx, hash, hashlen ); + mbedtls_md_update( &md_ctx, p, slen ); + mbedtls_md_finish( &md_ctx, result ); + + mbedtls_md_free( &md_ctx ); + + if( memcmp( p + slen, result, hlen ) == 0 ) + return( 0 ); + else + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +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 ) +{ + mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +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 ret; + size_t len, siglen, asn1_len; + unsigned char *p, *end; + mbedtls_md_type_t msg_md_alg; + const mbedtls_md_info_t *md_info; + mbedtls_asn1_buf oid; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + while( *p != 0 ) + { + if( p >= buf + siglen - 1 || *p != 0xFF ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + p++; + } + p++; + + len = siglen - ( p - buf ); + + if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) + { + if( memcmp( p, hash, hashlen ) == 0 ) + return( 0 ); + else + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + } + + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hashlen = mbedtls_md_get_size( md_info ); + + end = p + len; + + /* + * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len + 2 != len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len + 6 + hashlen != len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + oid.p = p; + p += oid.len; + + if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( md_alg != msg_md_alg ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + /* + * assume the algorithm parameters must be NULL + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( asn1_len != hashlen ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( memcmp( p, hash, hashlen ) != 0 ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + p += hashlen; + + if( p != end ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +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 ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret; + + dst->ver = src->ver; + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); + mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +} + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ + "3C94D22288ACD763FD8E5600ED4A702D" \ + "F84198A5F06C2E72236AE490C93F07F8" \ + "3CC559CD27BC2D1CA488811730BB5725" + +#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ + "D8AAEA56749EA28623272E4F7D0592AF" \ + "7C1F1313CAC9471B5C523BFE592F517B" \ + "407A1BD76C164B93DA2D32A383E58357" + +#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ + "F38D18D2B2F0E2DD275AA977E2BF4411" \ + "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ + "A74206CEC169D74BF5A8C50D6F48EA08" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + rsa.len = KEY_LEN; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, + rsa_plaintext, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, + rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha1.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha1.c new file mode 100644 index 00000000..f6146f48 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha1.c @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA1_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_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 mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + *dst = *src; +} + +/* + * SHA-1 context setup + */ +void mbedtls_sha1_starts( mbedtls_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; +} + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +void mbedtls_sha1_process( mbedtls_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; +} +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +void mbedtls_sha1_update( mbedtls_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 ); + mbedtls_sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_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 mbedtls_sha1_finish( mbedtls_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 ); + + mbedtls_sha1_update( ctx, sha1_padding, padn ); + mbedtls_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 ); +} + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + mbedtls_sha1_starts( &ctx ); + mbedtls_sha1_update( &ctx, input, ilen ); + mbedtls_sha1_finish( &ctx, output ); + mbedtls_sha1_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + mbedtls_sha1_starts( &ctx ); + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + mbedtls_sha1_update( &ctx, buf, buflen ); + } + else + mbedtls_sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + + mbedtls_sha1_finish( &ctx, sha1sum ); + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha256.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha256.c new file mode 100644 index 00000000..7c8e1399 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha256.c @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#include "mbedtls/debug.h" + +#define mbedtls_printf tls_info +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA256_ALT) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + 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; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; +} + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +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 mbedtls_sha256_process( mbedtls_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(MBEDTLS_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 /* MBEDTLS_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 /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; +} +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +void mbedtls_sha256_update( mbedtls_sha256_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 ); + mbedtls_sha256_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_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 +}; + +/* + * SHA-256 final digest + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char 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 ); + + mbedtls_sha256_update( ctx, sha256_padding, padn ); + mbedtls_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 ); +} + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +void mbedtls_sha256( const unsigned char *input, size_t ilen, + unsigned char output[32], int is224 ) +{ + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + mbedtls_sha256_starts( &ctx, is224 ); + mbedtls_sha256_update( &ctx, input, ilen ); + mbedtls_sha256_finish( &ctx, output ); + mbedtls_sha256_free( &ctx ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const int sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + mbedtls_sha256_starts( &ctx, k ); + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + mbedtls_sha256_update( &ctx, buf, buflen ); + } + else + mbedtls_sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + + mbedtls_sha256_finish( &ctx, sha256sum ); + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_ciphersuites.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_ciphersuites.c new file mode 100644 index 00000000..1648ca7c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_ciphersuites.c @@ -0,0 +1,1841 @@ +/* + * 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_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except rc4, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All remaining >= 128-bit ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All remaining >= 128-bit suites */ + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) +#else + if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) +#endif + *(q++) = *p; + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cli.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cli.c new file mode 100644 index 00000000..e3415025 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cli.c @@ -0,0 +1,3391 @@ +/* + * 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_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + if( end < p || (size_t)( end - p ) < hostname_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + + if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t sig_alg_len = 0; + const int *md; +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + } + + if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *grp_id; +#else + ((void) ssl); +#endif + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); +#else + for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) + { +#endif + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); + return; + } + + elliptic_curve_len += 2; + } + + if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + elliptic_curve_len = 0; + +#if defined(MBEDTLS_ECP_C) + for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); +#else + for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) + { +#endif + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + if( elliptic_curve_len == 0 ) + return; + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; +} + +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); + + if( end < p || (size_t)( end - p ) < 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + /* + * We may need to send ClientHello multiple times for Hello verification. + * We don't want to compute fresh values every time (both for performance + * and consistency reasons), so cache the extension content. + */ + if( ssl->handshake->ecjpake_cache == NULL || + ssl->handshake->ecjpake_cache_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return; + } + + memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); + ssl->handshake->ecjpake_cache_len = kkpp_len; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); + + kkpp_len = ssl->handshake->ecjpake_cache_len; + + if( (size_t)( end - p - 2 ) < kkpp_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + + if( end < p || (size_t)( end - p ) < 5 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->conf->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " + "extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " + "extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); + + if( end < p || (size_t)( end - p ) < 4 + tlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( tlen ) & 0xFF ); + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; + + if( end < p || (size_t)( end - p ) < 6 + alpnlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + *p = (unsigned char)( strlen( *cur ) & 0xFF ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Generate random bytes for ClientHello + */ +static int ssl_generate_random( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *p = ssl->handshake->randbytes; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + + /* + * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie != NULL ) + { + return( 0 ); + } +#endif + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n, olen, ext_len = 0; + unsigned char *buf; + unsigned char *p, *q; + unsigned char offer_compress; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + } + + if( ssl->conf->max_major_ver == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, " + "consider using mbedtls_ssl_config_defaults()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ( ret = ssl_generate_random( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); + return( ret ); + } + + memcpy( p, ssl->handshake->randbytes, 32 ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); + p += 32; + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTSL only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + n = ssl->session_negotiate->id_len; + + if( n < 16 || n > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->id_len = n = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + + *p++ = ssl->handshake->verify_cookie_len; + memcpy( p, ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + p += ssl->handshake->verify_cookie_len; + } + } +#endif + + /* + * Ciphersuite list + */ + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + + /* Skip writing ciphersuite length for now */ + n = 0; + q = p; + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ciphersuite_info == NULL ) + continue; + + if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || + ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) + continue; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + continue; +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + continue; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + continue; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", + ciphersuites[i] ) ); + + n++; + *p++ = (unsigned char)( ciphersuites[i] >> 8 ); + *p++ = (unsigned char)( ciphersuites[i] ); + } + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); + n++; + } + + /* Some versions of OpenSSL don't handle it correctly if not at end */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); + n++; + } +#endif + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + offer_compress = 1; +#else + offer_compress = 0; +#endif + + /* + * We don't support compression with DTLS right now: is many records come + * in the same datagram, uncompressing one could overwrite the next one. + * We don't want to add complexity for handling that case unless there is + * an actual need for it. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + offer_compress = 0; +#endif + + if( offer_compress ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) ); + + *p++ = 2; + *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", + MBEDTLS_SSL_COMPRESS_NULL ) ); + + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + + // First write extensions, then the total length + // +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", + ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ssl_safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + list_size = buf[0]; + if( list_size + 1 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret; + + if( ssl->transform_negotiate->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + name_len = buf[2]; + if( name_len != list_len - 1 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_ZLIB_SUPPORT) + int accept_comp; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; +#if defined(MBEDTLS_DEBUG_C) + uint32_t t; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + buf = ssl->in_msg; + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " + " min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + +#if defined(MBEDTLS_DEBUG_C) + t = ( (uint32_t) buf[2] << 24 ) + | ( (uint32_t) buf[3] << 16 ) + | ( (uint32_t) buf[4] << 8 ) + | ( (uint32_t) buf[5] ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#endif + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + accept_comp = 0; + else +#endif + accept_comp = 1; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL && + ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) +#else /* MBEDTLS_ZLIB_SUPPORT */ + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) +#endif/* MBEDTLS_ZLIB_SUPPORT */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + + if( ssl->transform_negotiate->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); + + suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( suite_info == NULL +#if defined(MBEDTLS_ARC4_C) + || ( ssl->conf->arc4_disabled && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + if( comp != MBEDTLS_SSL_COMPRESS_NULL +#if defined(MBEDTLS_ZLIB_SUPPORT) + && comp != MBEDTLS_SSL_COMPRESS_DEFLATE +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); + + if( ( ret = ssl_parse_ecjpake_kkpp( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", + ssl->handshake->dhm_ctx.len * 8, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + + curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( (*p) + len > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret; + size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + + if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " + "HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " + "SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm " + "that was not offered" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ecp_keypair *peer_key; + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk ); + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + MBEDTLS_ECDH_THEIRS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + unsigned char *p, *end; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + ssl->record_read = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + size_t sig_len, hashlen; + unsigned char hash[64]; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( end != p + sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + hashlen = 36; + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + mbedtls_md5_starts( &mbedtls_md5 ); + mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); + mbedtls_md5_update( &mbedtls_md5, params, params_len ); + mbedtls_md5_finish( &mbedtls_md5, hash ); + + mbedtls_sha1_starts( &mbedtls_sha1 ); + mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); + mbedtls_sha1_update( &mbedtls_sha1, params, params_len ); + mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); + + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + mbedtls_md_context_t ctx; + + mbedtls_md_init( &ctx ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, + mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + return( ret ); + } + + mbedtls_md_starts( &ctx ); + mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); + mbedtls_md_update( &ctx, params, params_len ); + mbedtls_md_finish( &ctx, hash ); + mbedtls_md_free( &ctx ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : + (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * Verify signature + */ + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->record_read == 0 ) + { + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->record_read = 1; + } + + ssl->client_auth = 0; + ssl->state++; + + if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) + ssl->client_auth++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + goto exit; + + ssl->record_read = 0; + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + size_t i; + + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d,%d", sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ssl->record_read == 0 ) + { + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + ssl->record_read = 0; + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + n = ssl->handshake->dhm_ctx.len; + + ssl->out_msg[4] = (unsigned char)( n >> 8 ); + ssl->out_msg[5] = (unsigned char)( n ); + i = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + i = 4; + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &n, + &ssl->out_msg[i], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + i = 4; + n = ssl->conf->psk_identity_len; + + if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " + "SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); + i += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + n = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + n = ssl->handshake->dhm_ctx.len; + + if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" + " or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i++] = (unsigned char)( n >> 8 ); + ssl->out_msg[i++] = (unsigned char)( n ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, + &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + i = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + i = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = i + n; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + unsigned int hashlen; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make an RSA signature of the handshake digests + */ + ssl->handshake->calc_verify( ssl, hash ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + hashlen = 36; + md_alg = MBEDTLS_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and SHA224 + * in order to satisfy 'weird' needs from the server side. + */ + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); + ssl->out_msg[5 + offset] = (unsigned char)( n ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + mbedtls_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } +#endif + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cookie.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cookie.c new file mode 100644 index 00000000..ee1b9f9c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cookie.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( (size_t)( end - *p ) < COOKIE_LEN ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + (*p)[0] = (unsigned char)( t >> 24 ); + (*p)[1] = (unsigned char)( t >> 16 ); + (*p)[2] = (unsigned char)( t >> 8 ); + (*p)[3] = (unsigned char)( t ); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + if( ret != 0 ) + return( ret ); + + if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + return( -1 ); + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + return( -1 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_tls.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_tls.c new file mode 100644 index 00000000..38d967a8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_tls.c @@ -0,0 +1,7685 @@ +/* + * 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. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* Length of the "epoch" field in the record header */ +static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +static int ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = +{ + MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ + 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ + 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ + 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ + 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ +}; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_CLI_C) +static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( src->peer_cert != NULL ) + { + int ret; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +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 ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* + * Key material generation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t i; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + mbedtls_sha1_starts( &sha1 ); + mbedtls_sha1_update( &sha1, padding, 1 + i ); + mbedtls_sha1_update( &sha1, secret, slen ); + mbedtls_sha1_update( &sha1, random, rlen ); + mbedtls_sha1_finish( &sha1, sha1sum ); + + mbedtls_md5_starts( &md5 ); + mbedtls_md5_update( &md5, secret, slen ); + mbedtls_md5_update( &md5, sha1sum, 20 ); + mbedtls_md5_finish( &md5, dstbuf + i * 16 ); + } + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padding, sizeof( padding ) ); + mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char tmp[128]; + unsigned char h_i[20]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S1, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, S2, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char tmp[128]; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += md_len ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_zeroize( h_i, sizeof( h_i ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + unsigned char tmp[64]; + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t iv_copy_len; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + + mbedtls_ssl_session *session = ssl->session_negotiate; + mbedtls_ssl_transform *transform = ssl->transform_negotiate; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + transform->ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", + transform->ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * SSLv3: + * master = + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) + * + * TLSv1+: + * master = PRF( premaster, "master secret", randbytes )[0..47] + */ + if( handshake->resume == 0 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, + handshake->pmslen ); + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + unsigned char session_hash[48]; + size_t hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + + ssl->handshake->calc_verify( ssl, session_hash ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { +#if defined(MBEDTLS_SHA512_C) + if( ssl->transform_negotiate->ciphersuite_info->mac == + MBEDTLS_MD_SHA384 ) + { + hash_len = 48; + } + else +#endif + hash_len = 32; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + hash_len = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); + + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "extended master secret", + session_hash, hash_len, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + } + else +#endif + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + "master secret", + handshake->randbytes, 64, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + } + else + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + + /* + * Swap the client and server random values. + */ + memcpy( tmp, handshake->randbytes, 64 ); + memcpy( handshake->randbytes, tmp + 32, 32 ); + memcpy( handshake->randbytes + 32, tmp, 32 ); + mbedtls_zeroize( tmp, sizeof( tmp ) ); + + /* + * SSLv3: + * key block = + * MD5( master + SHA1( 'A' + master + randbytes ) ) + + * MD5( master + SHA1( 'BB' + master + randbytes ) ) + + * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + + * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + + * ... + * + * TLSv1: + * key block = PRF( master, "key expansion", randbytes ) + */ + ret = handshake->tls_prf( session->master, 48, "key expansion", + handshake->randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + transform->keylen = cipher_info->key_bitlen / 8; + + if( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->mode == MBEDTLS_MODE_CCM ) + { + transform->maclen = 0; + + transform->ivlen = 12; + transform->fixed_ivlen = 4; + + /* Minimum length is expicit IV + tag */ + transform->minlen = transform->ivlen - transform->fixed_ivlen + + ( transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + } + else + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + return( ret ); + } + + /* Get MAC length */ + transform->maclen = mbedtls_md_get_size( md_info ); + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV except for SSL3 and TLS 1.0 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", + transform->keylen, transform->minlen, transform->ivlen, + transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + transform->maclen * 2; + key2 = keyblk + transform->maclen * 2 + transform->keylen; + + mac_enc = keyblk; + mac_dec = keyblk + transform->maclen; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + transform->maclen * 2 + transform->keylen; + key2 = keyblk + transform->maclen * 2; + + mac_enc = keyblk + transform->maclen; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( transform->maclen > sizeof transform->mac_enc ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->mac_enc, mac_enc, transform->maclen ); + memcpy( transform->mac_dec, mac_dec, transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_init != NULL ) + { + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); + + if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + transform->maclen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( ssl->conf->f_export_keys != NULL ) + { + ssl->conf->f_export_keys( ssl->conf->p_export_keys, + session->master, keyblk, + transform->maclen, transform->keylen, + iv_copy_len ); + } +#endif + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( cipher_info->mode == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + mbedtls_zeroize( keyblk, sizeof( keyblk ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + // Initialize compression + // + if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update( &md5, pad_1, 48 ); + mbedtls_md5_finish( &md5, hash ); + + mbedtls_md5_starts( &md5 ); + mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update( &md5, pad_2, 48 ); + mbedtls_md5_update( &md5, hash, 16 ); + mbedtls_md5_finish( &md5, hash ); + + mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update( &sha1, pad_1, 40 ); + mbedtls_sha1_finish( &sha1, hash + 16 ); + + mbedtls_sha1_starts( &sha1 ); + mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update( &sha1, pad_2, 40 ); + mbedtls_sha1_update( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + mbedtls_md5_finish( &md5, hash ); + mbedtls_sha1_finish( &sha1, hash + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) +{ + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish( &sha256, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); + + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) +{ + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish( &sha512, hash ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); + + return; +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#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 ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = ssl->conf->psk; + size_t psk_len = ssl->conf->psk_len; + + /* If the psk callback was called, use its result */ + if( ssl->handshake->psk != NULL ) + { + psk = ssl->handshake->psk; + psk_len = ssl->handshake->psk_len; + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +/* + * SSLv3.0 MAC functions + */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, + unsigned char *buf, size_t len, + unsigned char *ctr, int type ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, header, 11 ); + mbedtls_md_update( md_ctx, buf, len ); + mbedtls_md_finish( md_ctx, buf + len ); + + memset( padding, 0x5C, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, buf + len, md_size ); + mbedtls_md_finish( md_ctx, buf + len ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) +#define SSL_SOME_MODES_USE_MAC +#endif + +/* + * Encryption/decryption functions + */ +static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( ssl->session_out == NULL || ssl->transform_out == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + /* + * Add MAC before if needed + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_out->md_ctx_enc, + ssl->transform_out->mac_enc, + ssl->out_msg, ssl->out_msglen, + ssl->out_ctr, ssl->out_msgtype ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_msg, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_msg + ssl->out_msglen ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", + ssl->out_msg + ssl->out_msglen, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* AEAD not the only option */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + ssl->out_msg, ssl->out_msglen, + ssl->out_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM ) + { + int ret; + size_t enc_msglen, olen; + unsigned char *enc_msg; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + /* + * Generate IV + */ + if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, + ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + /* + * Encrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + add_data, 13, + enc_msg, enc_msglen, + enc_msg, &olen, + enc_msg + enc_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + + if( olen != enc_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen += taglen; + auth_done++; + + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret; + unsigned char *enc_msg; + size_t enc_msglen, padlen, olen = 0, i; + + padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % + ssl->transform_out->ivlen; + if( padlen == ssl->transform_out->ivlen ) + padlen = 0; + + for( i = 0; i <= padlen; i++ ) + ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; + + ssl->out_msglen += padlen + 1; + + enc_msglen = ssl->out_msglen; + enc_msg = ssl->out_msg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( ssl->out_iv, ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->transform_out->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + ssl->out_msglen, ssl->transform_out->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, + enc_msg, enc_msglen, + enc_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( enc_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); + } +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, + ssl->out_iv, ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, + ssl->out_iv + ssl->out_msglen ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +#define SSL_MAX_MAC_SIZE 48 + +static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) +{ + size_t i; + mbedtls_cipher_mode_t mode; + int auth_done = 0; +#if defined(SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + + if( ssl->session_in == NULL || ssl->transform_in == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); + + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", + ssl->in_msglen, ssl->transform_in->minlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret; + size_t olen = 0; + + padlen = 0; + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + ssl->in_msg, ssl->in_msglen, + ssl->in_msg, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM ) + { + int ret; + size_t dec_msglen, olen; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + unsigned char add_data[13]; + unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_iv_len = ssl->transform_in->ivlen - + ssl->transform_in->fixed_ivlen; + + if( ssl->in_msglen < explicit_iv_len + taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", ssl->in_msglen, + explicit_iv_len, taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; + + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + ssl->in_msglen = dec_msglen; + + memcpy( add_data, ssl->in_ctr, 8 ); + add_data[8] = ssl->in_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, add_data + 9 ); + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, + ssl->in_iv, + ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + add_data, 13, + dec_msg, dec_msglen, + dec_msg_result, &olen, + dec_msg + dec_msglen, taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + if( olen != dec_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + /* + * Decrypt and check the padding + */ + int ret; + unsigned char *dec_msg; + unsigned char *dec_msg_result; + size_t dec_msglen; + size_t minlen = 0; + size_t olen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + minlen += ssl->transform_in->ivlen; +#endif + + if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || + ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", ssl->in_msglen, + ssl->transform_in->ivlen, + ssl->transform_in->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + dec_msglen = ssl->in_msglen; + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char computed_mac[SSL_MAX_MAC_SIZE]; + unsigned char pseudo_hdr[13]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + dec_msglen -= ssl->transform_in->maclen; + ssl->in_msglen -= ssl->transform_in->maclen; + + memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); + memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); + pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, + ssl->in_iv, ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac ); + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, + ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", computed_mac, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, + ssl->transform_in->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + ssl->in_msglen, ssl->transform_in->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + dec_msglen -= ssl->transform_in->ivlen; + ssl->in_msglen -= ssl->transform_in->ivlen; + + for( i = 0; i < ssl->transform_in->ivlen; i++ ) + ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, + dec_msg, dec_msglen, + dec_msg_result, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( dec_msglen != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); + } +#endif + + padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; + + if( ssl->in_msglen < ssl->transform_in->maclen + padlen && + auth_done == 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); +#endif + padlen = 0; + correct = 0; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( padlen > ssl->transform_in->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, ssl->transform_in->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * TLSv1+: always check the padding up to the first failure + * and fake check up to 256 bytes of padding + */ + size_t pad_count = 0, real_count = 1; + size_t padding_idx = ssl->in_msglen - padlen - 1; + + /* + * Padding is guaranteed to be incorrect if: + * 1. padlen >= ssl->in_msglen + * + * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + + * ssl->transform_in->maclen + * + * In both cases we reset padding_idx to a safe value (0) to + * prevent out-of-buffer reads. + */ + correct &= ( ssl->in_msglen >= padlen + 1 ); + correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + + ssl->transform_in->maclen ); + + padding_idx *= correct; + + for( i = 1; i <= 256; i++ ) + { + real_count &= ( i <= padlen ); + pad_count += real_count * + ( ssl->in_msg[padding_idx + i] == padlen - 1 ); + } + + correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_msglen -= padlen; + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + ssl->in_msg, ssl->in_msglen ); + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char tmp[SSL_MAX_MAC_SIZE]; + + ssl->in_msglen -= ssl->transform_in->maclen; + + ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); + ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); + + memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &ssl->transform_in->md_ctx_dec, + ssl->transform_in->mac_dec, + ssl->in_msg, ssl->in_msglen, + ssl->in_ctr, ssl->in_msgtype ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * Process MAC and always update for padlen afterwards to make + * total time independent of padlen + * + * extra_run compensates MAC check for padlen + * + * Known timing attacks: + * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) + * + * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values + * correctly. (We round down instead of up, so -56 is the correct + * value for our calculations instead of -55) + */ + size_t j, extra_run = 0; + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + + extra_run &= correct * 0xFF; + + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); + mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, + ssl->in_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, + ssl->in_msg + ssl->in_msglen ); + /* Call mbedtls_md_process at least once due to cache attacks */ + for( j = 0; j < extra_run + 1; j++ ) + mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + + mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + + if( mbedtls_ssl_safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif /* SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ssl->in_msglen == 0 ) + { + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->out_msg; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *msg_post = ssl->in_msg; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - + ssl->transform_in->ctx_inflate.avail_out; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret; + size_t len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* Just to be sure */ + if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split accross datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf, i; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + + ssl->out_msglen - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + ssl->out_left -= ret; + } + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); + memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + if( ssl->transform_out != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - + ssl->transform_out->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif +} + +/* + * Retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl_swap_epochs( ssl ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + int ret; + mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl_swap_epochs( ssl ); + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + ssl->handshake->cur_msg = cur->next; + + MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* Cancel timer */ + ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Record layer functions + */ + +/* + * Write current record. + * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0, out_msg_type; + size_t len = ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + ; /* Skip special handshake treatment when resending */ + } + else +#endif + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + out_msg_type = ssl->out_msg[0]; + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); + ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); + ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); + ssl->out_msglen += 8; + len += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* We don't fragment, so frag_offset = 0 and frag_len = len */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + } + + /* Save handshake and CCS messages for resending */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && + ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || + ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + } + + ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], + ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Reassemble fragmented DTLS handshake messages. + * + * Use a temporary buffer for reassembly, divided in two parts: + * - the first holds the reassembled message (including handshake header), + * - the second holds a bitmask indicating which parts of the message + * (excluding headers) have been received so far. + */ +static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) +{ + unsigned char *msg, *bitmask; + size_t frag_len, frag_off; + size_t msg_len = ssl->in_hslen - 12; /* Without headers */ + + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * For first fragment, check size and allocate buffer + */ + if( ssl->handshake->hs_msg == NULL ) + { + size_t alloc_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* The bitmask needs one bit per byte of message excluding header */ + alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); + + ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); + if( ssl->handshake->hs_msg == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); + memset( ssl->handshake->hs_msg + 6, 0, 3 ); + memcpy( ssl->handshake->hs_msg + 9, + ssl->handshake->hs_msg + 1, 3 ); + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + msg = ssl->handshake->hs_msg + 12; + bitmask = msg + msg_len; + + /* + * Check and copy current fragment + */ + frag_off = ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8]; + frag_len = ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11]; + + if( frag_off + frag_len > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", + frag_off, frag_len, msg_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( frag_len + 12 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", + frag_len, ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + ssl_bitmask_set( bitmask, frag_off, frag_len ); + + /* + * Do we have the complete message by now? + * If yes, finalize it, else ask to read the next record. + */ + if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); + + if( frag_len + 12 < ssl->in_msglen ) + { + /* + * We'got more handshake messages in the same record. + * This case is not handled now because no know implementation does + * that and it's hard to test, so we prefer to fail cleanly for now. + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( ssl->in_left > ssl->next_record_offset ) + { + /* + * We've got more data in the buffer after the current record, + * that we don't want to overwrite. Move it before writing the + * reassembled message, and adjust in_left and next_record_offset. + */ + unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; + unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; + size_t remain_len = ssl->in_left - ssl->next_record_offset; + + /* First compute and check new lengths */ + ssl->next_record_offset = new_remain - ssl->in_hdr; + ssl->in_left = ssl->next_record_offset + remain_len; + + if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memmove( new_remain, cur_remain, remain_len ); + } + + memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); + + mbedtls_free( ssl->handshake->hs_msg ); + ssl->handshake->hs_msg = NULL; + + MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", + ssl->in_msg, ssl->in_hslen ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( + ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + /* ssl->handshake is NULL when receiving ClientHello for renego */ + if( ssl->handshake != NULL && + recv_msg_seq != ssl->handshake->in_msg_seq ) + { + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Reassemble if current message is fragmented or reassembly is + * already in progress */ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || + ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + + if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); + return( ret ); + } + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->handshake != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + ssl->handshake->in_msg_seq++; + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* Forward declaration */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + if( f_cookie_write == NULL || f_cookie_check == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * mbedtls_ssl_read_record() will ignore the record if anything else than + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function + * cannot not return 0. + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t len; + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); + } + + if( ret == 0 ) + { + /* Got a valid cookie, partially reset context */ + if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) +{ + int ret; + int major_ver, minor_ver; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); + + ssl->in_msgtype = ssl->in_hdr[0]; + ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->in_msgtype, + major_ver, minor_ver, ssl->in_msglen ) ); + + /* Check record type */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && + ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) + { + return( ret ); + } + + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check version */ + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against the size of our buffer */ + if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN + - (size_t)( ssl->in_msg - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Check length against bounds of the current transform and version */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen < 1 || + ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif + } + + /* + * DTLS-related tests done last, because most of them may result in + * silently dropping the record (but not the whole datagram), and we only + * want to consider that after ensuring that the "basic" fields (type, + * version, length) are sane. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* Drop unexpected ChangeCipherSpec messages */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Check epoch (and sequence number) with DTLS */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + rec_epoch == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* Replay detection only works for the current epoch */ + if( rec_epoch == ssl->in_epoch && + mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +/* + * If applicable, decrypt (and decompress) record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + ssl->in_msg, ssl->in_msglen ); + + if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + return( 0 ); +} + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + do { + + if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + return( ret ); + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl->in_hslen != 0 && ssl->in_hslen < ssl->in_msglen ) + { + /* + * Get next Handshake message in the current record + */ + ssl->in_msglen -= ssl->in_hslen; + + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + + return( 0 ); + } + + ssl->in_hslen = 0; + + /* + * Read the record header and parse it + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +read_record_header: +#endif + + if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = ssl->in_msglen + + mbedtls_ssl_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + goto read_record_header; + } +#endif + return( ret ); + } + + /* + * Read and optionally decrypt the message contents + */ + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + + if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || + ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + goto read_record_header; + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + /* + * When we sent the last flight of the handshake, we MUST respond to a + * retransmit of the peer's previous flight with a retransmit. (In + * practice, only the Finished message will make it, other messages + * including CCS use the old transform so they're dropped as invalid.) + * + * If the record we received is not a handshake message, however, it + * means the peer received our last flight so we can clean up + * handshake info. + * + * This check needs to be done before prepare_handshake() due to an edge + * case: if the client immediately requests renegotiation, this + * finishes the current handshake first, avoiding the new ClientHello + * being mistaken for an ancient message in the current handshake. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + else + { + ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + int authmode = ssl->conf->authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; +#endif + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_SRV_C */ + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); + mbedtls_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, + sizeof( mbedtls_x509_crt ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + + i += 3; + + while( i < ssl->in_hslen ) + { + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + if( 0 != ret && ( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ) != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + /* + * On client, make sure the server cert doesn't change during renego to + * avoid "triple handshake" attack: https://secure-resumption.com/ + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->session->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + if( ssl->session->peer_cert->raw.len != + ssl->session_negotiate->peer_cert->raw.len || + memcmp( ssl->session->peer_cert->raw.p, + ssl->session_negotiate->peer_cert->raw.p, + ssl->session->peer_cert->raw.len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + if( ca_chain == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ); + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_with_profile( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + ret = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + + return( ret ); +} +#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); + } + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + /* + * Set the in_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_starts( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts( &ssl->handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_starts( &ssl->handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_starts( &ssl->handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); +} +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); +} +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + mbedtls_md5_update( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update( &md5, session->master, 48 ); + mbedtls_md5_update( &md5, padbuf, 48 ); + mbedtls_md5_finish( &md5, md5sum ); + + mbedtls_sha1_update( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update( &sha1, session->master, 48 ); + mbedtls_sha1_update( &sha1, padbuf, 40 ); + mbedtls_sha1_finish( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + mbedtls_md5_starts( &md5 ); + mbedtls_md5_update( &md5, session->master, 48 ); + mbedtls_md5_update( &md5, padbuf, 48 ); + mbedtls_md5_update( &md5, md5sum, 16 ); + mbedtls_md5_finish( &md5, buf ); + + mbedtls_sha1_starts( &sha1 ); + mbedtls_sha1_update( &sha1, session->master, 48 ); + mbedtls_sha1_update( &sha1, padbuf , 40 ); + mbedtls_sha1_update( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish( &sha1, buf + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padbuf[36]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_md5_finish( &md5, padbuf ); + mbedtls_sha1_finish( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_sha256_context sha256; + unsigned char padbuf[32]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA256_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_sha256_finish( &sha256, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha256_free( &sha256 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static void ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_sha512_context sha512; + unsigned char padbuf[48]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA512_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_sha512_finish( &sha512, padbuf ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_sha512_free( &sha512 ); + + mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and swith in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + /* + * Set the out_msg pointer to the correct location based on IV length + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - + ssl->transform_negotiate->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); + + /* Set sequence_number to zero */ + memset( ssl->out_ctr + 2, 0, 6 ); + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->out_ctr, 0, 8 ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define SSL_MAX_HASH_LEN 36 +#else +#define SSL_MAX_HASH_LEN 12 +#endif + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned int hash_len; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* There is currently no ciphersuite using another length with TLS 1.2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + hash_len = 36; + else +#endif + hash_len = 12; + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_init( &handshake->fin_md5 ); + mbedtls_sha1_init( &handshake->fin_sha1 ); + mbedtls_md5_starts( &handshake->fin_md5 ); + mbedtls_sha1_starts( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_init( &handshake->fin_sha256 ); + mbedtls_sha256_starts( &handshake->fin_sha256, 0 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts( &handshake->fin_sha512, 1 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + handshake->sig_alg = MBEDTLS_SSL_HASH_SHA1; + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif +} + +static void ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl->handshake ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + ssl_set_timer( ssl, 0 ); + } +#endif + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Setup an SSL context + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret; + const size_t len = MBEDTLS_SSL_BUFFER_LEN; + + ssl->conf = conf; + + /* + * Prepare base structures + */ + if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || + ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); + mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->out_ctr = ssl->out_buf + 3; + ssl->out_len = ssl->out_buf + 11; + ssl->out_iv = ssl->out_buf + 13; + ssl->out_msg = ssl->out_buf + 13; + + ssl->in_hdr = ssl->in_buf; + ssl->in_ctr = ssl->in_buf + 3; + ssl->in_len = ssl->in_buf + 11; + ssl->in_iv = ssl->in_buf + 13; + ssl->in_msg = ssl->in_buf + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_buf; + ssl->out_hdr = ssl->out_buf + 8; + ssl->out_len = ssl->out_buf + 11; + ssl->out_iv = ssl->out_buf + 13; + ssl->out_msg = ssl->out_buf + 13; + + ssl->in_ctr = ssl->in_buf; + ssl->in_hdr = ssl->in_buf + 8; + ssl->in_len = ssl->in_buf + 11; + ssl->in_iv = ssl->in_buf + 13; + ssl->in_msg = ssl->in_buf + 13; + } + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret; + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + /* Cancel any possibly running timer */ + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + + ssl->in_msg = ssl->in_buf + 13; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + if( partial == 0 ) + ssl->in_left = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + ssl_dtls_replay_reset( ssl ); +#endif + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + ssl->record_read = 0; + + ssl->out_msg = ssl->out_buf + 13; + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + if( partial == 0 ) + memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_reset != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); + if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + if( partial == 0 ) + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +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 ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +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 ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +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 *) ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; +} + +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ) +{ + if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return; + + if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + conf->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new; + + new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new->cert = cert; + new->key = key; + new->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +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 ) +{ + if( psk == NULL || psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* Identity len will be encoded on two bytes */ + if( ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( conf->psk != NULL || conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk = NULL; + conf->psk_identity = NULL; + } + + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || + ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) + { + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk = NULL; + conf->psk_identity = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + conf->psk_len = psk_len; + conf->psk_identity_len = psk_identity_len; + + memcpy( conf->psk, psk, conf->psk_len ); + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + return( 0 ); +} + +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ) +{ + if( psk == NULL || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->handshake->psk != NULL ) + mbedtls_free( ssl->handshake->psk ); + + if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->psk_len = psk_len; + memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); + + return( 0 ); +} + +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 ) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || + ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) +{ + int ret; + + if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ) +{ + conf->sig_hashes = hashes; +} +#endif + +#if defined(MBEDTLS_ECP_C) +/* + * Set the allowed elliptic curves + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list ) +{ + conf->curve_list = curve_list; +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + size_t hostname_len; + + if( hostname == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hostname_len = strlen( hostname ); + + if( hostname_len + 1 == 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->hostname, hostname, hostname_len ); + + ssl->hostname[hostname_len] = '\0'; + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) +{ + conf->fallback = fallback; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_ARC4_C) +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) +{ + conf->arc4_disabled = arc4; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) +{ + conf->trunc_hmac = truncate; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) +{ + conf->cbc_record_splitting = split; +} +#endif + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +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 ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + conf->f_export_keys = f_export_keys; + conf->p_export_keys = p_export_keys; +} +#endif + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "DTLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion; + const mbedtls_ssl_transform *transform = ssl->transform_out; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + transform_expansion = transform->maclen + + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = mfl_code_to_length[ssl->conf->mfl_code]; + + /* + * Check if a smaller max length was negotiated + */ + if( ssl->session_out != NULL && + mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + { + max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + } + + return max_len; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return( ssl->session->peer_cert ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ssl_session_copy( dst, ssl->session ) ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} + +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret, record_read = 0; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) + { + record_read = 1; + } + else if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + if( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ! record_read ) + { + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif + + if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * SSLv3 does not have a "no_renegotiation" alert + */ + if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else + { + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = ssl_start_renegotiation( ssl ); + if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) + { + record_read = 1; + } + else if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + + /* If a non-handshake record was read during renego, fallthrough, + * else tell the user they should call mbedtls_ssl_read() again */ + if( ! record_read ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + if( ssl->in_msglen == 0 ) + /* all bytes consumed */ + ssl->in_offt = NULL; + else + /* more data available */ + ssl->in_offt += n; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, + * taking care of max fragment length and buffer size + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); + + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %d > %d", + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + + if( ssl->out_left != 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data, doing 1/n-1 splitting if necessary. + * + * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, + * then the caller will call us again with the same arguments, so + * remember wether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); + + mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) +{ + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_free( &handshake->fin_md5 ); + mbedtls_sha1_free( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + mbedtls_free( handshake->hs_msg ); + ssl_flight_free( handshake->flight ); +#endif + + mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + } +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { + mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->out_buf ); + } + + if( ssl->in_buf != NULL ) + { + mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->in_buf ); + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_free( ssl->compress_buf ); + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_finish != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); + mbedtls_ssl_hw_record_finish( ssl ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; +#endif + +#if defined(MBEDTLS_ECP_C) +static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { + MBEDTLS_ECP_DP_SECP256R1, + MBEDTLS_ECP_DP_SECP384R1, + MBEDTLS_ECP_DP_NONE +}; +#endif + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_ARC4_C) + conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ( ret = mbedtls_ssl_conf_dh_param( conf, + MBEDTLS_DHM_RFC5114_MODP_2048_P, + MBEDTLS_DHM_RFC5114_MODP_2048_G ) ) != 0 ) + { + return( ret ); + } + } +#endif + + /* + * Preset-specific defaults + */ + switch( preset ) + { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_suiteb_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = ssl_preset_suiteb_curves; +#endif + break; + + /* + * Default + */ + default: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS 1.0 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; +#endif + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = mbedtls_ecp_grp_id_list(); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_zeroize( conf->psk, conf->psk_len ); + mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); + conf->psk_len = 0; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_group_id *gid; + + if( ssl->conf->curve_list == NULL ) + return( -1 ); + + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ + !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + + switch( md ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/timing.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/timing.c new file mode 100644 index 00000000..0a976b80 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/timing.c @@ -0,0 +1,565 @@ +/* + * 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_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include "mbedtls/debug.h" +#define mbedtls_printf tls_info +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +#if defined(_WIN32) +#include +#include + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else + #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; + FILETIME ft; + static int tzflag; + + if (NULL != tv) { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tmpres /= 10; + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) { + if (!tzflag) { + _tzset(); + tzflag++; + } + + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} +#else +#define mbedtls_gettimeofday gettimeofday +#endif /* defined(_WIN32) */ + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + mbedtls_gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + mbedtls_gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + unsigned long delta; + LARGE_INTEGER offset, hfreq; + struct _hr_time *t = (struct _hr_time *) val; + + QueryPerformanceCounter( &offset ); + QueryPerformanceFrequency( &hfreq ); + + delta = (unsigned long)( ( 1000 * + ( offset.QuadPart - t->start.QuadPart ) ) / + hfreq.QuadPart ); + + if( reset ) + QueryPerformanceCounter( &t->start ); + + return( delta ); +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static DWORD WINAPI TimerProc( LPVOID TimerContext ) +{ + ((void) TimerContext); + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + return( TRUE ); +} + +void mbedtls_set_alarm( int seconds ) +{ + DWORD ThreadId; + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + unsigned long delta; + struct timeval offset; + struct _hr_time *t = (struct _hr_time *) val; + + mbedtls_gettimeofday( &offset, NULL ); + + if( reset ) + { + t->start.tv_sec = offset.tv_sec; + t->start.tv_usec = offset.tv_usec; + return( 0 ); + } + + delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 + + ( offset.tv_usec - t->start.tv_usec ) / 1000; + + return( delta ); +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ +{ \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + return( 1 ); \ +} while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles, ratio; + unsigned long millisecs, secs; + int hardfail; + struct mbedtls_timing_hr_time hires; + uint32_t a, b; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + for( a = 200; a <= 400; a += 200 ) + { + for( b = 200; b <= 400; b += 200 ) + { + mbedtls_timing_set_delay( &ctx, a, a + b ); + + busy_msleep( a - a / 8 ); + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 ); + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b - a / 8 - b / 8 ); + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b / 4 ); + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + hardfail = 0; + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_TIMING_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509.c new file mode 100644 index 00000000..62ffca5e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509.c @@ -0,0 +1,1084 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) +#include +#include +#include +#endif +#endif + +#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +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 ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *time) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + + CHECK_RANGE( 0, 9999, time->year ); + CHECK_RANGE( 0, 23, time->hour ); + CHECK_RANGE( 0, 59, time->min ); + CHECK_RANGE( 0, 59, time->sec ); + + switch( time->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + CHECK_RANGE( 1, 31, time->day ); + break; + case 4: case 6: case 9: case 11: + CHECK_RANGE( 1, 30, time->day ); + break; + case 2: + CHECK_RANGE( 1, 28 + (time->year % 4 == 0), time->day ); + break; + default: + return( ret ); + } + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *time ) +{ + int ret; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &time->year ) ); + if ( 2 == yearlen ) + { + if ( time->year < 50 ) + time->year += 100; + + time->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &time->mon ) ); + CHECK( x509_parse_int( p, 2, &time->day ) ); + CHECK( x509_parse_int( p, 2, &time->hour ) ); + CHECK( x509_parse_int( p, 2, &time->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &time->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( time ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *time ) +{ + int ret; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, time ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +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 ret; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + if( *p == end ) + return( 0 ); + + ext->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) + return( ret ); + + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +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 ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + SYSTEMTIME st; + + GetSystemTime( &st ); + + now->year = st.wYear; + now->mon = st.wMonth; + now->day = st.wDay; + now->hour = st.wHour; + now->min = st.wMinute; + now->sec = st.wSecond; + + return( 0 ); +} +#else +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt; + mbedtls_time_t tt; + int ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + tt = mbedtls_time( NULL ); + lt = gmtime( &tt ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/certs.h" + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA1_C) + int ret; + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + mbedtls_x509_crt_init( &cacert ); + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); + + return( 0 ); +#else + ((void) verbose); + return( 0 ); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509_crt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509_crt.c new file mode 100644 index 00000000..f21c9889 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509_crt.c @@ -0,0 +1,2389 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ + /* Hashes from SHA-1 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk_alg acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg, + const mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( ret ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we only parse and use dNSName at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & MBEDTLS_ASN1_CONTEXT_SPECIFIC ) != MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + /* Skip everything but DNS name */ + if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + extn_oid.tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.p = *p; + *p += extn_oid.len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + // Use the original buffer until we figure out actual length + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + // Create and populate a new buffer for the raw field + crt->raw.len = crt_end - buf; + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, crt->raw.len ); + + // Direct pointers to the new buffer + p += crt->raw.len - len; + end = crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->version++; + + if( crt->version > 3 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_PTHREAD) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_PTHREAD) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + const char *sep = ""; + size_t sep_len = 0; + + while( cur != NULL ) + { + if( cur->buf.len + sep_len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + n -= cur->buf.len + sep_len; + for( i = 0; i < sep_len; i++ ) + *p++ = sep[i]; + for( i = 0; i < cur->buf.len; i++ ) + *p++ = cur->buf.p[i]; + + sep = ", "; + sep_len = 2; + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & type ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & code ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation is no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + crl_list->issuer_raw.len != ca->subject_raw.len || + memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, + crl_list->issuer_raw.len ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); + + if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( 0 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + * bottom means child is the end entity cert + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top, int bottom ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + /* Exception: self-signed end-entity certs that are locally trusted. */ + if( top && bottom && + child->raw.len == parent->raw.len && + memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) + { + need_ca_bit = 0; + } + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +static int x509_crt_verify_top( + mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, int self_cnt, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + uint32_t ca_flags = 0; + int check_path_cnt; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_x509_crt *future_past_ca = NULL; + + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* + * Child is the top of the chain. Check against the trust_ca list. + */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown', no need to try any CA + */ + trust_ca = NULL; + } + else + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + + for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) + { + if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) + continue; + + check_path_cnt = path_cnt + 1; + + /* + * Reduce check_path_cnt to check against if top of the chain is + * the same as the trusted CA + */ + if( child->subject_raw.len == trust_ca->subject_raw.len && + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) == 0 ) + { + check_path_cnt--; + } + + /* Self signed certificates do not count towards the limit */ + if( trust_ca->max_pathlen > 0 && + trust_ca->max_pathlen < check_path_cnt - self_cnt ) + { + continue; + } + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + continue; + } + + if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) || + mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + { + if ( future_past_ca == NULL ) + future_past_ca = trust_ca; + + continue; + } + + break; + } + + if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) + { + /* + * Top of chain is signed by a trusted CA + */ + *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + } + + /* + * If top of chain is not the same as the trusted CA send a verify request + * to the callback for any issues with validity and CRL presence for the + * trusted CA certificate. + */ + if( trust_ca != NULL && + ( child->subject_raw.len != trust_ca->subject_raw.len || + memcmp( child->subject_raw.p, trust_ca->subject_raw.p, + child->issuer_raw.len ) != 0 ) ) + { +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the chain's top crt */ + *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); +#else + ((void) ca_crl); +#endif + + if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) + ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, + &ca_flags ) ) != 0 ) + { + return( ret ); + } + } + } + + /* Call callback on top cert */ + if( NULL != f_vrfy ) + { + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + } + + *flags |= ca_flags; + + return( 0 ); +} + +static int x509_crt_verify_child( + mbedtls_x509_crt *child, mbedtls_x509_crt *parent, + mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, int self_cnt, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + uint32_t parent_flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + mbedtls_x509_crt *grandparent; + const mbedtls_md_info_t *md_info; + + /* Counting intermediate self signed certificates */ + if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + self_cnt++; + + /* path_cnt is 0 for the first intermediate CA */ + if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + } + + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( md_info == NULL ) + { + /* + * Cannot check 'unknown' hash + */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + else + { + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + + if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + } + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); +#endif + + /* Look for a grandparent in trusted CAs */ + for( grandparent = trust_ca; + grandparent != NULL; + grandparent = grandparent->next ) + { + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + if( grandparent != NULL ) + { + ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, + path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + /* Look for a grandparent upwards the chain */ + for( grandparent = parent->next; + grandparent != NULL; + grandparent = grandparent->next ) + { + /* +2 because the current step is not yet accounted for + * and because max_pathlen is one higher than it should be. + * Also self signed certificates do not count to the limit. */ + if( grandparent->max_pathlen > 0 && + grandparent->max_pathlen < 2 + path_cnt - self_cnt ) + { + continue; + } + + if( x509_crt_check_parent( parent, grandparent, + 0, path_cnt == 0 ) == 0 ) + break; + } + + /* Is our parent part of the chain or at the top? */ + if( grandparent != NULL ) + { + ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, + profile, path_cnt + 1, self_cnt, &parent_flags, + f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, + path_cnt + 1, self_cnt, &parent_flags, + f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + } + + /* child is verified to be a child of the parent, call verify callback */ + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) + return( ret ); + + *flags |= parent_flags; + + return( 0 ); +} + +/* + * Verify the certificate validity + */ +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 ) +{ + return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); +} + + +/* + * Verify the certificate validity, with profile + */ +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 ) +{ + size_t cn_len; + int ret; + int pathlen = 0, selfsigned = 0; + mbedtls_x509_crt *parent; + mbedtls_x509_name *name; + mbedtls_x509_sequence *cur = NULL; + mbedtls_pk_type_t pk_type; + + if( profile == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + *flags = 0; + + if( cn != NULL ) + { + name = &crt->subject; + cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + cur = &crt->subject_alt_names; + + while( cur != NULL ) + { + if( cur->buf.len == cn_len && + x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) + break; + + if( cur->buf.len > 2 && + memcmp( cur->buf.p, "*.", 2 ) == 0 && + x509_check_wildcard( cn, &cur->buf ) == 0 ) + { + break; + } + + cur = cur->next; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + while( name != NULL ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) + { + if( name->val.len == cn_len && + x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) + break; + + if( name->val.len > 2 && + memcmp( name->val.p, "*.", 2 ) == 0 && + x509_check_wildcard( cn, &name->val ) == 0 ) + break; + } + + name = name->next; + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + } + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Look for a parent in trusted CAs */ + for( parent = trust_ca; parent != NULL; parent = parent->next ) + { + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + } + + if( parent != NULL ) + { + ret = x509_crt_verify_top( crt, parent, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + /* Look for a parent upwards the chain */ + for( parent = crt->next; parent != NULL; parent = parent->next ) + if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) + break; + + /* Are we part of the chain or at the top? */ + if( parent != NULL ) + { + ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + else + { + ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, + pathlen, selfsigned, flags, f_vrfy, p_vrfy ); + if( ret != 0 ) + return( ret ); + } + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/iot.mk new file mode 100644 index 00000000..3b184824 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/iot.mk @@ -0,0 +1,2 @@ +LIBA_TARGET := libiot_nghttp2.a +HDR_REFS += src/infra diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2.h new file mode 100644 index 00000000..8b96d25d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.c new file mode 100644 index 00000000..b40d5672 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.h new file mode 100644 index 00000000..7e33a528 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.c new file mode 100644 index 00000000..a2f7e3fb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.h new file mode 100644 index 00000000..542df190 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.c new file mode 100644 index 00000000..6533f989 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.h new file mode 100644 index 00000000..6fed6ea0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.c new file mode 100644 index 00000000..76c919ec --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.h new file mode 100644 index 00000000..07aeb8b7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.c new file mode 100644 index 00000000..d7e80a23 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.h new file mode 100644 index 00000000..584dad39 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.c new file mode 100644 index 00000000..661668de --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.h new file mode 100644 index 00000000..979f6b12 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman_data.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman_data.c new file mode 100644 index 00000000..085b2e92 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.c new file mode 100644 index 00000000..8d80eb98 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.h new file mode 100644 index 00000000..be85fd2f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.c new file mode 100644 index 00000000..49caa100 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.h new file mode 100644 index 00000000..bde7023d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_int.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_int.h new file mode 100644 index 00000000..56c071a4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.c new file mode 100644 index 00000000..9de8299a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.h new file mode 100644 index 00000000..48096a2d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.c new file mode 100644 index 00000000..5a669731 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.h new file mode 100644 index 00000000..be33ac5d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.c new file mode 100644 index 00000000..c71af3e1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.h new file mode 100644 index 00000000..b1adc401 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.c new file mode 100644 index 00000000..0527ec94 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.h new file mode 100644 index 00000000..c9fe50c9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.c new file mode 100644 index 00000000..1d62f5b6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.h new file mode 100644 index 00000000..16b64e09 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.c new file mode 100644 index 00000000..3d35983d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.h new file mode 100644 index 00000000..33918356 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.c new file mode 100644 index 00000000..79aa1562 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.h new file mode 100644 index 00000000..a527db13 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.c new file mode 100644 index 00000000..b3d64e60 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.h new file mode 100644 index 00000000..d5f99564 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.c new file mode 100644 index 00000000..4c45dfe0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.h new file mode 100644 index 00000000..3ffdc14a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.c new file mode 100644 index 00000000..0fc440eb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.h new file mode 100644 index 00000000..edb1c59b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.c new file mode 100644 index 00000000..6299b0f5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.h new file mode 100644 index 00000000..c67781f8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.c new file mode 100644 index 00000000..e3d2b1e4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.h new file mode 100644 index 00000000..7ff69281 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.c new file mode 100644 index 00000000..dedf86e8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.h new file mode 100644 index 00000000..4d35029a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_version.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_version.c new file mode 100644 index 00000000..1b21d39c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2ver.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2ver.h new file mode 100644 index 00000000..28ededcd --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.bat b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.bat new file mode 100644 index 00000000..61d8cd6e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.sh b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.sh new file mode 100644 index 00000000..248f8124 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.sh @@ -0,0 +1,399 @@ +#! /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() +{ + CHECK_OS=$(uname -r | grep 'ali') + if [ "${OS}" = "Linux" ] && [ "${CHECK_OS}" = "" ]; 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" + +FUNC_NAME_LIST="" +HEADER_FILE_LIST="" + +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} ./src -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}" + # echo -e "\n${FUNC_DEC}" + + FUNC_FILE=$(grep ${func} ./wrappers/os/ubuntu/* | gawk -F':' '{print $1}' | sed -n 's/.\/wrappers\///g;s/\//\\\//g;p' | sed -n '1,1p') + if [ "${FUNC_FILE}" = "" ];then + FUNC_FILE=$(grep ${func} ./wrappers/tls/* | gawk -F':' '{print $1}' | sed -n 's/.\/wrappers\///g;s/\//\\\//g;p' | sed -n '1,1p') + fi + # echo -e "\n${FUNC_FILE}" + + sed -n '/WRAPPER_FUNC_REFERENCE:/{:a;N;/*\//!ba;p}' ${WRAPPER_DOC} | sed -n '1d;s/FUNC_NAME/'${func}'/g;s/FUNC_FILE/'${FUNC_FILE}'/g;p' >> ${WRAPPERS_DIR}/wrapper.c + 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/^ *//1;/;/{s/;/\n{\n\treturn;\n}\n\n/g};p' >> ${WRAPPERS_DIR}/wrapper.c + else + echo "${FUNC_DEC}" | sed -n 's/^ *//1;/;/{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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/make.settings b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/make.settings new file mode 100644 index 00000000..b2fcb7c9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/make.settings @@ -0,0 +1,88 @@ +# +# 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/makefile b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/makefile new file mode 100644 index 00000000..00c5c086 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/makefile @@ -0,0 +1,37 @@ +include tools/project.mk +include make.settings +include tools/default_settings.mk +include tools/parse_make_settings.mk +include $(RULE_DIR)/funcs.mk + +# CFLAGS += -DINSPECT_MQTT_FLOW + +COMP_LIB := libiot_sdk.a +COMP_LIB_COMPONENTS := \ + 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) + +include $(RULE_DIR)/rules.mk +include tools/mock_build_options.mk + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/model.json b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/model.json new file mode 100644 index 00000000..9989387b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.c new file mode 100644 index 00000000..fd8073d4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.h new file mode 100644 index 00000000..e46c57cb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.c new file mode 100644 index 00000000..e43ee54d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.h new file mode 100644 index 00000000..a3a05c94 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.c new file mode 100644 index 00000000..15113704 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.h new file mode 100644 index 00000000..7131fefb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.c new file mode 100644 index 00000000..9b1c7eed --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.h new file mode 100644 index 00000000..4eea8338 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.c new file mode 100644 index 00000000..ec6e1e2e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.h new file mode 100644 index 00000000..1d2eb168 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_tcp.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_tcp.c new file mode 100644 index 00000000..fbece6e1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_wrapper.h new file mode 100644 index 00000000..9a350294 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/iot.mk new file mode 100644 index 00000000..0e3647ec --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize.h new file mode 100644 index 00000000..8d0cef68 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize_common.c new file mode 100644 index 00000000..c034a795 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize_common.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#include +#include +#include "iotx_coap_internal.h" + +int CoAPDeserialize_Header(CoAPMessage *msg, unsigned char *buf) +{ + msg->header.version = ((buf[0] >> 6) & 0x03); + msg->header.type = ((buf[0] >> 4) & 0x03); + msg->header.tokenlen = (buf[0] & 0x0F); + msg->header.code = buf[1]; + msg->header.msgid = buf[2] << 8; + msg->header.msgid += buf[3]; + + return 4; +} + +int CoAPDeserialize_Token(CoAPMessage *msg, unsigned char *buf) +{ + memcpy(msg->token, buf, msg->header.tokenlen); + return msg->header.tokenlen; +} + +static int CoAPDeserialize_Option(CoAPMsgOption *option, unsigned char *buf, unsigned short *predeltas) +{ + unsigned char *ptr = buf; + unsigned short optdelta = 0; + unsigned short optlen = 0; + unsigned short predelta = 0; + + optdelta = (*ptr & 0xF0) >> 4; + optlen = (*ptr & 0x0F); + ptr++; + + predelta = *predeltas; + if (13 == optdelta) { + predelta += 13 + *ptr; + ptr ++; + + } else if (14 == optdelta) { + predelta += 269; + predelta += (*ptr << 8); + predelta += *(ptr + 1); + ptr += 2; + } else { + predelta += optdelta; + } + option->num = predelta; + + if (13 == optlen) { + optlen = 13 + *ptr; + ptr ++; + } else if (14 == optlen) { + optlen = 269; + optlen += (*ptr << 8); + optlen += *(ptr + 1); + ptr += 2; + } + option->len = optlen; + + option->val = ptr; + *predeltas = option->num; + + return (ptr - buf + option->len); +} + +int CoAPDeserialize_Options(CoAPMessage *msg, unsigned char *buf, int buflen) +{ + int index = 0; + int count = 0; + unsigned char *ptr = buf; + unsigned short len = 0; + unsigned short optdeltas = 0; + + msg->optcount = 0; + while ((count < buflen) && (0xFF != *ptr)) { + len = CoAPDeserialize_Option(&msg->options[index], ptr, &optdeltas); + msg->optcount += 1; + ptr += len; + index ++; + count += len; + } + + return (int)(ptr - buf); +} + +int CoAPDeserialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen) +{ + unsigned char *ptr = buf; + + if (0xFF == *ptr) { + ptr ++; + } else { + return 0; + } + msg->payloadlen = buflen - 1; + msg->payload = (unsigned char *)ptr; + + return buflen; +} + +int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen) +{ + int count = 0; + int remlen = buflen; + unsigned char *ptr = buf; + + if (NULL == buf || NULL == msg) { + return COAP_ERROR_INVALID_PARAM; + } + + if (buflen < 4) { + return COAP_ERROR_INVALID_LENGTH; + } + + /* Deserialize CoAP header. */ + count = CoAPDeserialize_Header(msg, ptr); + ptr += count; + remlen -= count; + + /* Deserialize the token, if any. */ + count = CoAPDeserialize_Token(msg, ptr); + ptr += count; + remlen -= count; + + count = CoAPDeserialize_Options(msg, ptr, remlen); + ptr += count; + remlen -= count; + + CoAPDeserialize_Payload(msg, ptr, remlen); + + return COAP_SUCCESS; +} diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPMessage_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPMessage_common.c new file mode 100644 index 00000000..47e6104f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPPlatform.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPPlatform.h new file mode 100644 index 00000000..02f6eca0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize.h new file mode 100644 index 00000000..4a8177d1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize_common.c new file mode 100644 index 00000000..ae2f0d89 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize_common.c @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#include +#include +#include "CoAPSerialize.h" +#include "iotx_coap_internal.h" + +int CoAPSerialize_Header(CoAPMessage *msg, unsigned char *buf, unsigned short buflen) +{ + if(4 > buflen){ + return 0; + } + buf[0] = (((msg->header.version & 0x3) << 6) | ((msg->header.type & 0x3) << 4)) + | (msg->header.tokenlen & 0x0F); + + buf[1] = msg->header.code; + buf[2] = (msg->header.msgid & 0xFF00) >> 8; + buf[3] = (msg->header.msgid & 0x00FF); + + return 4; +} + +int CoAPSerialize_Token(CoAPMessage *msg, unsigned char * buf, unsigned short buflen) +{ + int i = 0; + + if(buflen < msg->header.tokenlen){ + return 0; + } + for (i = 0; i < msg->header.tokenlen; i++){ + buf[i] = msg->token[i]; + } + return msg->header.tokenlen; +} + +static unsigned short CoAPSerialize_Option(CoAPMsgOption *option, unsigned char *buf) +{ + unsigned char *ptr = buf; + + if(269 <= option->num){ + *ptr = ((14 & 0x0F) << 4); + } + else if(13 <= option->num){ + *ptr = ((13 & 0x0F) << 4); + } + else{ + *ptr = option->num << 4; + } + + if (269 <= option->len){ + *ptr |= (14 & 0x0F); + } + else if(13 <= option->len){ + *ptr |= (13 & 0x0F); + } + else{ + *ptr |= (option->len & 0x0F); + } + ptr ++; + + if (269 <= option->num){ + *ptr = (unsigned char)(((option->num - 269) & 0xFF00) >> 8); + *(ptr+1) = (unsigned char)(((option->num - 269) & 0x00FF)); + ptr += 2; + } + else if(13 <= option->num){ + *ptr = (unsigned char)(option->num - 13); + ptr ++; + } + + + if (269 <= option->len){ + *ptr = (unsigned char)(((option->len - 269) & 0xFF00) >> 8); + *(ptr+1) = (unsigned char)(((option->len - 269) & 0x00FF)); + ptr += 2; + } + else if(13 <= option->len){ + *ptr = (unsigned char)(option->len - 13); + ptr ++; + } + + + memcpy(ptr, option->val, option->len); + ptr += option->len; + + return (int)(ptr - buf); +} + +unsigned short CoAPSerialize_Options(CoAPMessage *msg, unsigned char * buf, unsigned short buflen) +{ + int i = 0; + unsigned short count = 0; + + for (i = 0; i < msg->optcount; i++) + { + unsigned short len = 0; + len = CoAPSerialize_Option(&msg->options[i], &buf[count]); + if (0 < len){ + count += len; + } + else{ + return 0; + } + } + + return count; +} + +static unsigned short CoAPSerialize_OptionLen(CoAPMsgOption *option) +{ + unsigned short len = 1; + + if(269 <= option->num){ + len += 2; + } + else if(13 <= option->num){ + len += 1; + } + else{ + } + + if (269 <= option->len){ + len += 2; + } + else if(13 <= option->len){ + len += 1; + } + else{ + } + + len += option->len; + return len; +} + + +unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg) +{ + int i = 0; + unsigned short count = 0; + + for (i = 0; i < msg->optcount; i++) + { + unsigned short len = 0; + len = CoAPSerialize_OptionLen(&msg->options[i]); + if (0 < len){ + count += len; + } + else{ + return 0; + } + } + + return count; +} + + +int CoAPSerialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen) +{ + if(msg->payloadlen + 1 > buflen){ + return 0; + } + if(msg->payloadlen > 0 && NULL != msg->payload) + { + *buf = 0xFF; + buf ++; + memcpy(buf, msg->payload, msg->payloadlen); + return msg->payloadlen + 1; + } + else{ + return 0; + } +} + + +unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg) +{ + unsigned short msglen = 4; + + msglen += msg->header.tokenlen; + msglen += CoAPSerialize_OptionsLen(msg); + + if(0 < msg->payloadlen){ + msglen += msg->payloadlen; + msglen += 1; /*CoAP payload marker*/ + } + + return msglen; +} + +int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen) +{ + unsigned char *ptr = buf; + unsigned short count = 0; + unsigned short remlen = buflen; + + if(NULL == buf || NULL == msg){ + return COAP_ERROR_INVALID_PARAM; + } + + count = CoAPSerialize_Header(msg, ptr, remlen); + ptr += count; + remlen -= count; + + count = CoAPSerialize_Token(msg, ptr, remlen); + ptr += count; + remlen -= count; + + count = CoAPSerialize_Options(msg, ptr, remlen); + ptr += count; + remlen -= count; + + count = CoAPSerialize_Payload(msg, ptr, remlen); + ptr += count; + remlen -= count; + + return (buflen-remlen); +} diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPExport.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPExport.h new file mode 100644 index 00000000..5e0016cd --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPMessage.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPMessage.h new file mode 100644 index 00000000..5899698b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPNetwork.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPNetwork.h new file mode 100644 index 00000000..43ec5b1e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPPlatform.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPPlatform.h new file mode 100644 index 00000000..8e8da178 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPExport.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPExport.c new file mode 100644 index 00000000..5c9a6dea --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPExport.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + +#include +#include +#include +#include "iotx_coap_internal.h" +#include "ctype.h" +#include "Cloud_CoAPPlatform.h" +#include "Cloud_CoAPNetwork.h" +#include "Cloud_CoAPExport.h" + +#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */ +#define COAPS_DEFAULT_PORT 5684 /* CoAP default UDP port for secure transmission */ + +#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */ +#define COAP_DEFAULT_HOST_LEN 128 +#define COAP_DEFAULT_WAIT_TIME_MS 2000 + +unsigned int Cloud_CoAPUri_parse(char *p_uri, coap_endpoint_type *p_endpoint_type, + char host[COAP_DEFAULT_HOST_LEN], unsigned short *port) +{ + int len = 0; + char *p = NULL, *q = NULL; + if (NULL == p_uri || NULL == p_endpoint_type) { + return COAP_ERROR_INVALID_PARAM; + } + + COAP_DEBUG("The uri is %s", p_uri); + len = strlen(p_uri); + p = p_uri; + q = (char *)COAP_DEFAULT_SCHEME; + while (len && *q && tolower(*p) == *q) { + ++p; + ++q; + --len; + } + + if (*q) { + return COAP_ERROR_INVALID_URI; + } + if (tolower(*p) == 's') { + ++p; + --len; + *p_endpoint_type = COAP_ENDPOINT_DTLS; + *port = COAPS_DEFAULT_PORT; + } else if (*p == '-') { + ++p; + --len; + q = (char *)"psk"; + while (len && *q && tolower(*p) == *q) { + ++p; + ++q; + --len; + } + if (*q) { + return COAP_ERROR_INVALID_URI; + } + *p_endpoint_type = COAP_ENDPOINT_PSK; + *port = COAP_DEFAULT_PORT; + } else { + *p_endpoint_type = COAP_ENDPOINT_NOSEC; + *port = COAP_DEFAULT_PORT; + } + COAP_DEBUG("The endpoint type is: %d", *p_endpoint_type); + + q = (char *)"://"; + while (len && *q && tolower(*p) == *q) { + ++p; + ++q; + --len; + } + + if (*q) { + return COAP_ERROR_INVALID_URI; + } + + q = p; + while (len && *q != ':') { + ++q; + --len; + } + if (p == q) { + return COAP_ERROR_INVALID_URI; + } + + if (COAP_DEFAULT_HOST_LEN - 1 < (q - p)) { + return COAP_ERROR_INVALID_URI; + } else { + memset(host, 0x00, COAP_DEFAULT_HOST_LEN); + strncpy(host, p, q - p); + } + COAP_DEBUG("The host name is: %s", host); + if (len && *q == ':') { + p = ++q; + --len; + + while (len && isdigit(*q)) { + ++q; + --len; + } + + if (p < q) { + int uri_port = 0; + + while (p < q) { + uri_port = uri_port * 10 + (*p++ - '0'); + } + + if (uri_port > 65535) { + return COAP_ERROR_INVALID_URI; + } + *port = uri_port; + } + } + COAP_DEBUG("The port is: %d", *port); + + return COAP_SUCCESS; +} + + +Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param) +{ + unsigned int ret = COAP_SUCCESS; + Cloud_CoAPContext *p_ctx = NULL; + coap_network_init_t network_param; + char host[COAP_DEFAULT_HOST_LEN] = {0}; + + memset(&network_param, 0x00, sizeof(coap_network_init_t)); + p_ctx = coap_malloc(sizeof(Cloud_CoAPContext)); + if (NULL == p_ctx) { + COAP_ERR("malloc for coap context failed"); + goto err; + } + + memset(p_ctx, 0, sizeof(Cloud_CoAPContext)); + p_ctx->message_id = 1; + p_ctx->notifier = param->notifier; + p_ctx->sendbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN); + if (NULL == p_ctx->sendbuf) { + COAP_ERR("not enough memory"); + goto err; + } + + p_ctx->recvbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN); + if (NULL == p_ctx->recvbuf) { + COAP_ERR("not enough memory"); + goto err; + } + + if (0 == param->waittime) { + p_ctx->waittime = COAP_DEFAULT_WAIT_TIME_MS; + } else { + p_ctx->waittime = param->waittime; + } + + /*CoAP message send list*/ + INIT_LIST_HEAD(&p_ctx->list.sendlist); + p_ctx->list.count = 0; + p_ctx->list.maxcount = param->maxcount; + + /*set the endpoint type by uri schema*/ + if (NULL != param->url) { + ret = Cloud_CoAPUri_parse(param->url, &network_param.ep_type, host, &network_param.port); + } + + if (COAP_SUCCESS != ret) { + goto err; + } + +#ifdef COAP_DTLS_SUPPORT + if (COAP_ENDPOINT_DTLS == network_param.ep_type) { + extern const char *iotx_ca_crt; + network_param.p_ca_cert_pem = (unsigned char *)iotx_ca_crt; + } +#endif + if (COAP_ENDPOINT_NOSEC == network_param.ep_type + || COAP_ENDPOINT_PSK == network_param.ep_type) { + network_param.p_ca_cert_pem = NULL; + } + network_param.p_host = host; + + /*CoAP network init*/ + ret = Cloud_CoAPNetwork_init(&network_param, &p_ctx->network); + + if (COAP_SUCCESS != ret) { + goto err; + } + + return p_ctx; +err: + if (NULL == p_ctx) { + return p_ctx; + } + + if (NULL != p_ctx->recvbuf) { + coap_free(p_ctx->recvbuf); + p_ctx->recvbuf = NULL; + } + + if (NULL != p_ctx->sendbuf) { + coap_free(p_ctx->sendbuf); + p_ctx->sendbuf = NULL; + } + + coap_free(p_ctx); + p_ctx = NULL; + + return p_ctx; +} + +void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx) +{ + Cloud_CoAPSendNode *cur, *next; + + if (NULL == p_ctx) { + return; + } + + Cloud_CoAPNetwork_deinit(&p_ctx->network); + + list_for_each_entry_safe(cur, next, &p_ctx->list.sendlist, sendlist, Cloud_CoAPSendNode) { + if (NULL != cur) { + if (NULL != cur->message) { + coap_free(cur->message); + cur->message = NULL; + } + coap_free(cur); + cur = NULL; + } + } + + if (NULL != p_ctx->recvbuf) { + coap_free(p_ctx->recvbuf); + p_ctx->recvbuf = NULL; + } + + if (NULL != p_ctx->sendbuf) { + coap_free(p_ctx->sendbuf); + p_ctx->sendbuf = NULL; + } + + + if (NULL != p_ctx) { + coap_free(p_ctx); + p_ctx = NULL; + } +} diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPMessage.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPMessage.c new file mode 100644 index 00000000..4214d880 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPNetwork.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPNetwork.c new file mode 100644 index 00000000..68847070 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPNetwork.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#include +#include +#include +#include + +#include "iotx_coap_internal.h" +#include "Cloud_CoAPExport.h" +#include "Cloud_CoAPNetwork.h" + +#ifdef COAP_DTLS_SUPPORT +static void *Cloud_CoAPDTLS_Malloc(uint32_t size) +{ +#ifdef INFRA_MEM_STATS + return LITE_malloc(size, MEM_MAGIC, "dtls"); +#else + return HAL_Malloc(size); +#endif +} +static void Cloud_CoAPDTLS_Free(void *ptr) +{ +#ifdef INFRA_MEM_STATS + LITE_free(ptr); +#else + HAL_Free((void *)ptr); +#endif +} + +static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session); + +unsigned int Cloud_CoAPNetworkDTLS_read(void *p_session, + unsigned char *p_data, + unsigned int *p_datalen, + unsigned int timeout) +{ + unsigned int err_code = DTLS_SUCCESS; + const unsigned int read_len = *p_datalen; + DTLSContext *context = NULL; + + COAP_TRC("<< secure_datagram_read, read buffer len %d, timeout %d", read_len, timeout); + (void)read_len; + if (NULL != p_session) { + /* read dtls application data*/ + context = (DTLSContext *)p_session; + err_code = HAL_DTLSSession_read(context, p_data, p_datalen, timeout); + if (DTLS_PEER_CLOSE_NOTIFY == err_code + || DTLS_FATAL_ALERT_MESSAGE == err_code) { + COAP_INFO("dtls session read failed, return (0x%04x)", err_code); + Cloud_CoAPNetworkDTLS_freeSession(context); + } + if (DTLS_SUCCESS == err_code) { + return COAP_SUCCESS; + } else { + return COAP_ERROR_READ_FAILED; + } + } + + return COAP_ERROR_INVALID_PARAM; +} + +unsigned int Cloud_CoAPNetworkDTLS_write(void *p_session, + const unsigned char *p_data, + unsigned int *p_datalen) +{ + unsigned int err_code = DTLS_SUCCESS; + if (NULL != p_session) { + err_code = HAL_DTLSSession_write((DTLSContext *)p_session, p_data, p_datalen); + if (DTLS_SUCCESS == err_code) { + return COAP_SUCCESS; + } else { + return COAP_ERROR_WRITE_FAILED; + } + } + return COAP_ERROR_INVALID_PARAM; +} + +static void Cloud_CoAPNetworkDTLS_freeSession(void *p_session) +{ + /* Free the session.*/ + HAL_DTLSSession_free((DTLSContext *)p_session); +} + +void *Cloud_CoAPNetworkDTLS_createSession(char *p_host, + unsigned short port, + unsigned char *p_ca_cert_pem) +{ + DTLSContext *context = NULL; + dtls_hooks_t dtls_hooks; + coap_dtls_options_t dtls_options; + + memset(&dtls_hooks, 0, sizeof(dtls_hooks_t)); + dtls_hooks.malloc = Cloud_CoAPDTLS_Malloc; + dtls_hooks.free = Cloud_CoAPDTLS_Free; + + HAL_DTLSHooks_set(&dtls_hooks); + + memset(&dtls_options, 0x00, sizeof(coap_dtls_options_t)); + dtls_options.p_ca_cert_pem = p_ca_cert_pem; + dtls_options.p_host = p_host; + dtls_options.port = port; + + context = HAL_DTLSSession_create(&dtls_options); + return (void *)context; +} + +#endif + +unsigned int Cloud_CoAPNetwork_write(coap_network_t *p_network, + const unsigned char *p_data, + unsigned int datalen) +{ + int rc = COAP_ERROR_WRITE_FAILED; + +#ifdef COAP_DTLS_SUPPORT + if (COAP_ENDPOINT_DTLS == p_network->ep_type) { + rc = Cloud_CoAPNetworkDTLS_write(p_network->context, p_data, &datalen); + } else { +#endif + rc = HAL_UDP_write((intptr_t)p_network->context, p_data, datalen); + COAP_DEBUG("[CoAP-NWK]: Network write return %d", rc); + + if (-1 == rc) { + rc = COAP_ERROR_WRITE_FAILED; + } else { + rc = COAP_SUCCESS; + } +#ifdef COAP_DTLS_SUPPORT + } +#endif + return (unsigned int)rc; +} + +int Cloud_CoAPNetwork_read(coap_network_t *network, unsigned char *data, + unsigned int datalen, unsigned int timeout) +{ + int len = 0; + +#ifdef COAP_DTLS_SUPPORT + if (COAP_ENDPOINT_DTLS == network->ep_type) { + len = datalen; + memset(data, 0x00, datalen); + Cloud_CoAPNetworkDTLS_read(network->context, data, (unsigned int *)&len, timeout); + } else { +#endif + memset(data, 0x00, datalen); + len = HAL_UDP_readTimeout((intptr_t)network->context, + data, COAP_MSG_MAX_PDU_LEN, timeout); +#ifdef COAP_DTLS_SUPPORT + } +#endif + if (len > 0) { + COAP_TRC("<< CoAP recv %d bytes data", len); + } + return len; +} + +unsigned int Cloud_CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t *p_network) +{ + unsigned int err_code = COAP_SUCCESS; + + if (NULL == p_param || NULL == p_network) { + return COAP_ERROR_INVALID_PARAM; + } + + /* TODO : Parse the url here */ + p_network->ep_type = p_param->ep_type; + +#ifdef COAP_DTLS_SUPPORT + if (COAP_ENDPOINT_DTLS == p_param->ep_type) { + p_network->context = Cloud_CoAPNetworkDTLS_createSession(p_param->p_host, + p_param->port, p_param->p_ca_cert_pem); + if (NULL == p_network->context) { + return COAP_ERROR_NET_INIT_FAILED; + } + } +#endif + if (COAP_ENDPOINT_NOSEC == p_param->ep_type + || COAP_ENDPOINT_PSK == p_param->ep_type) { + /*Create udp socket*/ + p_network->context = (void *)HAL_UDP_create(p_param->p_host, p_param->port); + if ((void *) - 1 == p_network->context) { + return COAP_ERROR_NET_INIT_FAILED; + } + } + return err_code; +} + + +unsigned int Cloud_CoAPNetwork_deinit(coap_network_t *p_network) +{ + unsigned int err_code = COAP_SUCCESS; + +#ifdef COAP_DTLS_SUPPORT + if (COAP_ENDPOINT_DTLS == p_network->ep_type) { + Cloud_CoAPNetworkDTLS_freeSession(p_network->context); + p_network->context = NULL; + } +#endif + if (COAP_ENDPOINT_NOSEC == p_network->ep_type + || COAP_ENDPOINT_PSK == p_network->ep_type) { + HAL_UDP_close_without_connect((intptr_t)p_network->context); + } + + return err_code; +} + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/README.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/README.md new file mode 100644 index 00000000..1fb7b45c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/iotx_coap_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/iotx_coap_api.c new file mode 100644 index 00000000..3888cd30 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/iotx_coap_api.c @@ -0,0 +1,952 @@ +/* +* 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 + 1] = {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; + } + if(node.value_length > 32) { + return IOTX_ERR_BUFF_TOO_SHORT; + } + 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/coap_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/coap_api.h new file mode 100644 index 00000000..29599682 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/coap_api.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __IOTX_COAP_API_H__ +#define __IOTX_COAP_API_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "infra_defs.h" + +/*iotx return code definition*/ +typedef enum { + IOTX_ERR_RECV_MSG_TIMEOUT = -9, /*Receive message timeout */ + IOTX_ERR_SEND_MSG_FAILED = -8, /* Send message failed*/ + IOTX_ERR_MSG_TOO_LOOG = -7, /* The payload too loog */ + IOTX_ERR_URI_TOO_LOOG = -6, /* URI length too long */ + IOTX_ERR_NOT_AUTHED = -5, /* Client isn't authed */ + IOTX_ERR_AUTH_FAILED = -4, /* Client authed failed */ + IOTX_ERR_BUFF_TOO_SHORT = -3, /* Buffer too short */ + IOTX_ERR_NO_MEM = -2, /* Malloc failed */ + IOTX_ERR_INVALID_PARAM = -1, /* Invalid parameter */ + IOTX_SUCCESS = 0, /* Success */ +} iotx_ret_code_t; + +/* The message payload encode format */ +typedef enum { + IOTX_CONTENT_TYPE_JSON, + IOTX_CONTENT_TYPE_CBOR, +} iotx_content_type_t; + +/* The message type */ +typedef enum { + IOTX_MESSAGE_CON = 0, /* confirmable message */ + IOTX_MESSAGE_NON = 1, /* non-confirmable message */ + IOTX_MESSAGE_ACK = 2, /* acknowledgement message */ + IOTX_MESSAGE_RST = 3, /* reset message */ +} iotx_msg_type_t; + +/* IoTx events to notify application */ +typedef enum { + IOTX_COAP_EVENT_SEND_FAILED = 0, + IOTX_COAP_EVENT_RECV_FAILED = 1, + IOTX_COAP_EVENT_AUTH_FAILED = 2, +} iotx_coap_event_t; + +typedef enum { + IOTX_COAP_RESP_CODE_CONTENT = 0x45, /* Mapping to 2.05, Content*/ + IOTX_COAP_RESP_CODE_BAD_REQUEST = 0x80, /* Mapping to 4.00, Bad Request*/ + IOTX_COAP_RESP_CODE_UNAUTHORIZED = 0x81, /* Mapping to 4.01, Token is invalid or expire*/ + IOTX_COAP_RESP_CODE_NOT_FOUND = 0x84, /* Mapping to 4.04, Path or uri is not found*/ + IOTX_COAP_RESP_CODE_URL_TOO_LONG = 0x8E, /* Mapping to 4.14, The request url is too long*/ + IOTX_COAP_RESP_CODE_INTERNAL_SERVER_ERROR = 0xA0,/* Mapping to 5.00, Internal server error*/ + +} iotx_coap_resp_code_t; + +/* Callback function to notify the application events.*/ +typedef void (*iotx_event_handle_t)(void *context, iotx_coap_event_t event, void *p_data); + +/*IoTx device*/ +typedef struct { + char product_key[IOTX_PRODUCT_KEY_LEN + 1]; + char device_name[IOTX_DEVICE_NAME_LEN + 1]; + char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2]; + char device_secret[IOTX_DEVICE_SECRET_LEN + 1]; +} iotx_deviceinfo_t; + +typedef struct { + char product_key[IOTX_PRODUCT_KEY_LEN + 1]; + char device_name[IOTX_DEVICE_NAME_LEN + 1]; + char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2]; + char device_secret[IOTX_DEVICE_SECRET_LEN + 1]; + char module_vendor_id[IOTX_PARTNER_ID_LEN + 1]; +} iotx_device_info_t; + +/* IoTx initializa parameters */ +typedef struct { + char *p_url; /*Can be NULL*/ + int wait_time_ms; /*unit is micro second*/ + iotx_device_info_t *p_devinfo; /*Device info*/ + iotx_event_handle_t event_handle; /*TODO, not supported now*/ +} iotx_coap_config_t; + +/* Callback function to handle the response message.*/ +typedef void (*iotx_response_callback_t)(void *p_arg, void *p_message); + +/* IoTx message definition */ +typedef struct { + unsigned char *p_payload; + unsigned short payload_len; + iotx_content_type_t content_type; + iotx_msg_type_t msg_type; + void *user_data; + iotx_response_callback_t resp_callback; +} iotx_message_t; + + +/*iotx coap context definition*/ +typedef void iotx_coap_context_t; + + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_coap coap + * @{ + */ + +/** + * @brief Initialize the CoAP client. + * This function initialize the data structures and network, + * and create the DTLS session. + * + * @param [in] p_config: Specify the CoAP client parameter. + * + * @retval NULL : Initialize failed. + * @retval NOT_NULL : The contex of CoAP client. + * @see None. + */ +iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config); + +/** + * @brief De-initialize the CoAP client. + * This function release CoAP DTLS session. + * and release the related resource. + * + * @param [in] p_context: Pointer of contex, specify the CoAP client. + * + * @return None. + * @see None. + */ +void IOT_CoAP_Deinit(iotx_coap_context_t **p_context); + + +/** + * @brief Handle device name authentication with remote server. + * + * @param [in] p_context: Pointer of contex, specify the CoAP client. + * + * @retval IOTX_SUCCESS : Authenticate success. + * @retval IOTX_ERR_SEND_MSG_FAILED : Send authentication message failed. + * @retval IOTX_ERR_AUTH_FAILED : Authenticate failed or timeout. + * @see iotx_ret_code_t. + */ +int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context); + + +/** + * @brief Handle CoAP response packet from remote server, + * and process timeout request etc.. + * + * @param [in] p_context : Pointer of contex, specify the CoAP client. + * + * @return status. + * @see iotx_ret_code_t. + */ +int IOT_CoAP_Yield(iotx_coap_context_t *p_context); + + +/** + * @brief Send a message with specific path to server. + * Client must authentication with server before send message. + * + * @param [in] p_context : Pointer of contex, specify the CoAP client. + * @param [in] p_path: Specify the path name. + * @param [in] p_message: Message to be sent. + * + * @retval IOTX_SUCCESS : Send the message success. + * @retval IOTX_ERR_MSG_TOO_LOOG : The message length is too long. + * @retval IOTX_ERR_NOT_AUTHED : The client hasn't authenticated with server + * @see iotx_ret_code_t. + */ +int IOT_CoAP_SendMessage(iotx_coap_context_t *p_context, char *p_path, iotx_message_t *p_message); + +/** +* @brief Retrieves the length and payload pointer of specified message. +* +* @param [in] p_message: Pointer to the message to get the payload. Should not be NULL. +* @param [out] pp_payload: Pointer to the payload. +* @param [out] p_len: Size of the payload. +* +* @retval IOTX_SUCCESS : Get the payload success. +* @retval IOTX_ERR_INVALID_PARAM : Can't get the payload due to invalid parameter. +* @see iotx_ret_code_t. +**/ +int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload, int *p_len); + +/** +* @brief Get the response code from a CoAP message. +* +* @param [in] p_message: Pointer to the message to add the address information to. +* Should not be NULL. +* @param [out] p_resp_code: The response code. +* +* @retval IOTX_SUCCESS : When get the response code to message success. +* @retval IOTX_ERR_INVALID_PARAM : Pointer to the message is NULL. +* @see iotx_ret_code_t. +**/ +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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/coap_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/coap_wrapper.h new file mode 100644 index 00000000..1419f555 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/examples/coap_example.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/examples/coap_example.c new file mode 100644 index 00000000..78e71ab1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iot.mk new file mode 100644 index 00000000..b53a2ea0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iot.mk @@ -0,0 +1,13 @@ +LIBA_TARGET := libiot_coap.a +HDR_REFS := src/infra +LIB_SRCS_PATTERN := *.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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap.h new file mode 100644 index 00000000..e557ef7a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap.h @@ -0,0 +1,2 @@ +#include "CoAPServer.h" +#include "iotx_coap_internal.h" diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap_config.h new file mode 100644 index 00000000..489903e3 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/iotx_coap_internal.h new file mode 100644 index 00000000..364634e6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPExport.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPExport.c new file mode 100644 index 00000000..d6e03973 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPExport.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPExport.h new file mode 100644 index 00000000..bf2b9aab --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPInternal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPInternal.h new file mode 100644 index 00000000..b5441be4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPMessage.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPMessage.c new file mode 100644 index 00000000..69e96311 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPMessage.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPMessage.h new file mode 100644 index 00000000..f5b43506 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPNetwork.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPNetwork.c new file mode 100644 index 00000000..86755443 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPNetwork.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPNetwork.h new file mode 100644 index 00000000..361d640e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPObserve.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPObserve.c new file mode 100644 index 00000000..34450703 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPObserve.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPObserve.h new file mode 100644 index 00000000..8ecc78a1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPPlatform.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPPlatform.c new file mode 100644 index 00000000..7468cbf5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPResource.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPResource.c new file mode 100644 index 00000000..a5872a88 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPResource.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPResource.h new file mode 100644 index 00000000..eee5ed1a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPServer.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPServer.c new file mode 100644 index 00000000..03b70e8a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPServer.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/CoAPServer.h new file mode 100644 index 00000000..795ef514 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/README.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/server/README.md new file mode 100644 index 00000000..5929bdfd --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/dev_bind_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/dev_bind_api.h new file mode 100644 index 00000000..98b76a0a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/dev_bind_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/dev_bind_wrapper.h new file mode 100644 index 00000000..2e1f3e4f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_bind.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_bind.c new file mode 100644 index 00000000..3931bb82 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_bind_statis.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_bind_statis.c new file mode 100644 index 00000000..a2533cba --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_bind_statis.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_bind_statis.h new file mode 100644 index 00000000..9fb5b7ae --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_cmp.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_cmp.h new file mode 100644 index 00000000..0e467d4b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_cmp_coap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_cmp_coap.c new file mode 100644 index 00000000..5be0625f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_cmp_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_cmp_mqtt.c new file mode 100644 index 00000000..f4e57dd7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_event.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_event.c new file mode 100644 index 00000000..399b8908 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_event.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_event.h new file mode 100644 index 00000000..f4eaef49 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_info.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_info.c new file mode 100644 index 00000000..f85f01f2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_info.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_info.h new file mode 100644 index 00000000..31c6db68 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_log.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_log.h new file mode 100644 index 00000000..425929bc --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_notify.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_notify.c new file mode 100644 index 00000000..a1d14674 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_notify.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_notify.h new file mode 100644 index 00000000..4b5691a1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_packet.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_packet.c new file mode 100644 index 00000000..11a859e4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_packet.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_packet.h new file mode 100644 index 00000000..45595a91 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_report.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_report.c new file mode 100644 index 00000000..22e1e67a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset.h new file mode 100644 index 00000000..c05bbbb5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset/awss_dev_reset.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset/awss_dev_reset.c new file mode 100644 index 00000000..b7b7d051 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset/awss_dev_reset.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset/awss_dev_reset.h new file mode 100644 index 00000000..c2b77e07 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset/awss_dev_reset_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_reset/awss_dev_reset_internal.h new file mode 100644 index 00000000..5489edf7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_timer.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_timer.c new file mode 100644 index 00000000..86cb4a2a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_timer.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_timer.h new file mode 100644 index 00000000..f00dc82e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_utils.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/awss_utils.h new file mode 100644 index 00000000..b41303df --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/dev_bind_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/dev_bind_internal.h new file mode 100644 index 00000000..d20f1506 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/iot_import_awss.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/iot_import_awss.h new file mode 100644 index 00000000..4107ce6a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/os/os.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/os/os.h new file mode 100644 index 00000000..5fe9a495 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/os/os_misc.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/os/os_misc.c new file mode 100644 index 00000000..5a7ef36f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/passwd.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/passwd.c new file mode 100644 index 00000000..b58ed6bb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/passwd.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/impl/passwd.h new file mode 100644 index 00000000..665da65e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_bind/iot.mk new file mode 100644 index 00000000..3071a842 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/README.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/README.md new file mode 100644 index 00000000..b9583a6d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_adapter.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_adapter.c new file mode 100644 index 00000000..9e89800b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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_subdev_item_t *node = NULL; + iotx_alcs_subdev_item_t *next = NULL; + + list_for_each_entry_safe(node, next, &adapter->alcs_subdev_list, linked_list, iotx_alcs_subdev_item_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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_adapter.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_adapter.h new file mode 100644 index 00000000..dabfca5e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_api.c new file mode 100644 index 00000000..f15e378c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_api.h new file mode 100644 index 00000000..cdeb96ed --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_api_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_api_internal.h new file mode 100644 index 00000000..31adbab5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_base64.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_base64.c new file mode 100644 index 00000000..3f4a3d27 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_base64.c @@ -0,0 +1,132 @@ + +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include "infra_types.h" +#include "infra_defs.h" +#include "alcs_base64.h" + +static int8_t g_encodingTable[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + +static int8_t g_decodingTable[256]; +static int32_t g_modTable[] = { 0, 2, 1 }; + +static void build_decoding_table() +{ + static int32_t signal = 0; + int32_t i = 0; + + if (signal != 0) { + return; + } + + for (i = 0; i < 64; i++) { + g_decodingTable[(uint8_t) g_encodingTable[i]] = i; + } + + signal = 1; + return; +} + +int utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax, + uint8_t *encodedData, uint32_t *outputLength) +{ + uint32_t i = 0; + uint32_t j = 0; + + if (NULL == encodedData) { + return FAIL_RETURN; + } + + *outputLength = 4 * ((inputLength + 2) / 3); + + if (outputLenMax < *outputLength) { + return FAIL_RETURN; + } + + for (i = 0, j = 0; i < inputLength;) { + uint32_t octet_a = i < inputLength ? (uint8_t) data[i++] : 0; + uint32_t octet_b = i < inputLength ? (uint8_t) data[i++] : 0; + uint32_t octet_c = i < inputLength ? (uint8_t) data[i++] : 0; + + uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; + + encodedData[j++] = g_encodingTable[(triple >> 3 * 6) & 0x3F]; + encodedData[j++] = g_encodingTable[(triple >> 2 * 6) & 0x3F]; + encodedData[j++] = g_encodingTable[(triple >> 1 * 6) & 0x3F]; + encodedData[j++] = g_encodingTable[(triple >> 0 * 6) & 0x3F]; + } + + for (i = 0; i < g_modTable[inputLength % 3]; i++) { + encodedData[*outputLength - 1 - i] = '='; + } + + return SUCCESS_RETURN; +} + +int utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax, + uint8_t *decodedData, uint32_t *outputLength) +{ + uint32_t i = 0; + uint32_t j = 0; + uint32_t sextet_a = 0; + uint32_t sextet_b = 0; + uint32_t sextet_c = 0; + uint32_t sextet_d = 0; + uint32_t triple = 0; + + build_decoding_table(); + + if (inputLength % 4 != 0) { + return FAIL_RETURN; + } + + *outputLength = inputLength / 4 * 3; + + + if (data[inputLength - 1] == '=') { + (*outputLength)--; + } + + if (data[inputLength - 2] == '=') { + (*outputLength)--; + } + + if (outputLenMax < *outputLength) { + return FAIL_RETURN; + } + + for (i = 0, j = 0; i < inputLength;) { + sextet_a = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]]; + sextet_b = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]]; + sextet_c = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]]; + sextet_d = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]]; + + triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); + + if (j < *outputLength) { + decodedData[j++] = (triple >> 2 * 8) & 0xFF; + } + + if (j < *outputLength) { + decodedData[j++] = (triple >> 1 * 8) & 0xFF; + } + + if (j < *outputLength) { + decodedData[j++] = (triple >> 0 * 8) & 0xFF; + } + } + + return SUCCESS_RETURN; +} \ No newline at end of file diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_base64.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_base64.h new file mode 100644 index 00000000..6912a09f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_client.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_client.c new file mode 100644 index 00000000..54313bde --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_coap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_coap.c new file mode 100644 index 00000000..8cf3fe96 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_coap.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_coap.h new file mode 100644 index 00000000..398d9dff --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_internal.h new file mode 100644 index 00000000..de02f287 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_localsetup.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_localsetup.c new file mode 100644 index 00000000..53a66c72 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_localsetup.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_localsetup.h new file mode 100644 index 00000000..e3d41715 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_mqtt.c new file mode 100644 index 00000000..ac099492 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_mqtt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_mqtt.h new file mode 100644 index 00000000..05902530 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_server.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/alcs_server.c new file mode 100644 index 00000000..068ca2ad --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/iotx_alcs.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/iotx_alcs.h new file mode 100644 index 00000000..040a4aa3 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/iotx_alcs_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/alcs/iotx_alcs_config.h new file mode 100644 index 00000000..5294ac26 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client.c new file mode 100644 index 00000000..e0ce83be --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client.h new file mode 100644 index 00000000..08e138cc --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client_adapter.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client_adapter.c new file mode 100644 index 00000000..b42197ff --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client_adapter.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/client/dm_client_adapter.h new file mode 100644 index 00000000..bf82c90b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_gateway.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_gateway.c new file mode 100644 index 00000000..8f38be42 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_gateway.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_gateway.h new file mode 100644 index 00000000..c742223f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_ntp.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_ntp.c new file mode 100644 index 00000000..ffb9f941 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_ntp.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_ntp.h new file mode 100644 index 00000000..d5f20d06 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_solo.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_solo.c new file mode 100644 index 00000000..7cb2a9a5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_solo.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/impl_solo.h new file mode 100644 index 00000000..7bebcfd8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/iot_export_linkkit.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/iot_export_linkkit.h new file mode 100644 index 00000000..91096812 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/linkkit_export.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/linkkit_export.h new file mode 100644 index 00000000..96961762 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/linkkit_gateway_export.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/deprecated/linkkit_gateway_export.h new file mode 100644 index 00000000..f957510a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dev_model_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dev_model_api.h new file mode 100644 index 00000000..75ffd98a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_api.c new file mode 100644 index 00000000..d3653e01 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_cota.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_cota.c new file mode 100644 index 00000000..a87da3e5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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; + uint64_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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_cota.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_cota.h new file mode 100644 index 00000000..c5f54d07 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_fota.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_fota.c new file mode 100644 index 00000000..f0a0feae --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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; + uint64_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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_fota.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_fota.h new file mode 100644 index 00000000..d75157a1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_intf.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_intf.h new file mode 100644 index 00000000..1d26f06c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ipc.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ipc.c new file mode 100644 index 00000000..44a5126e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ipc.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ipc.h new file mode 100644 index 00000000..36ebe1b3 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_log_report.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_log_report.c new file mode 100644 index 00000000..4bc8ba49 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_manager.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_manager.c new file mode 100644 index 00000000..b19030ff --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_manager.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_manager.h new file mode 100644 index 00000000..fc145498 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message.c new file mode 100644 index 00000000..0582fd6a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message.h new file mode 100644 index 00000000..a9174403 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message_cache.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message_cache.c new file mode 100644 index 00000000..7c599130 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message_cache.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_message_cache.h new file mode 100644 index 00000000..d4892018 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_msg_process.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_msg_process.c new file mode 100644 index 00000000..f0ed9ce3 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_msg_process.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_msg_process.h new file mode 100644 index 00000000..911949b8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_opt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_opt.c new file mode 100644 index 00000000..75ffa8f7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_opt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_opt.h new file mode 100644 index 00000000..552d846c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ota.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ota.c new file mode 100644 index 00000000..6a974dab --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ota.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_ota.h new file mode 100644 index 00000000..8d25e46b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_shadow.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_shadow.c new file mode 100644 index 00000000..0bffa7f1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_shadow.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_shadow.h new file mode 100644 index 00000000..3320a8ff --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_tsl_alink.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_tsl_alink.c new file mode 100644 index 00000000..cf306b85 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_tsl_alink.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_tsl_alink.h new file mode 100644 index 00000000..f73adfae --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_utils.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_utils.c new file mode 100644 index 00000000..fb1f4aec --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_utils.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_utils.h new file mode 100644 index 00000000..e84b9ac5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/dm_wrapper.h new file mode 100644 index 00000000..6a3f0c22 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/cJSON.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/cJSON.c new file mode 100644 index 00000000..47fb5c32 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/cJSON.c @@ -0,0 +1,2283 @@ +/* +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#ifdef __GNUC__ + #pragma GCC visibility push(default) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ + #pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char *)(global_error.json + global_error.position); +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 3) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char *) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) { + return 1; + } + + if (string1 == string2) { + return 0; + } + + for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { + if (*string1 == '\0') { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks { + void *(*allocate)(uint32_t size); + void(*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; + +extern void *HAL_Malloc(uint32_t size); +extern void HAL_Free(void *ptr); +static internal_hooks global_hooks = { HAL_Malloc, HAL_Free, realloc }; + +static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) { + return NULL; + } + + length = strlen((const char *)string) + sizeof(""); + if (!(copy = (unsigned char *)hooks->allocate(length))) { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks *const hooks) +{ + cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON)); + if (node) { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ + struct lconv *lconv = localeconv(); + return (unsigned char)lconv->decimal_point[0]; +} + +typedef struct { + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +#define cannot_read(buffer, size) (!can_read(buffer, size)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { + switch (buffer_at_offset(input_buffer)[i]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) { + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) { + item->valueint = INT_MAX; + } else if (number <= INT_MIN) { + item->valueint = INT_MIN; + } else { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) { + object->valueint = INT_MAX; + } else if (number <= INT_MIN) { + object->valueint = INT_MIN; + } else { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +typedef struct { + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char *ensure(printbuffer *const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) { + newsize = INT_MAX; + } else { + return NULL; + } + } else { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) { + /* reallocate with realloc if available */ + newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); + } else { + /* otherwise reallocate manually */ + newbuffer = (unsigned char *)p->hooks.allocate(newsize); + if (!newbuffer) { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) { + memcpy(newbuffer, p->buffer, p->offset + 1); + } + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer *const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char *)buffer_pointer); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test; + + if (output_buffer == NULL) { + return false; + } + + /* This checks for NaN and Infinity */ + if ((d * 0) != 0) { + length = sprintf((char *)number_buffer, "null"); + } else { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char *)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || ((double)test != d)) { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char *)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occured */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length); + if (output_pointer == NULL) { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) { + if (number_buffer[i] == decimal_point) { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char *const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) { + h += (unsigned int)input[i] - '0'; + } else if ((input[i] >= 'A') && (input[i] <= 'F')) { + h += (unsigned int)10 + input[i] - 'A'; + } else if ((input[i] >= 'a') && (input[i] <= 'f')) { + h += (unsigned int)10 + input[i] - 'a'; + } else { /* invalid */ + return 0; + } + + if (i < 3) { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 +* A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, + const unsigned char *const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } else { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } else if (codepoint < 0x800) { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } else if (codepoint < 0x10000) { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } else if (codepoint <= 0x10FFFF) { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } else { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } else { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { + /* is escape sequence */ + if (input_end[0] == '\\') { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) { + if (*input_pointer != '\\') { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) { + goto fail; + } + + switch (input_pointer[1]) { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char *)output; + + input_buffer->offset = (size_t)(input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) { + input_buffer->hooks.deallocate(output); + } + + if (input_pointer != NULL) { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) { + return false; + } + + /* empty string */ + if (input == NULL) { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) { + return false; + } + strcpy((char *)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) { + switch (*input_pointer) { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { + /* normal character, copy */ + *output_pointer = *input_pointer; + } else { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char *)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) +{ + return print_string_ptr((unsigned char *)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) { + return NULL; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { + buffer->offset++; + } + + if (buffer->offset == buffer->length) { + buffer->offset--; + } + + return buffer; +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, + cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL) { + goto fail; + } + + buffer.content = (const unsigned char *)value; + buffer.length = strlen((const char *)value) + sizeof(""); + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) { /* memory fail */ + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(&buffer))) { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { + goto fail; + } + } + if (return_parse_end) { + *return_parse_end = (const char *)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) { + cJSON_Delete(item); + } + + if (value != NULL) { + error local_error; + local_error.json = (const unsigned char *)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) { + local_error.position = buffer.offset; + } else if (buffer.length > 0) { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) { + *return_parse_end = (const char *)local_error.json + local_error.position; + } else { + global_error = local_error; + } + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +#define cjson_min(a, b) ((a < b) ? a : b) + +static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks) +{ + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char *)hooks->allocate(256); + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) { + printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->length); + buffer->buffer = NULL; + if (printed == NULL) { + goto fail; + } + } else { /* otherwise copy the JSON over to a new buffer */ + printed = (unsigned char *)hooks->allocate(buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + } + + return printed; + +fail: + if (buffer->buffer != NULL) { + hooks->deallocate(buffer->buffer); + } + +#if 0 + if (printed != NULL) { + hooks->deallocate(printed); + } +#endif + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char *)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char *)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) { + return NULL; + } + + p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) { + return NULL; + } + + return (char *)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (len < 0) { + return false; + } + + p.buffer = (unsigned char *)buf; + p.length = (size_t)len; + p.offset = 0; + p.noalloc = true; + p.format = fmt; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') + || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { + return parse_object(item, input_buffer); + } + + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) { + return false; + } + + switch ((item->type) & 0xFF) { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) { + return false; + } + strcpy((char *)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) { + return false; + } + strcpy((char *)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) { + return false; + } + strcpy((char *)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: { + size_t raw_length = 0; + if (item->valuestring == NULL) { + if (!output_buffer->noalloc) { + output_buffer->hooks.deallocate(output_buffer->buffer); + } + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) { + /* start the linked list */ + current_item = head = new_item; + } else { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) { + if (!print_value(current_element, output_buffer)) { + return false; + } + update_offset(output_buffer); + if (current_element->next) { + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) { + return false; + } + *output_pointer++ = ','; + if (output_buffer->format) { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) { + /* start the linked list */ + current_item = head = new_item; + } else { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) { + goto fail; /* faile to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) { + return false; + } + + /* Compose the output: */ + length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) { + if (output_buffer->format) { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) { + return false; + } + for (i = 0; i < output_buffer->depth; i++) { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) { + return false; + } + update_offset(output_buffer); + + length = (size_t)(output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = (size_t)((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) { + return false; + } + if (current_item->next) { + *output_pointer++ = ','; + } + + if (output_buffer->format) { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) { + return false; + } + if (output_buffer->format) { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *c = array->child; + size_t i = 0; + while (c) { + i++; + c = c->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)i; +} + +static cJSON *get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) { + return NULL; + } + + current_element = object->child; + if (case_sensitive) { + while ((current_element != NULL) && (strcmp(name, current_element->string) != 0)) { + current_element = current_element->next; + } + } else { + while ((current_element != NULL) + && (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) { + current_element = current_element->next; + } + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks) +{ + cJSON *ref = cJSON_New_Item(hooks); + if (!ref) { + return NULL; + } + memcpy(ref, item, sizeof(cJSON)); + ref->string = NULL; + ref->type |= cJSON_IsReference; + ref->next = ref->prev = NULL; + return ref; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL)) { + return; + } + + child = array->child; + + if (child == NULL) { + /* list is empty, start new one */ + array->child = item; + } else { + /* append to the end */ + while (child->next) { + child = child->next; + } + suffix_object(child, item); + } +} + +CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + /* call cJSON_AddItemToObjectCS for code reuse */ + cJSON_AddItemToObjectCS(object, (char *)cJSON_strdup((const unsigned char *)string, &global_hooks), item); + /* remove cJSON_StringIsConst flag */ + item->type &= ~cJSON_StringIsConst; +} + +#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ + #pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + if (!item) { + return; + } + if (!(item->type & cJSON_StringIsConst) && item->string) { + global_hooks.deallocate(item->string); + } + item->string = (char *)string; + item->type |= cJSON_StringIsConst; + cJSON_AddItemToArray(object, item); +} +#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + cJSON_AddItemToArray(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) +{ + if ((parent == NULL) || (item == NULL)) { + return NULL; + } + + if (item->prev != NULL) { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) { + /* first element */ + parent->child = item->next; + } + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0) { + return; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) { + cJSON_AddItemToArray(array, newitem); + return; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) { + array->child = newitem; + } else { + newitem->prev->next = newitem; + } +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) +{ + if ((parent == NULL) || (replacement == NULL)) { + return false; + } + + if (replacement == item) { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) { + replacement->next->prev = replacement; + } + if (replacement->prev != NULL) { + replacement->prev->next = replacement; + } + if (parent->child == item) { + parent->child = replacement; + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *obj = NULL; + + if (which < 0) { + return; + } + + obj = get_array_item(array, (size_t)which); + if (obj == NULL) { + return; + } + + cJSON_ReplaceItemViaPointer(array, obj, newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, + cJSON_bool case_sensitive) +{ + cJSON *obj = NULL; + + if (replacement == NULL) { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { + cJSON_free(replacement->string); + } + replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + replacement->type &= ~cJSON_StringIsConst; + + obj = get_object_item(object, string, case_sensitive); + if (obj == NULL) { + return false; + } + + cJSON_ReplaceItemViaPointer(object, obj, replacement); + + return true; +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = b ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) { + item->valueint = INT_MAX; + } else if (num <= INT_MIN) { + item->valueint = INT_MIN; + } else { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_String; + item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (!item->valuestring) { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Raw; + item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); + if (!item->valuestring) { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if (count < 0) { + return NULL; + } + + a = cJSON_CreateArray(); + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if (count < 0) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateNumber((double)numbers[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if (count < 0) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateNumber(numbers[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if (count < 0) { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { + n = cJSON_CreateString(strings[i]); + if (!n) { + cJSON_Delete(a); + return NULL; + } + if (!i) { + a->child = n; + } else { + suffix_object(p, n); + } + p = n; + } + + return a; +} + +/* Duplication */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) { + newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); + if (!newitem->valuestring) { + goto fail; + } + } + if (item->string) { + newitem->string = (item->type & cJSON_StringIsConst) ? item->string : (char *)cJSON_strdup(( + unsigned char *)item->string, &global_hooks); + if (!newitem->string) { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) { + newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) { + goto fail; + } + if (next != NULL) { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } else { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + + return newitem; + +fail: + if (newitem != NULL) { + cJSON_Delete(newitem); + } + + return NULL; +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + unsigned char *into = (unsigned char *)json; + while (*json) { + if (*json == ' ') { + json++; + } else if (*json == '\t') { + /* Whitespace characters. */ + json++; + } else if (*json == '\r') { + json++; + } else if (*json == '\n') { + json++; + } else if ((*json == '/') && (json[1] == '/')) { + /* double-slash comments, to end of line. */ + while (*json && (*json != '\n')) { + json++; + } + } else if ((*json == '/') && (json[1] == '*')) { + /* multiline comments. */ + while (*json && !((*json == '*') && (json[1] == '/'))) { + json++; + } + json += 2; + } else if (*json == '\"') { + /* string literals, which are \" sensitive. */ + *into++ = (unsigned char) * json++; + while (*json && (*json != '\"')) { + if (*json == '\\') { + *into++ = (unsigned char) * json++; + } + *into++ = (unsigned char) * json++; + } + *into++ = (unsigned char) * json++; + } else { + /* All other characters. */ + *into++ = (unsigned char) * json++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) +{ + if (item == NULL) { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) { + return true; + } + + switch (a->type & 0xFF) { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (a->valuedouble == b->valuedouble) { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) { + return true; + } + + return false; + + case cJSON_Array: { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + return true; + } + + case cJSON_Object: { + cJSON *a_element = NULL; + cJSON_ArrayForEach(a_element, a) { + /* TODO This has O(n^2) runtime, which is horrible! */ + cJSON *b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); +} diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/cJSON.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/cJSON.h new file mode 100644 index 00000000..2e3715a6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/data/cntdown_tsl.data b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/data/cntdown_tsl.data new file mode 100644 index 00000000..b963e47a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/data/sched_tsl.data b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/data/sched_tsl.data new file mode 100644 index 00000000..1b17be1d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/data/solo_tsl.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/data/solo_tsl.c new file mode 100644 index 00000000..1b17be1d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/linkkit_example_gateway.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/linkkit_example_gateway.c new file mode 100644 index 00000000..12eaea85 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/linkkit_example_solo.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/linkkit_example_solo.c new file mode 100644 index 00000000..bacad601 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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 property setting 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/model_for_examples.json b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/examples/model_for_examples.json new file mode 100644 index 00000000..40ab215d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/impl_linkkit.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/impl_linkkit.c new file mode 100644 index 00000000..fec9787f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iot.mk new file mode 100644 index 00000000..ab77f05a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm.c new file mode 100644 index 00000000..9ebfe130 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm.h new file mode 100644 index 00000000..877b1032 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_coap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_coap.c new file mode 100644 index 00000000..10a24665 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_coap.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_coap.h new file mode 100644 index 00000000..9d664b3c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_internal.h new file mode 100644 index 00000000..ca9fccd3 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_mqtt.c new file mode 100644 index 00000000..64473c29 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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[0] != '\0') { + ((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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_mqtt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_cm_mqtt.h new file mode 100644 index 00000000..90b42890 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_dm.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_dm.h new file mode 100644 index 00000000..c5ade513 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_dm_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_dm_config.h new file mode 100644 index 00000000..7920fa5f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_dm_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_dm_internal.h new file mode 100644 index 00000000..ef6ef91f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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" + #include "dm_server_adapter.h" + #include "dm_server.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_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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_log_report.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/iotx_log_report.h new file mode 100644 index 00000000..dde32ee1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server.c new file mode 100644 index 00000000..5735d9fd --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server.h new file mode 100644 index 00000000..2ada9788 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server_adapter.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server_adapter.c new file mode 100644 index 00000000..dc827706 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server_adapter.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_model/server/dm_server_adapter.h new file mode 100644 index 00000000..bfb49a75 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset.c new file mode 100644 index 00000000..59c89b83 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset_api.h new file mode 100644 index 00000000..fed53791 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset_internal.h new file mode 100644 index 00000000..8899e5da --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/dev_reset_wrapper.h new file mode 100644 index 00000000..f1d09a51 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/examples/dev_reset_example.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/examples/dev_reset_example.c new file mode 100644 index 00000000..b9540190 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_reset/iot.mk new file mode 100644 index 00000000..c1a3219a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_api.h new file mode 100644 index 00000000..3a0e9244 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_api.h @@ -0,0 +1,10 @@ +#ifndef _DEV_SIGN_H_ +#define _DEV_SIGN_H_ + +#include "dev_sign_internal.h" + +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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_internal.h new file mode 100644 index 00000000..26672ded --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_internal.h @@ -0,0 +1,12 @@ +#ifndef _DEV_SIGN_INTERNAL_H_ +#define _DEV_SIGN_INTERNAL_H_ + +#include +#include +#include "infra_config.h" +#include "infra_defs.h" +#include "dev_sign_api.h" +#include "dev_sign_wrapper.h" + +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_mqtt.c new file mode 100644 index 00000000..9f223d9c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_mqtt.c @@ -0,0 +1,220 @@ +#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; +} + +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])); + } + + /* 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_wrapper.h new file mode 100644 index 00000000..c3520e6b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/dev_sign_wrapper.h @@ -0,0 +1,4 @@ + + +#include "infra_types.h" +#include "infra_defs.h" diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/examples/dev_sign_example.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/examples/dev_sign_example.c new file mode 100644 index 00000000..fba49325 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dev_sign/iot.mk new file mode 100644 index 00000000..09398a55 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg.c new file mode 100644 index 00000000..29f6af78 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg_api.h new file mode 100644 index 00000000..d1fcf8fe --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg_internal.h new file mode 100644 index 00000000..79d73306 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/dynreg_wrapper.h new file mode 100644 index 00000000..b7e52f51 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/examples/dynreg_example.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/examples/dynreg_example.c new file mode 100644 index 00000000..f42c219a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/dynamic_register/iot.mk new file mode 100644 index 00000000..4674ef3d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/README.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/README.md new file mode 100644 index 00000000..e1a6de0e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/examples/http_example.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/examples/http_example.c new file mode 100644 index 00000000..6b40a557 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_api.h new file mode 100644 index 00000000..ab02885b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_api.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_HTTP_H_ +#define _IOT_EXPORT_HTTP_H_ + +#include "infra_types.h" +#include "infra_defs.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +typedef struct { + char product_key[IOTX_PRODUCT_KEY_LEN + 1]; + char device_name[IOTX_DEVICE_NAME_LEN + 1]; + char device_id[IOTX_DEVICE_ID_LEN + 1]; + char device_secret[IOTX_DEVICE_SECRET_LEN + 1]; + char module_vendor_id[IOTX_MODULE_ID_LEN + 1]; +} iotx_device_info_t; + +/* IoTx http initial param */ +typedef struct { + iotx_device_info_t *device_info; + int keep_alive; + int timeout_ms; +} iotx_http_param_t; + +/* IoTx http context */ +typedef struct { + char *p_auth_token; + uint32_t auth_token_len; + char is_authed; + const char *version; + const char *signmethod; + const char *sign; + iotx_device_info_t *p_devinfo; + const char *timestamp; + void *httpc; + int keep_alive; + int timeout_ms; +} iotx_http_t, *iotx_http_pt; + +/* IoTx http message definition + * request_payload and response_payload need to be allocate in order to save memory. + * topic_path specify the topic url you want to publish message. + */ +typedef struct { + char *topic_path; + uint32_t request_payload_len; + char *request_payload; + uint32_t response_payload_len; + char *response_payload; + uint32_t timeout_ms; +} iotx_http_message_param_t; + +/* The response code from sever */ +typedef enum { + IOTX_HTTP_SUCCESS = 0, + IOTX_HTTP_COMMON_ERROR = 10000, + IOTX_HTTP_PARAM_ERROR = 10001, + IOTX_HTTP_AUTH_CHECK_ERROR = 20000, + IOTX_HTTP_TOKEN_EXPIRED_ERROR = 20001, + IOTX_HTTP_TOKEN_NULL_ERROR = 20002, + IOTX_HTTP_TOKEN_CHECK_ERROR = 20003, + IOTX_HTTP_UPDATE_SESSION_ERROR = 20004, + IOTX_HTTP_PUBLISH_MESSAGE_ERROR = 30001, + IOTX_HTTP_REQUEST_TOO_MANY_ERROR = 40000, +} iotx_http_upstream_response_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_http http + * @{ + */ + +/** + * @brief Initialize the HTTP client + * This function initialize the data. + * + * @param [in] pInitParams: Specify the init param infomation. + * + * @retval NULL : Initialize failed. + * @retval NOT_NULL : The contex of HTTP client. + * @see None. + */ +void *IOT_HTTP_Init(iotx_http_param_t *pInitParams); + +/** + * @brief De-initialize the HTTP client + * This function release the related resource. + * + * @param [in] handle: pointer to http context pointer. + * @return None. + * @see None. + */ +void IOT_HTTP_DeInit(void **handle); + +/** + * @brief Handle device name authentication with remote server. + * + * @param [in] handle: Pointer of context, specify the HTTP client. + * + * @retval 0 : Authenticate success. + * @retval -1 : Authenticate failed. + * @see iotx_err_t. + */ +int IOT_HTTP_DeviceNameAuth(void *handle); + +/** + * @brief Send a message with specific path to server. + * Client must authentication with server before send message. + * + * @param [in] handle: Pointer of contex, specify the HTTP client. + * @param [in] msg_param: Specify the topic path and http payload configuration. + * + * @retval 0 : Success. + * @retval -1 : Failed. + * @see iotx_err_t. + */ +int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param); + +/** + * @brief close tcp connection from client to server. + * + * @param [in] handle: Pointer of contex, specify the HTTP client. + * @return None. + * @see None. + */ +void IOT_HTTP_Disconnect(void *handle); + +/** @} */ /* end of api_http */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_debug.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_debug.h new file mode 100644 index 00000000..98240001 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_wrapper.h new file mode 100644 index 00000000..5cf7890a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/http_wrapper.h @@ -0,0 +1,19 @@ +#ifndef _HTTP_WRAPPER_H +#define _HTTP_WRAPPER_H + +#include "infra_types.h" +#include "infra_defs.h" +#include "wrappers_defs.h" + +int HAL_SetProductKey(char *product_key); +int HAL_SetProductSecret(char *product_secret); +int HAL_SetDeviceName(char *device_name); +int HAL_SetDeviceSecret(char *device_secret); +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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/iot.mk new file mode 100644 index 00000000..c63a16c5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/iot.mk @@ -0,0 +1,11 @@ +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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/iotx_http_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/iotx_http_api.c new file mode 100644 index 00000000..2d2489c1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http/iotx_http_api.c @@ -0,0 +1,763 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include +#include + +#include "infra_httpc.h" +#include "infra_json_parser.h" +#include "infra_timer.h" +#include "infra_sha1.h" +#include "infra_report.h" +#include "http_debug.h" +#include "http_api.h" +#include "http_wrapper.h" + + + +#ifdef INFRA_MEM_STATS + #include "infra_mem_stats.h" + #define HTTP_API_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "http.api") + #define HTTP_API_FREE(ptr) LITE_free(ptr) +#else + #define HTTP_API_MALLOC(size) HAL_Malloc(size) + #define HTTP_API_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;} +#endif + +#define HTTP_LITE_JSON_VALUE_OF(key, src) LITE_json_value_of(key, src, 0x1234, "http.api") + +#ifndef CONFIG_MID_HTTP_TIMEOUT + #define CONFIG_MID_HTTP_TIMEOUT (5 * 1000) +#endif + +#ifndef CONFIG_HTTP_AUTH_TIMEOUT + #define CONFIG_HTTP_AUTH_TIMEOUT (5 * 1000) +#endif + +/* +#define IOTX_HTTP_TIMESTAMP_OPTIONAL_ENABLE +*/ +#define IOTX_HTTP_SIGN_LENGTH (41) +#define IOTX_HTTP_SIGN_SOURCE_LEN (256) +#define IOTX_HTTP_AUTH_TOKEN_LEN (192+1) +#define IOTX_HTTP_URL_LEN_MAX (135) + +#ifdef IOTX_HTTP_TIMESTAMP_OPTIONAL_ENABLE +#define IOTX_HTTP_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%stimestamp%s" +#define IOTX_HTTP_AUTH_DEVICENAME_STR \ + "{" \ + "\"version\":\"%s\", \"clientId\":\"%s\"," \ + "\"signmethod\":\"%s\",\"sign\":\"%s\"," \ + "\"productKey\":\"%s\",\"deviceName\":\"%s\"," \ + "\"timestamp\":\"%s\"" \ + "}" +#else +#define IOTX_HTTP_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%s" +#define IOTX_HTTP_AUTH_DEVICENAME_STR \ + "{" \ + "\"version\":\"%s\", \"clientId\":\"%s\"," \ + "\"signmethod\":\"%s\",\"sign\":\"%s\"," \ + "\"productKey\":\"%s\",\"deviceName\":\"%s\"" \ + "}" +#endif + +#define IOTX_HTTP_AUTH_STR "auth" +#define IOTX_HTTP_ONLINE_SERVER_URL "https://iot-as-http.cn-shanghai.aliyuncs.com" +#define IOTX_HTTP_ONLINE_SERVER_PORT 443 + +#define IOTX_SHA_METHOD "hmacsha1" + +#define IOTX_HTTP_HEADER_KEEPALIVE_STR "Connection: Keep-Alive\r\n" +#define IOTX_HTTP_HEADER_PASSWORD_STR "password:" +#define IOTX_HTTP_UPSTREAM_HEADER_STR \ + IOTX_HTTP_HEADER_KEEPALIVE_STR \ + IOTX_HTTP_HEADER_PASSWORD_STR \ + "%s" \ + IOTX_HTTP_HEADER_END_STR +#define IOTX_HTTP_HEADER_END_STR "\r\n" + +#define HTTP_AUTH_RESP_MAX_LEN (256) + +static iotx_http_t *iotx_http_context_bak = NULL; + + +/* + Http server url: https://iot-as-http.cn-shanghai.aliyuncs.com + Only https protocal is supported at present. + The /auth interface is used to get access token before any data transform which need to be requested just one time. + The device must call /auth to get the token before transfer any data. + Every data transfer need to be with access token. + You need to request for a new token if the current token have been expired. + Token can be cached in local devices, which has 48 hours term of validity. + POST /auth HTTP/1.1 + Host: iot-as-http.cn-shanghai.aliyuncs.com + Content-Type: application/json + body: {"version":"default","clientId":"xxxxx","signmethod":"hmacsha1","sign":"xxxxxxxxxx","productKey":"xxxxxx","deviceName":"xxxxxxx","timestamp":"xxxxxxx"} +*/ + +static int iotx_calc_sign(const char *p_device_secret, const char *p_msg, char *sign) +{ + http_info("| method: %s", IOTX_SHA_METHOD); + utils_hmac_sha1(p_msg, strlen(p_msg), sign, p_device_secret, strlen(p_device_secret)); + return SUCCESS_RETURN; +} + +static int calc_snprintf_string_length(char *fmt, ...) +{ + va_list args; + int rc = 0; + char *p = NULL; + char *sval = NULL; + + if (NULL == fmt) { + return -1; + } + + va_start(args, fmt); + + for (p = fmt; *p; p++) { + if (*p != '%') { + rc++; + continue; + } + switch (*++p) { + case 's': + for (sval = va_arg(args, char *); *sval; sval++) { + rc++; + } + break; + default: + rc++; + break; + } + } + + va_end(args); + + return rc; +} + +static int construct_full_http_authenticate_url(char *buf) +{ + LITE_snprintf(buf, IOTX_HTTP_URL_LEN_MAX, + "%s/%s", IOTX_HTTP_ONLINE_SERVER_URL, IOTX_HTTP_AUTH_STR); + http_info("get_http_authenticate_url is %s", buf); + return 0; +} + +static int construct_full_http_upstream_url(char *buf, const char *topic_path) +{ + LITE_snprintf(buf, IOTX_HTTP_URL_LEN_MAX, + "%s%s", IOTX_HTTP_ONLINE_SERVER_URL, topic_path); + http_info("construct_full_http_upstream_url is %s", buf); + return 0; +} + +static int http_report_func(void *handle, const char *topic_name, int req_ack, void *data, int len) +{ + iotx_http_message_param_t msg_param; + char request_buf[1024]; + char topic_path[100]; + + if (handle == NULL || topic_name == NULL || data == NULL) { + http_err("params err"); + return -1; + } + + HAL_Snprintf(topic_path, sizeof(topic_path), "/topic%s", topic_name); + + memset(&msg_param, 0, sizeof(iotx_http_message_param_t)); + msg_param.request_payload = (char *)data; + msg_param.response_payload = request_buf; + msg_param.timeout_ms = CONFIG_MID_HTTP_TIMEOUT; + msg_param.request_payload_len = len; + msg_param.response_payload_len = 1024; + msg_param.topic_path = topic_path; + + return IOT_HTTP_SendMessage(handle, &msg_param); +} + +static void *verify_iotx_http_context(void *handle) +{ + iotx_http_t *iotx_http_context = (iotx_http_t *)handle; + + if (NULL == iotx_http_context || + NULL == iotx_http_context_bak || + iotx_http_context_bak != iotx_http_context) { + http_err("iotx_http_context not valid pointer!"); + + iotx_http_context = NULL; + } + + return iotx_http_context; +} + +void *IOT_HTTP_Init(iotx_http_param_t *pInitParams) +{ + iotx_device_info_t *p_devinfo; + iotx_http_t *iotx_http_context; + + /* currently http is singleton, init twice not allowed. */ + if (NULL != iotx_http_context_bak) { + http_err("Init twice not allowed, please deinit first"); + return NULL; + } + + if (NULL == pInitParams || NULL == pInitParams->device_info) { + http_err("Invalid argument: pInitParams or device_info = NULL"); + return NULL; + } + + p_devinfo = pInitParams->device_info; + +/* + HAL_SetProductKey(p_devinfo->product_key); + HAL_SetDeviceName(p_devinfo->device_name); + HAL_SetDeviceSecret(p_devinfo->device_secret); +*/ + + iotx_http_context = (iotx_http_t *)HTTP_API_MALLOC(sizeof(iotx_http_t)); + + if (NULL == iotx_http_context) { + http_err("Allocate memory for iotx_http_context failed"); + return NULL; + } + + memset(iotx_http_context, 0x00, sizeof(iotx_http_t)); + + iotx_http_context->keep_alive = pInitParams->keep_alive; + iotx_http_context->timeout_ms = pInitParams->timeout_ms; + iotx_http_context->p_auth_token = HTTP_API_MALLOC(IOTX_HTTP_AUTH_TOKEN_LEN); + if (NULL == iotx_http_context->p_auth_token) { + http_err("Allocate memory for auth token failed"); + goto err; + } + memset(iotx_http_context->p_auth_token, 0x00, IOTX_HTTP_AUTH_TOKEN_LEN); + iotx_http_context->is_authed = 0; + iotx_http_context->auth_token_len = IOTX_HTTP_AUTH_TOKEN_LEN; + + /*Get deivce information*/ + iotx_http_context->p_devinfo = (iotx_device_info_t *)HTTP_API_MALLOC(sizeof(iotx_device_info_t)); + if (NULL == iotx_http_context->p_devinfo) { + http_err("Allocate memory for iotx_http_context->p_devinfo failed"); + goto err; + } + memset(iotx_http_context->p_devinfo, 0x00, sizeof(iotx_device_info_t)); + + /*It should be implement by the user*/ + memset(iotx_http_context->p_devinfo, 0x00, sizeof(iotx_device_info_t)); + strncpy(iotx_http_context->p_devinfo->device_id, p_devinfo->device_id, strlen(p_devinfo->device_id)); + strncpy(iotx_http_context->p_devinfo->product_key, p_devinfo->product_key, strlen(p_devinfo->product_key)); + strncpy(iotx_http_context->p_devinfo->device_secret, p_devinfo->device_secret, strlen(p_devinfo->device_secret)); + strncpy(iotx_http_context->p_devinfo->device_name, p_devinfo->device_name, strlen(p_devinfo->device_name)); + + iotx_http_context->httpc = HTTP_API_MALLOC(sizeof(httpclient_t)); + if (NULL == iotx_http_context->httpc) { + http_err("Allocate memory for iotx_http_context->httpc failed"); + goto err; + } + memset(iotx_http_context->httpc, 0x00, sizeof(httpclient_t)); + + iotx_http_context_bak = iotx_http_context; + + return iotx_http_context; +err: + /* Error, release the memory */ + if (NULL != iotx_http_context) { + if (NULL != iotx_http_context->p_devinfo) { + HTTP_API_FREE(iotx_http_context->p_devinfo); + } + if (NULL != iotx_http_context->p_auth_token) { + HTTP_API_FREE(iotx_http_context->p_auth_token); + } + + iotx_http_context->auth_token_len = 0; + HTTP_API_FREE(iotx_http_context); + } + return NULL; +} + +void IOT_HTTP_DeInit(void **handle) +{ + iotx_http_t *iotx_http_context; + if (NULL == handle) { + http_err("handle is NULL pointer"); + return; + } + if (NULL == (iotx_http_context = verify_iotx_http_context(*handle))) { + return; + } + + if (NULL != iotx_http_context->p_devinfo) { + HTTP_API_FREE(iotx_http_context->p_devinfo); + } + if (NULL != iotx_http_context->p_auth_token) { + HTTP_API_FREE(iotx_http_context->p_auth_token); + } + if (NULL != iotx_http_context->httpc) { + HTTP_API_FREE(iotx_http_context->httpc); + } + + iotx_http_context->auth_token_len = 0; + HTTP_API_FREE(iotx_http_context); + iotx_http_context_bak = NULL; +} + +int IOT_HTTP_DeviceNameAuth(void *handle) +{ + int ret = -1; + int ret_code = 0; + char *pvalue = NULL; + char *response_message = NULL; + char sign[IOTX_HTTP_SIGN_LENGTH] = {0}; + char http_url[IOTX_HTTP_URL_LEN_MAX] = {0}; + char timestamp[14] = {0}; + httpclient_t *httpc; + httpclient_data_t httpc_data = {0}; + char *req_payload = NULL; + char *rsp_payload = NULL; + int len = 0; + char p_msg_unsign[IOTX_HTTP_SIGN_SOURCE_LEN] = {0}; + iotx_time_t timer; + iotx_http_t *iotx_http_context; + const char *pub_key = NULL; + /* */ + /* body: */ + /* { */ + /* "version": "default",//默认default */ + /* "clientId": "xxxxxx",//å¿…å¡« */ + /* "signmethod": "hmacsha1",//åªæ”¯æŒhmacmd5å’Œhmacsha1,默认hmacmd5 */ + /* "sign": "xxxxxxxxxxxxx",//必填,signmethod(deviceSecret,content), content = 将所有æäº¤ç»™æœåŠ¡å™¨çš„å‚æ•°ï¼ˆversion,sign,signmethod除外), 按照字æ¯é¡ºåºæŽ’åº, ç„¶åŽå°†å‚æ•°å€¼ä¾æ¬¡æ‹¼æŽ¥ï¼Œæ— æ‹¼æŽ¥ç¬¦å· */ + /* "productKey": "xxxxxx",//å¿…å¡« */ + /* "deviceName": "xxxxxx",//å¿…å¡« */ + /* "timestamp": "xxxxxx"//选填 13byte */ + /* } */ + + if (NULL == (iotx_http_context = verify_iotx_http_context(handle))) { + goto do_exit; + } + iotx_http_context->is_authed = 0; + + /* FIXME:some compile error when calling this function. Get TimeStamp */ + /* + if(!utils_get_epoch_time_from_ntp(timestamp, sizeof(timestamp))) + { + http_info("http time response: \r\n\r\n%s", timestamp); + goto do_exit; + } + */ + + /* Calculate Sign */ + LITE_snprintf(p_msg_unsign, IOTX_HTTP_SIGN_SOURCE_LEN, + IOTX_HTTP_SIGN_SRC_STR, + iotx_http_context->p_devinfo->device_id, + iotx_http_context->p_devinfo->device_name, + iotx_http_context->p_devinfo->product_key +#ifdef IOTX_HTTP_TIMESTAMP_OPTIONAL_ENABLE + , timestamp +#endif + ); + + iotx_calc_sign(iotx_http_context->p_devinfo->device_secret, p_msg_unsign, sign); + + /* to save stack memory*/ + len = calc_snprintf_string_length(IOTX_HTTP_AUTH_DEVICENAME_STR, + "default", + iotx_http_context->p_devinfo->device_id, + IOTX_SHA_METHOD, + sign, + iotx_http_context->p_devinfo->product_key, + iotx_http_context->p_devinfo->device_name, + timestamp + ); + + if (len < 0) { + goto do_exit; + } + + req_payload = (char *)HTTP_API_MALLOC(len + 1); + memset(req_payload, 0, len + 1); + + http_debug("allocate req_payload: len = %d", len); + + len = HAL_Snprintf(req_payload, len + 1, + IOTX_HTTP_AUTH_DEVICENAME_STR, + "default", + iotx_http_context->p_devinfo->device_id, + IOTX_SHA_METHOD, + sign, + iotx_http_context->p_devinfo->product_key, + iotx_http_context->p_devinfo->device_name, + timestamp + ); + http_debug("len = %d, req_payload: \r\n%s", len, req_payload); + + /* Malloc Http Response Payload */ + rsp_payload = (char *)HTTP_API_MALLOC(HTTP_AUTH_RESP_MAX_LEN); + if (NULL == rsp_payload) { + http_err("Allocate HTTP rsp_payload buf failed!"); + goto do_exit; + } + memset(rsp_payload, 0, HTTP_AUTH_RESP_MAX_LEN); + + /* Construct Auth Url */ + construct_full_http_authenticate_url(http_url); + + /* Set httpclient and httpclient_data */ + httpc = (httpclient_t *)iotx_http_context->httpc; + + httpc_data.post_content_type = "application/json"; + httpc_data.post_buf = req_payload; + httpc_data.post_buf_len = len; + httpc_data.response_buf = rsp_payload; + httpc_data.response_buf_len = HTTP_AUTH_RESP_MAX_LEN; + + httpc->header = "Connection: Keep-Alive\r\n"; + + /* + Test Code + iotx_http_context->p_auth_token = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiaG1hY3NoYTEifQ.eyJleHBpcmUiOjE1MDQ3ODE4MzQ5MDAsInRva2VuIjoiM2EyZTRmYzMyNjk5NDE0Y2E3MDFjNzIzNzI1YjIyNDgifQ.e87AFhkvNKiqF5xdgm1P47f9DwY"; + iotx_http_context->is_authed = 1; + ret = 0; + goto do_exit; + Test Code + */ + + { + extern const char *iotx_ca_crt; + pub_key = iotx_ca_crt; + } + + /* Send Request and Get Response */ + if (0 != iotx_post(httpc, + http_url, + IOTX_HTTP_ONLINE_SERVER_PORT, + pub_key, + &httpc_data)) { + goto do_exit; + } + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, CONFIG_HTTP_AUTH_TIMEOUT); + + + ret = httpclient_recv_response(httpc, iotx_time_left(&timer), &httpc_data); + if (ret < 0) { + http_err("httpclient_recv_response error, ret = %d", ret); + httpclient_close(httpc); + return ret; + } + if (0 == iotx_http_context->keep_alive) { + http_info("http not keepalive"); + httpclient_close(httpc); + } + /* + body: + { + "code": 0,//业务状æ€ç  + "message": "success",//ä¸šåŠ¡ä¿¡æ¯ + "info": { + "token": "eyJ0eXBlIjoiSldUIiwiYWxnIjoiaG1hY3NoYTEifQ.eyJleHBpcmUiOjE1MDI1MzE1MDc0NzcsInRva2VuIjoiODA0ZmFjYTBiZTE3NGUxNjliZjY0ODVlNWNiNDg3MTkifQ.OjMwu29F0CY2YR_6oOyiOLXz0c8" + } + } + */ + http_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf); + + pvalue = HTTP_LITE_JSON_VALUE_OF("code", httpc_data.response_buf); + if (!pvalue) { + goto do_exit; + } + ret_code = atoi(pvalue); + http_info("ret_code = %d", ret_code); + HTTP_API_FREE(pvalue); + pvalue = NULL; + + pvalue = HTTP_LITE_JSON_VALUE_OF("message", httpc_data.response_buf); + if (NULL == pvalue) { + goto do_exit; + } + response_message = pvalue; + http_info("response_message: %s", response_message); + (void)response_message; + HTTP_API_FREE(pvalue); + pvalue = NULL; + + switch (ret_code) { + case IOTX_HTTP_SUCCESS: + break; + case IOTX_HTTP_COMMON_ERROR: + case IOTX_HTTP_PARAM_ERROR: + case IOTX_HTTP_AUTH_CHECK_ERROR: + case IOTX_HTTP_UPDATE_SESSION_ERROR: + case IOTX_HTTP_REQUEST_TOO_MANY_ERROR: + default: + ret = FAIL_RETURN; + goto do_exit; + } + + pvalue = HTTP_LITE_JSON_VALUE_OF("info.token", httpc_data.response_buf); + if (NULL == pvalue) { + http_err("can't get token from json, Abort!"); + goto do_exit; + } + + strcpy(iotx_http_context->p_auth_token, pvalue); + iotx_http_context->is_authed = 1; + HTTP_API_FREE(pvalue); + pvalue = NULL; + + + iotx_set_report_func(http_report_func); + /* report module id */ + ret = iotx_report_mid(iotx_http_context); + if (SUCCESS_RETURN != ret) { + http_err("Send ModuleId message to server(Http) failed, ret = %d", ret); + goto do_exit; + } + /* report device information */ + ret = iotx_report_devinfo(iotx_http_context); + if (SUCCESS_RETURN != ret) { + http_err("Send devinfo message to server(Http) failed, ret = %d", ret); + goto do_exit; + } + /* report firmware */ + ret = iotx_report_firmware_version(iotx_http_context); + if (SUCCESS_RETURN != ret) { + http_err("Send firmware message to server(Http) failed, ret = %d", ret); + goto do_exit; + } + + ret = 0; + +do_exit: + if (pvalue) { + HTTP_API_FREE(pvalue); + pvalue = NULL; + } + if (req_payload) { + HTTP_API_FREE(req_payload); + req_payload = NULL; + } + if (rsp_payload) { + HTTP_API_FREE(rsp_payload); + rsp_payload = NULL; + } + + return ret; +} + +int IOT_HTTP_SendMessage(void *handle, iotx_http_message_param_t *msg_param) +{ + int ret = -1; + int response_code = 0; + char *pvalue = NULL; + char http_url[IOTX_HTTP_URL_LEN_MAX] = {0}; + httpclient_t *httpc = NULL; + httpclient_data_t httpc_data = {0}; + char *messageId = NULL; + char *user_data = NULL; + int len = 0; + uint32_t payload_len = 0; + iotx_time_t timer; + iotx_http_t *iotx_http_context; + const char *pub_key = NULL; + /* + POST /topic/${topic} HTTP/1.1 + Host: iot-as-http.cn-shanghai.aliyuncs.com + password:${token} + Content-Type: application/octet-stream + body: ${your_data} + */ + if (NULL == (iotx_http_context = verify_iotx_http_context(handle))) { + goto do_exit; + } + + if (NULL == msg_param) { + http_err("iotx_http_context or msg_param NULL pointer!"); + goto do_exit; + } + + httpc = (httpclient_t *)iotx_http_context->httpc; + + if (NULL == httpc) { + http_err("httpc null pointer"); + goto do_exit; + } + + if (0 == iotx_http_context->is_authed) { + http_err("Device is not authed"); + goto do_exit; + } + + if (NULL == msg_param->request_payload) { + http_err("IOT_HTTP_SendMessage request_payload NULL!"); + goto do_exit; + } + + if (NULL == msg_param->response_payload) { + http_err("IOT_HTTP_SendMessage response_payload NULL!"); + goto do_exit; + } + + if (NULL == msg_param->topic_path) { + http_err("IOT_HTTP_SendMessage topic_path NULL!"); + goto do_exit; + } + + payload_len = strlen(msg_param->request_payload) + 1; + msg_param->request_payload_len = msg_param->request_payload_len > payload_len \ + ? payload_len : msg_param->request_payload_len; + + /* Construct Auth Url */ + construct_full_http_upstream_url(http_url, msg_param->topic_path); + + len = strlen(IOTX_HTTP_HEADER_PASSWORD_STR) + strlen(iotx_http_context->p_auth_token) + strlen( + IOTX_HTTP_HEADER_KEEPALIVE_STR) + strlen(IOTX_HTTP_HEADER_END_STR); + httpc->header = HTTP_API_MALLOC(len + 1); + if (NULL == httpc->header) { + http_err("Allocate memory for httpc->header failed"); + goto do_exit; + } + LITE_snprintf(httpc->header, len + 1, + IOTX_HTTP_UPSTREAM_HEADER_STR, iotx_http_context->p_auth_token); + http_info("httpc->header = %s", httpc->header); + + httpc_data.post_content_type = "application/octet-stream"; + httpc_data.post_buf = msg_param->request_payload; + httpc_data.post_buf_len = msg_param->request_payload_len; + httpc_data.response_buf = msg_param->response_payload; + httpc_data.response_buf_len = msg_param->response_payload_len; + + http_info("request_payload: \r\n\r\n%s\r\n", httpc_data.post_buf); + + { + extern const char *iotx_ca_crt; + pub_key = iotx_ca_crt; + } + + /* Send Request and Get Response */ + if (iotx_post(httpc, + http_url, + IOTX_HTTP_ONLINE_SERVER_PORT, + pub_key, + &httpc_data)) { + goto do_exit_pre; + } + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, msg_param->timeout_ms); + + ret = httpclient_recv_response(httpc, iotx_time_left(&timer), &httpc_data); + if (ret < 0) { + http_err("httpclient_recv_response error, ret = %d", ret); + httpclient_close(httpc); + goto do_exit_pre; + } + + if (0 == iotx_http_context->keep_alive) { + httpclient_close(httpc); + } + + /* + body: + { + "code": 0, + "message": "success", + "info": { + "messageId": 892687627916247040, + "data": byte[]//may be NULL + } + } + */ + http_info("http response: \r\n\r\n%s\r\n", httpc_data.response_buf); + + pvalue = HTTP_LITE_JSON_VALUE_OF("code", httpc_data.response_buf); + if (!pvalue) { + goto do_exit_pre; + } + + response_code = atoi(pvalue); + HTTP_API_FREE(pvalue); + pvalue = NULL; + http_info("response code: %d", response_code); + + pvalue = HTTP_LITE_JSON_VALUE_OF("message", httpc_data.response_buf); + if (NULL == pvalue) { + goto do_exit_pre; + } + http_info("response_message: %s", pvalue); + HTTP_API_FREE(pvalue); + pvalue = NULL; + + switch (response_code) { + case IOTX_HTTP_SUCCESS: + break; + case IOTX_HTTP_TOKEN_EXPIRED_ERROR: + iotx_http_context->is_authed = IOT_FALSE; + IOT_HTTP_DeviceNameAuth((iotx_http_t *)iotx_http_context); + case IOTX_HTTP_COMMON_ERROR: + case IOTX_HTTP_PARAM_ERROR: + case IOTX_HTTP_AUTH_CHECK_ERROR: + case IOTX_HTTP_TOKEN_NULL_ERROR: + case IOTX_HTTP_TOKEN_CHECK_ERROR: + case IOTX_HTTP_UPDATE_SESSION_ERROR: + case IOTX_HTTP_PUBLISH_MESSAGE_ERROR: + case IOTX_HTTP_REQUEST_TOO_MANY_ERROR: + default: + goto do_exit_pre; + } + + /* info.messageId */ + pvalue = HTTP_LITE_JSON_VALUE_OF("info.messageId", httpc_data.response_buf); + if (NULL == pvalue) { + http_err("messageId: NULL"); + goto do_exit_pre; + } + messageId = pvalue; + http_info("messageId: %s", messageId); + (void)messageId; + HTTP_API_FREE(pvalue); + pvalue = NULL; + + /* info.data */ + pvalue = HTTP_LITE_JSON_VALUE_OF("info.data", httpc_data.response_buf); + user_data = pvalue; + + /* Maybe NULL */ + if (user_data) { + http_info("user_data: %s", user_data); + } else { + http_info("user_data: %p", user_data); + } + if (NULL != pvalue) { + HTTP_API_FREE(pvalue); + } + pvalue = NULL; + + ret = 0; + +do_exit_pre: + + if (pvalue) { + HTTP_API_FREE(pvalue); + } + + if (httpc != NULL && httpc->header) { + HTTP_API_FREE(httpc->header); + } + +do_exit: + + return ret; +} + +void IOT_HTTP_Disconnect(void *handle) +{ + iotx_http_t *iotx_http_context; + if (NULL != (iotx_http_context = verify_iotx_http_context(handle))) { + httpclient_close(iotx_http_context->httpc); + } +} + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_break_resume.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_break_resume.c new file mode 100644 index 00000000..1bfc9364 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_stream.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/examples/http2_example_stream.c new file mode 100644 index 00000000..4be80070 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_api.h new file mode 100644 index 00000000..1eda9fd0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_config.h new file mode 100644 index 00000000..d1bc5d38 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_internal.h new file mode 100644 index 00000000..0b97aa38 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.c new file mode 100644 index 00000000..0f9f2067 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_upload_api.h new file mode 100644 index 00000000..236a1791 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/http2_wrapper.h new file mode 100644 index 00000000..454401b2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iot.mk new file mode 100644 index 00000000..cffc110e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iotx_http2.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/http2/iotx_http2.c new file mode 100644 index 00000000..d73eb968 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_aes.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_aes.c new file mode 100644 index 00000000..90ccbbad --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_aes.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_aes.h new file mode 100644 index 00000000..f7c16748 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_aes_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_aes_config.h new file mode 100644 index 00000000..85c8f396 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_cjson.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_cjson.c new file mode 100644 index 00000000..b2260ca4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_cjson.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_cjson.h new file mode 100644 index 00000000..77c14b55 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_compat.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_compat.c new file mode 100644 index 00000000..7de7c9af --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_compat.c @@ -0,0 +1,287 @@ +#include "infra_config.h" + +#ifdef INFRA_COMPAT +#include +#include "infra_types.h" +#include "infra_defs.h" +#include "infra_compat.h" + +sdk_impl_ctx_t g_sdk_impl_ctx = {0}; + +#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); + +/* 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 = *(iotx_mqtt_region_types_t *)data; + /* iotx_guider_set_region(*(int *)data); */ + + res = SUCCESS_RETURN; + } + break; + case IOTX_IOCTL_GET_REGION: { + *(iotx_mqtt_region_types_t *)data = ctx->domain_type; + + res = SUCCESS_RETURN; + } + break; + case IOTX_IOCTL_SET_MQTT_DOMAIN: { + ctx->domain_type = IOTX_CLOUD_REGION_CUSTOM; + + if (strlen(data) > IOTX_DOMAIN_MAX_LEN) { + 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 (strlen(data) > IOTX_DOMAIN_MAX_LEN) { + 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 (strlen(data) > IOTX_CUSTOMIZE_INFO_LEN) { + 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_compat.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_compat.h new file mode 100644 index 00000000..4b58a8cc --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_compat.h @@ -0,0 +1,284 @@ +#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 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_config.h new file mode 100644 index 00000000..794ba028 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_config.h @@ -0,0 +1,5 @@ +#ifndef _INFRA_CONFIG_H_ +#define _INFRA_CONFIG_H_ + +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_defs.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_defs.c new file mode 100644 index 00000000..45d97ca0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_defs.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_defs.h new file mode 100644 index 00000000..21bb0523 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_defs.h @@ -0,0 +1,363 @@ +#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) +#define IOTX_DOMAIN_MAX_LEN (64) +#define IOTX_CUSTOMIZE_INFO_LEN (80) + +#define DEV_SIGN_SOURCE_MAXLEN (200) +#define DEV_SIGN_HOSTNAME_MAXLEN (64) +#define DEV_SIGN_CLIENT_ID_MAXLEN (200) +#define DEV_SIGN_USERNAME_MAXLEN (64) +#define DEV_SIGN_PASSWORD_MAXLEN (65) + +#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; + +/** + * @brief contains iot_ioctl context + * + */ +typedef struct { + int domain_type; + int dynamic_register; + char cloud_custom_domain[IOTX_DOMAIN_MAX_LEN + 1]; + uint16_t mqtt_port_num; + char http_custom_domain[IOTX_DOMAIN_MAX_LEN + 1]; + char mqtt_customzie_info[IOTX_CUSTOMIZE_INFO_LEN + 1]; +} sdk_impl_ctx_t; + +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; + +#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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_httpc.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_httpc.c new file mode 100644 index 00000000..9d02a878 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_httpc.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_httpc.h new file mode 100644 index 00000000..0148ede8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_httpc.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef _INFRA_HTTPC_H_ +#define _INFRA_HTTPC_H_ + +#include "infra_net.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup HttpClient + * @{ + * HttpClient API implements the client-side of HTTP/1.1. It provides base interfaces to execute an HTTP request on a given URL. It also supports HTTPS (HTTP over TLS) to provide secure communication.\n + * @section HttpClient_Usage_Chapter How to use this module + * In this release, MediaTek provides two types of APIs: high level APIs and low level APIs.\n + * - \b The \b high \b level \b APIs + * - Enables to execute a single HTTP request on a given URL. + * - Call #httpclient_get(), #httpclient_post(), #httpclient_put() or #httpclient_delete() to get, post, put or delete and HTTP request.\n + * - \b The \b low \b level \b APIs + * - Enables to execute more than one HTTP requests during a Keep-Alive connection. Keep-alive is the idea of using a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair. + * - Step1: Call #httpclient_connect() to connect to a remote server. + * - Step2: Call #httpclient_send_request() to send an HTTP request to the server. + * - Step3: Call #httpclient_recv_response() to receive an HTTP response from the server. + * - Step4: Repeat Steps 2 and 3 to execute more requests. + * - Step5: Call #httpclient_close() to close the connection. + * - Sample code: Please refer to the example under /project/mt7687_hdk/apps/http_client/http_client_keepalive folder. + */ + +/** @defgroup httpclient_define Define + * @{ + */ +/** @brief This macro defines the HTTP port. */ +#define HTTP_PORT 80 + +/** @brief This macro defines the HTTPS port. */ +#define HTTPS_PORT 443 +/** + * @} + */ + +/** @defgroup httpclient_enum Enum + * @{ + */ +/** @brief This enumeration defines the HTTP request type. */ +typedef enum { + HTTPCLIENT_GET, + HTTPCLIENT_POST, + HTTPCLIENT_PUT, + HTTPCLIENT_DELETE, + HTTPCLIENT_HEAD +} HTTPCLIENT_REQUEST_TYPE; + + +/** @defgroup httpclient_struct Struct + * @{ + */ +/** @brief This structure defines the httpclient_t structure. */ +typedef struct { + int remote_port; /**< HTTP or HTTPS port. */ + utils_network_t net; + int response_code; /**< Response code. */ + char *header; /**< Custom header. */ + char *auth_user; /**< Username for basic authentication. */ + char *auth_password; /**< Password for basic authentication. */ +} httpclient_t; + +/** @brief This structure defines the HTTP data structure. */ +typedef struct { + int is_more; /**< Indicates if more data needs to be retrieved. */ + int is_chunked; /**< Response data is encoded in portions/chunks.*/ + int retrieve_len; /**< Content length to be retrieved. */ + int response_content_len; /**< Response content length. */ + int response_received_len; /**< Response have received length. */ + int post_buf_len; /**< Post data length. */ + int response_buf_len; /**< Response buffer length. */ + char *post_content_type; /**< Content type of the post data. */ + char *post_buf; /**< User data to be posted. */ + char *response_buf; /**< Buffer to store the response data. */ +} httpclient_data_t; + +int iotx_post(httpclient_t *client, + const char *url, + int port, + const char *ca_crt, + httpclient_data_t *client_data); + +int httpclient_recv_response(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data); + +int httpclient_common(httpclient_t *client, const char *url, int port, const char *ca_crt, + HTTPCLIENT_REQUEST_TYPE method, uint32_t timeout_ms, httpclient_data_t *client_data); + +void httpclient_close(httpclient_t *client); + +#ifdef __cplusplus +} +#endif + +#endif /* __HTTPCLIENT_H__ */ + + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_json_parser.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_json_parser.c new file mode 100644 index 00000000..9de932ee --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_json_parser.c @@ -0,0 +1,845 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include "infra_config.h" + +#ifdef INFRA_JSON_PARSER + +#include +#include +#include +#include + +#include "infra_types.h" +#include "infra_json_parser.h" + +void *HAL_Malloc(uint32_t size); +void HAL_Free(void *ptr); +int HAL_Snprintf(char *str, const int len, const char *fmt, ...); + +#ifdef INFRA_LOG +#include "infra_log.h" +#define jparser_debug(...) log_debug("jparser", __VA_ARGS__) +#else +#define jparser_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0) +#endif + +#ifdef INFRA_MEM_STATS +#include "infra_mem_stats.h" +#define jparser_malloc(size) LITE_malloc(size, MEM_MAGIC, "jparser") +#define jparser_free(ptr) LITE_free(ptr) +#else +#define jparser_malloc(size) HAL_Malloc(size) +#define jparser_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;} +#endif + +char *json_get_object(int type, char *str, char *str_end) +{ + char *pos = NULL; + char ch = (type == JOBJECT) ? '{' : '['; + + if (!str || !str_end) { + return NULL; + } + + while (str != NULL && *str != 0 && str < str_end) { + if (*str == ' ') { + str++; + continue; + } + pos = (*str == ch) ? str : NULL; + break; + } + return pos; +} + +char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len, + char **val, int *val_len, int *val_type) +{ + char JsonMark[JTYPEMAX][2] = { { '\"', '\"' }, { '{', '}' }, { '[', ']' }, { '0', ' ' } }; + int iMarkDepth = 0, iValueType = JNONE, iNameLen = 0, iValueLen = 0, iStringDepth = 0; + char *p_cName = 0, *p_cValue = 0, *p_cPos = str; + + if (type == JOBJECT) { + /* Get Key */ + p_cPos = strchr(p_cPos, '\"'); + if (!p_cPos) { + goto do_exit; + } + p_cName = ++p_cPos; + p_cPos = strchr(p_cPos, '\"'); + if (!p_cPos) { + goto do_exit; + } + iNameLen = p_cPos - p_cName; + + /* Get Value */ + p_cPos = strchr(p_cPos, ':'); + } + while (p_cPos && *p_cPos && p_cPos < str_end) { + if (*p_cPos == '\"') { + iValueType = JSTRING; + p_cValue = ++p_cPos; + break; + } else if (*p_cPos == '{') { + iValueType = JOBJECT; + p_cValue = p_cPos++; + break; + } else if (*p_cPos == '[') { + iValueType = JARRAY; + p_cValue = p_cPos++; + break; + } else if ((*p_cPos == '-') || (*p_cPos >= '0' && *p_cPos <= '9')) { + iValueType = JNUMBER; + p_cValue = p_cPos++; + break; + } else if (*p_cPos == 't' || *p_cPos == 'T' || *p_cPos == 'f' || *p_cPos == 'F') { + iValueType = JBOOLEAN; + p_cValue = p_cPos; + break; + } + p_cPos++; + } + + while (p_cPos && *p_cPos && p_cPos < str_end && iValueType > JNONE) { + if (iValueType == JBOOLEAN) { + int len = strlen(p_cValue); + + if ((*p_cValue == 't' || *p_cValue == 'T') && len >= 4 + && (!strncmp(p_cValue, "true", 4) + || !strncmp(p_cValue, "TRUE", 4))) { + iValueLen = 4; + p_cPos = p_cValue + iValueLen; + break; + } else if ((*p_cValue == 'f' || *p_cValue == 'F') && len >= 5 + && (!strncmp(p_cValue, "false", 5) + || !strncmp(p_cValue, "FALSE", 5))) { + iValueLen = 5; + p_cPos = p_cValue + iValueLen; + break; + } + } else if (iValueType == JNUMBER) { + if ((*p_cPos < '0' || *p_cPos > '9') && (*p_cPos != '.') && (*p_cPos != '+') \ + && (*p_cPos != '-') && ((*p_cPos != 'e')) && (*p_cPos != 'E')) { + iValueLen = p_cPos - p_cValue; + break; + } + } else if (iValueType == JSTRING) { + if (*p_cPos == '\"') { + iValueLen = p_cPos - p_cValue; + break; + } + } else if (*p_cPos == JsonMark[iValueType][1]) { + if (iStringDepth == 0) { + if (iMarkDepth == 0) { + iValueLen = p_cPos - p_cValue + 1; + p_cPos++; + break; + } else { + iMarkDepth--; + } + } + } else if (*p_cPos == JsonMark[iValueType][0]) { + if (iStringDepth == 0) { + iMarkDepth++; + } + } else if (*p_cPos == '\"') { + if (iStringDepth) { + iStringDepth = 0; + } else { + iStringDepth = 1; + } + } + p_cPos++; + } + + if (type == JOBJECT) { + if ((p_cName + iNameLen) > str_end) { + goto do_exit; + } + *key = p_cName; + *key_len = iNameLen; + } + if ((p_cValue + iValueLen) > str_end) { + goto do_exit; + } + + *val = p_cValue; + *val_len = iValueLen; + *val_type = iValueType; + if (iValueType == JSTRING) { + return p_cValue + iValueLen + 1; + } else { + return p_cValue + iValueLen; + } + +do_exit: + *val = NULL; + *val_len = 0; + *key = NULL; + *key_len = 0; + return NULL; +} + +int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData) +{ + char *pos = 0, *key = 0, *val = 0; + int klen = 0, vlen = 0, vtype = 0; + int ret = JSON_RESULT_ERR; + + if (p_cJsonStr == NULL || iStrLen == 0 || pfnCB == NULL) { + return ret; + } + + json_object_for_each_kv(p_cJsonStr, iStrLen, pos, key, klen, val, vlen, vtype) { + if (key && klen && val && vlen) { + ret = JSON_RESULT_OK; + if (JSON_PARSE_FINISH == pfnCB(key, klen, val, vlen, vtype, p_CBData)) { + break; + } + } + } + + return ret; +} + +int json_get_value_by_name_cb(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType, + void *p_CBData) +{ + JSON_NV *p_stNameValue = (JSON_NV *)p_CBData; + +#ifdef JSON_DEBUG + int i; + + if (p_cName) { + jparser_debug("Name:"); + for (i = 0; i < iNameLen; i++) { + jparser_debug("%c", *(p_cName + i)); + } + } + + if (p_cValue) { + jparser_debug("Value:"); + for (i = 0; i < iValueLen; i++) { + jparser_debug("%c", *(p_cValue + i)); + } + } +#endif + + if ((iNameLen == p_stNameValue->nLen) && !strncmp(p_cName, p_stNameValue->pN, p_stNameValue->nLen)) { + p_stNameValue->pV = p_cValue; + p_stNameValue->vLen = iValueLen; + p_stNameValue->vType = iValueType; + return JSON_PARSE_FINISH; + } else { + return JSON_PARSE_OK; + } +} + +char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType) +{ + JSON_NV stNV; + + memset(&stNV, 0, sizeof(stNV)); + stNV.pN = p_cName; + stNV.nLen = strlen(p_cName); + if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) { + if (p_iValueLen) { + *p_iValueLen = stNV.vLen; + } + if (p_iValueType) { + *p_iValueType = stNV.vType; + } + } + return stNV.pV; +} + +char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen, + int *p_iValueType) +{ + JSON_NV stNV; + + memset(&stNV, 0, sizeof(stNV)); + stNV.pN = p_cName; + stNV.nLen = p_cNameLen; + if (JSON_RESULT_OK == json_parse_name_value(p_cJsonStr, iStrLen, json_get_value_by_name_cb, (void *)&stNV)) { + if (p_iValueLen) { + *p_iValueLen = stNV.vLen; + } + if (p_iValueType) { + *p_iValueType = stNV.vType; + } + } + return stNV.pV; +} + +char *LITE_json_value_of(char *key, char *src, ...) +{ + char *value = NULL; + char *ret = NULL; + char *delim = NULL; + char *key_iter; + char *key_next; + char *src_iter; + + int key_len; + int value_len = -1; + int src_iter_len; + + if (NULL == key || NULL == src) { + return NULL; + } + +#if WITH_MEM_STATS_PER_MODULE +{ + char *module_name = NULL; + int magic = 0; + va_list ap; + va_start(ap, src); + magic = va_arg(ap, int); + if (MEM_MAGIC == magic) { + module_name = va_arg(ap, char *); + } + va_end(ap); +} +#endif + + src_iter = src; + src_iter_len = strlen(src_iter); + key_iter = key; + + do { + if ((delim = strchr(key_iter, '.')) != NULL) { + key_len = delim - key_iter; + key_next = key_iter; + + value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0); + if (value == NULL) { + return NULL; + } + + src_iter = value; + src_iter_len = value_len; + key_iter = delim + 1; + } + } while (delim); + + key_len = strlen(key_iter); + key_next = key_iter; + value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0); + if (NULL == value) { + return NULL; + } + + ret = jparser_malloc((value_len + 1) * sizeof(char)); + + if (NULL == ret) { + return NULL; + } + + HAL_Snprintf(ret, value_len + 1, "%s", value); + return ret; +} + +#if WITH_JSON_KEYS_OF +static list_head_t *_LITE_json_keys_of(char *src, int src_len, char *prefix, ...) +{ + static 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); + char *module_name = NULL; + char *iter_pre = NULL; + char *pos = 0, *key = 0, *val = 0; + int klen = 0, vlen = 0, vtype = 0; + int magic = 0; + unsigned int count = 1; + unsigned int mlen = 0; + + if (src == NULL || prefix == NULL) { + return NULL; + } + +#if WITH_MEM_STATS_PER_MODULE + va_list ap; + va_start(ap, prefix); + magic = va_arg(ap, int); + if (MEM_MAGIC == magic) { + module_name = va_arg(ap, char *); + } + va_end(ap); +#endif + + if (!strcmp("", prefix)) { + INIT_LIST_HEAD(&keylist); + } + + if (JOBJECT == type) { + json_object_for_each_kv(src, src_len, pos, key, klen, val, vlen, vtype) { + if (key && klen && val && vlen) { + + json_key_t *entry = NULL; + + entry = jparser_malloc(sizeof(json_key_t), magic, module_name); + + if (NULL == entry) { + utils_err("jparser_malloc failed!"); + return NULL; + } + memset(entry, 0, sizeof(json_key_t)); + + mlen = strlen(prefix) + klen + 1; + if (module_name) { + entry->key = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key); + } else { + entry->key = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key); + } + + if (NULL == entry->key) { + jparser_free(entry); + return NULL; + } + + list_add_tail(&entry->list, &keylist); + + if (JOBJECT == vtype) { + mlen = strlen(prefix) + klen + 2; + if (module_name) { + iter_pre = LITE_format_nstring(mlen, "%s%.*s.", magic, module_name, prefix, klen, key); + } else { + iter_pre = LITE_format_nstring(mlen, "%s%.*s.", prefix, klen, key); + } + if (NULL == iter_pre) { + return NULL; + } + + _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); + jparser_free(iter_pre); + } else if (JARRAY == vtype) { + mlen = strlen(prefix) + klen + 1; + if (module_name) { + iter_pre = LITE_format_nstring(mlen, "%s%.*s", magic, module_name, prefix, klen, key); + } else { + iter_pre = LITE_format_nstring(mlen, "%s%.*s", prefix, klen, key); + } + if (NULL == iter_pre) { + return NULL; + } + + _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); + jparser_free(iter_pre); + } + } + } + } else if (JARRAY == type) { + json_array_for_each_entry(src, src_len, pos, val, vlen, vtype) { + if (val && vlen) { + + json_key_t *entry = NULL; + unsigned int tmp = 0; + unsigned int arridxlen = 0; + entry = jparser_malloc(sizeof(json_key_t), magic, module_name); + if (NULL == entry) { + utils_err("jparser_malloc failed!"); + return NULL; + } + memset(entry, 0, sizeof(json_key_t)); + + tmp = count; + do { + tmp /= 10; + ++arridxlen; + } while (tmp); + mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen; + if (module_name) { + entry->key = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count); + } else { + entry->key = LITE_format_nstring(mlen, "%s[%d]", prefix, count); + } + if (NULL == entry->key) { + jparser_free(entry); + return NULL; + } + + list_add_tail(&entry->list, &keylist); + + if (JOBJECT == vtype) { + mlen = strlen("%s[%d].") + strlen(prefix) + arridxlen; + if (module_name) { + iter_pre = LITE_format_nstring(mlen, "%s[%d].", magic, module_name, prefix, count); + } else { + iter_pre = LITE_format_nstring(mlen, "%s[%d].", prefix, count); + } + if (NULL == iter_pre) { + return NULL; + } + + _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); + jparser_free(iter_pre); + } else if (JARRAY == vtype) { + mlen = strlen("%s[%d]") + strlen(prefix) + arridxlen; + if (module_name) { + iter_pre = LITE_format_nstring(mlen, "%s[%d]", magic, module_name, prefix, count); + } else { + iter_pre = LITE_format_nstring(mlen, "%s[%d]", prefix, count); + } + if (NULL == iter_pre) { + return NULL; + } + + _LITE_json_keys_of_ext(vtype, val, vlen, iter_pre, magic, module_name); + jparser_free(iter_pre); + } + ++count; + } + } + } + + if (!strcmp("", prefix)) { + json_key_t *entry = NULL; + + entry = jparser_malloc(sizeof(json_key_t), magic, module_name); + if (NULL == entry) { + utils_err("jparser_malloc failed!"); + return NULL; + } + memset(entry, 0, sizeof(json_key_t)); + list_add_tail(&entry->list, &keylist); + + return &keylist; + } + + return NULL; + +} + +int contain_arr(const char *src, int src_len, const char **arr_pre) +{ + int i = 0; + int ret = -1; + int deep = 0; + const char *pre = NULL; + + if (NULL == src || NULL == arr_pre || src_len <= 0) { + return -1; + } + + *arr_pre = NULL; + for (i = 0; i < src_len; ++i) { + switch (src[i]) { + case '[': { + if (deep != 0) { + return ret; + } + ++deep; + if (!pre) { + pre = &src[i]; + } + } + break; + case ']': { + if (deep != 1) { + return ret; + } + --deep; + if ('[' == src[i - 1]) { + return ret; + } + } + break; + default: { + if ((pre != NULL) && (0 == deep)) { + return ret; + } + } + break; + } + } + if ((NULL != pre) && (pre < src + src_len) && (pre >= src)) { + *arr_pre = pre; + ret = 0; + } + return ret; +} + +static char *_json_value_by_arrname(char *src, int src_len, const char *key, int key_len, int *val_len) +{ + char *pos = src; + char *entry = NULL; + const char *p = NULL; + const char *arr_pre = key; + const char *arr_suf = NULL; + int vtype; + int loop; + int loop_tmp = 0; + do { + loop = 0; + + arr_pre = strchr(arr_pre, '['); + if (arr_pre && (arr_pre < key + key_len)) { + arr_suf = strchr(arr_pre, ']'); + } + if (arr_pre && arr_suf && (arr_suf < key + key_len)) { + loop_tmp = 0; + for (p = arr_pre + 1; p < arr_suf; ++p) { + if (*p > '9' || *p < '0') { + return NULL; + } + loop_tmp *= 10; + loop_tmp += *p - '0'; + + } + + pos = json_get_object(JARRAY, pos, src + src_len); + if (pos != 0 && *pos != 0) { + if (*pos == '[' && *(pos + 1) == ']') { + return NULL; + } + } + + json_array_for_each_entry(src, src_len, pos, entry, *val_len, vtype) { + if (entry && *val_len) { + if (++loop >= loop_tmp) { + break; + } + } + } + + if (loop != loop_tmp) { + return NULL; + } + src = entry; + arr_pre = arr_suf + 1; + } + } while (arr_pre && arr_suf && (arr_pre < key + key_len)); + return entry; +} + +void LITE_json_keys_release(list_head_t *keylist) +{ + json_key_t *pos, *tmp; + + if (NULL == keylist) { + return; + } + + list_for_each_entry_safe(pos, tmp, keylist, list, json_key_t) { + if (pos->key) { + jparser_free(pos->key); + } + list_del(&pos->list); + jparser_free(pos); + } +} + +list_head_t *LITE_json_keys_of_ext(char *src, char *prefix, ...) +{ + char *module_name = NULL; + int magic = 0; + +#if WITH_MEM_STATS_PER_MODULE + + va_list ap; + va_start(ap, prefix); + magic = va_arg(ap, int); + if (MEM_MAGIC == magic) { + module_name = va_arg(ap, char *); + } + va_end(ap); +#endif + + if (!src || !prefix) { + return NULL; + } + + return _LITE_json_keys_of_ext(JOBJECT, src, strlen(src), prefix, magic, module_name); +} + +static char *_LITE_json_value_of_ext(char *key, char *src, int src_len, int *val_len) +{ + char *value = NULL; + char *delim = NULL; + char *key_iter; + char *key_next; + char *src_iter; + const char *arr_pre = NULL; + + int value_len; + int key_len; + int obj_key_len = 0; + int key_type; + int src_iter_len; + + src_iter = src; + src_iter_len = src_len; + key_iter = key; + value_len = src_iter_len; + do { + if ((delim = strchr(key_iter, '.')) != NULL) { + key_len = delim - key_iter; + key_type = JOBJECT; + key_next = key_iter; + if (0 == contain_arr(key_next, key_len, &arr_pre)) { + key_type = JARRAY; + obj_key_len = arr_pre - key_iter; + if (obj_key_len) { + value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0); + } else { + value = src_iter; + } + } else { + value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0); + } + + if (NULL == value) { + return NULL; + } + + if (key_type == JARRAY) { + if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) { + return NULL; + } + } + src_iter = value; + src_iter_len = value_len; + key_iter = delim + 1; + + } + } while (delim); + + key_len = strlen(key_iter); + key_next = key_iter; + key_type = JOBJECT; + if (0 == contain_arr(key_next, key_len, &arr_pre)) { + key_type = JARRAY; + obj_key_len = arr_pre - key_iter; + if (obj_key_len) { + value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, obj_key_len, &value_len, 0); + } else { + value = src_iter; + } + } else { + value = json_get_value_by_name_len(src_iter, src_iter_len, key_next, key_len, &value_len, 0); + } + + if (NULL == value) { + return NULL; + } + if (key_type == JARRAY) { + if (NULL == (value = _json_value_by_arrname(value, value_len, arr_pre, key_len - obj_key_len, &value_len))) { + return NULL; + } + } + *val_len = value_len; + return value; +} + +#endif /* #if WITH_JSON_TOKEN_EXT */ +#endif /* #if WITH_JSON_KEYS_OF */ +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_json_parser.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_json_parser.h new file mode 100644 index 00000000..4224964b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_json_parser.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef _INFRA_JSON_PARSER_H_ +#define _INFRA_JSON_PARSER_H_ + +/* #include "iotx_utils_internal.h" */ + +typedef struct JSON_NV { + int nLen; + int vLen; + int vType; + char *pN; + char *pV; +} JSON_NV; + +/** +The descriptions of the json value node type +**/ +enum JSONTYPE { + JNONE = -1, + JSTRING = 0, + JOBJECT, + JARRAY, + JNUMBER, + JBOOLEAN, + JTYPEMAX +}; + +/** +The error codes produced by the JSON parsers +**/ +enum JSON_PARSE_CODE { + JSON_PARSE_ERR, + JSON_PARSE_OK, + JSON_PARSE_FINISH +}; + +/** +The return codes produced by the JSON parsers +**/ +enum JSON_PARSE_RESULT { + JSON_RESULT_ERR = -1, + JSON_RESULT_OK +}; + +typedef int (*json_parse_cb)(char *p_cName, int iNameLen, char *p_cValue, int iValueLen, int iValueType, + void *p_Result); + +/** +* @brief Parse the JSON string, and iterate through all keys and values, +* then handle the keys and values by callback function. +* +* @param[in] p_cJsonStr @n The JSON string +* @param[in] iStrLen @n The JSON string length +* @param[in] pfnCB @n Callback function +* @param[out] p_CBData @n User data +* @return JSON_RESULT_OK success, JSON_RESULT_ERR failed +* @see None. +* @note None. +**/ +int json_parse_name_value(char *p_cJsonStr, int iStrLen, json_parse_cb pfnCB, void *p_CBData); + +/** +* @brief Get the value by a specified key from a json string +* +* @param[in] p_cJsonStr @n the JSON string +* @param[in] iStrLen @n the JSON string length +* @param[in] p_cName @n the specified key string +* @param[out] p_iValueLen @n the value length +* @param[out] p_iValueType @n the value type +* @return A pointer to the value +* @see None. +* @note None. +**/ +char *json_get_value_by_name(char *p_cJsonStr, int iStrLen, char *p_cName, int *p_iValueLen, int *p_iValueType); + +/** +* @brief Get the value by a specified key from a json string +* +* @param[in] p_cJsonStr @n the JSON string +* @param[in] iStrLen @n the JSON string length +* @param[in] p_cName @n the specified key string +* @param[in] p_cNameLen @n the specified key string length +* @param[out] p_iValueLen @n the value length +* @param[out] p_iValueType @n the value type +* @return A pointer to the value +* @see None. +* @note None. +**/ +char *json_get_value_by_name_len(char *p_cJsonStr, int iStrLen, char *p_cName, int p_cNameLen, int *p_iValueLen, + int *p_iValueType); + +/** + * @brief Get the JSON object point associate with a given type. + * + * @param[in] type @n The object type + * @param[in] str @n The JSON string + * @param[in] str_end @n The end point of Json string + * @returns The json object point with the given field type. + * @see None. + * @note None. + */ +char *json_get_object(int type, char *str, char *str_end); +char *json_get_next_object(int type, char *str, char *str_end, char **key, int *key_len, char **val, int *val_len, + int *val_type); + +/** + * @brief retrieve each key&value pair from the json string + * + * @param[in] str @n Json string to revolve + * @param[in] slen @n The length of json string + * @param[in] pos @n cursor + * @param[out] key @n pointer to the next Key object + * @param[out] klen @n Key object length + * @param[out] val @n pointer to the next Value object + * @param[out] vlen @n Value object length + * @param[out] vtype @n Value object type(digital, string, object, array) + * @see None. + * @note None. + */ +#define json_object_for_each_kv(str, slen, pos, key, klen, val, vlen, vtype) \ + for (pos = json_get_object(JOBJECT, str, str + slen); \ + pos != NULL && *pos!= 0 && (pos=json_get_next_object(JOBJECT, pos, str + slen , &key, &klen, &val, &vlen, &vtype))!=0; ) + +/** + * @brief retrieve each entry from the json array + * + * @param[in] str @n Json array to revolve + * @param[in] slen @n the length of Json array + * @param[in] pos @n cursor + * @param[out] entry @n pointer to the next entry from the array + * @param[out] len @n entry length + * @param[out] type @n entry type(digital, string, object, array) + * @see None. + * @note None. + */ +#define json_array_for_each_entry(str, slen, pos, entry, len, type) \ + for (pos = json_get_object(JARRAY, str, str + slen); \ + pos != NULL && *pos!= 0 && (pos=json_get_next_object(JARRAY, ++pos, str + slen, 0, 0, &entry, &len, &type))!=0; ) + + +/** + * @brief backup the last character to register parameters, + * and set the end character with '\0' + * + * @param[in] json_str @n json string + * @param[in] str_len @n json string lenth + * @param[out] register @n used to backup the last character + * @see None. + * @note None. + */ +#define backup_json_str_last_char(json_str, str_len, register) { \ + register = *((char *)json_str + str_len); \ + *((char *)json_str + str_len) = '\0'; \ + } + +/** + * @brief restore the last character from register parameters + * + * @param[in] json_str @n json string + * @param[in] str_len @n json string lenth + * @param[in] register @n used to restore the last character + * @see None. + * @note None. + */ +#define restore_json_str_last_char(json_str, str_len, register) { \ + *((char *)json_str + str_len) = register; \ + } + +char *LITE_json_value_of(char *key, char *src, ...); + +#endif /* __JSON_PARSER_H__ */ + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_list.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_list.h new file mode 100644 index 00000000..b2d6c35e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_log.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_log.c new file mode 100644 index 00000000..add4f6ee --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_log.c @@ -0,0 +1,266 @@ +#include "infra_config.h" + +extern void **LITE_get_mem_mutex(void); +extern void *HAL_MutexCreate(void); +extern void HAL_MutexDestroy(void *); + +#include +#include +#include "infra_compat.h" +#include "infra_log.h" +#if defined(INFRA_CJSON) + #include "infra_cjson.h" +#endif + +#if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED) +static log_client logcb = { + .name = "linkkit", + .priority = LOG_DEBUG_LEVEL, + .text_buf = {0} +}; + +static char *lvl_names[] = { + "non", "crt", "err", "wrn", "inf", "dbg", "flw" +}; + +/* 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white. */ +char *lvl_color[] = { + "[0m", "[1;31m", "[1;31m", "[1;35m", "[1;33m", "[1;36m", "[1;37m" +}; + +void LITE_syslog_routine(char *m, const char *f, const int l, const int level, const char *fmt, va_list *params) +{ + char *tmpbuf = logcb.text_buf; + char *o = tmpbuf; + int truncated = 0; + + if (LITE_get_loglevel() < level || level < LOG_NONE_LEVEL) { + return; + } + +#if !defined(_WIN32) + LITE_printf("%s%s", "\033", lvl_color[level]); + LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l); +#endif /* #if !defined(_WIN32) */ + + memset(tmpbuf, 0, sizeof(logcb.text_buf)); + + o = tmpbuf; + o += LITE_vsnprintf(o, LOG_MSG_MAXLEN + 1, fmt, *params); + + if (o - tmpbuf > LOG_MSG_MAXLEN) { + o = tmpbuf + strlen(tmpbuf); + truncated = 1; + } + if (strlen(tmpbuf) == LOG_MSG_MAXLEN) { + truncated = 1; + } + + LITE_printf("%s", tmpbuf); + if (truncated) { + LITE_printf(" ..."); + } + + if (tmpbuf[strlen(tmpbuf) - 1] != '\n') { + LITE_printf("\r\n"); + } + +#if !defined(_WIN32) + LITE_printf("%s", "\033[0m"); +#endif /* #if !defined(_WIN32) */ + return; +} + +void LITE_syslog(char *m, const char *f, const int l, const int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + LITE_syslog_routine(m, f, l, level, fmt, &ap); + va_end(ap); +} + +int LITE_get_loglevel(void) +{ + return logcb.priority; +} + +void LITE_set_loglevel(int pri) +{ + void **mutex = NULL; + logcb.priority = pri; + +#if WITH_MEM_STATS + mutex = LITE_get_mem_mutex(); + if (pri != LOG_NONE_LEVEL) { + if (*mutex == NULL) { + *mutex = HAL_MutexCreate(); + if (*mutex == NULL) { + LITE_printf("\nCreate memStats mutex error\n"); + } + } + } else if (*mutex != NULL) { + HAL_MutexDestroy(*mutex); + *mutex = NULL; + } +#endif +} + +void LITE_rich_hexdump(const char *f, const int l, + const int level, + const char *buf_str, + const void *buf_ptr, + const int buf_len) +{ + if (LITE_get_loglevel() < level) { + return; + } + + LITE_printf("%s%s", "\033", lvl_color[level]); + LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l); + LITE_printf("HEXDUMP %s @ %p[%d]\r\n", buf_str, buf_ptr, buf_len); + LITE_hexdump(buf_str, buf_ptr, buf_len); + + LITE_printf("%s", "\033[0m"); + return; +} + +int log_multi_line_internal(const char *f, const int l, + const char *title, int level, char *payload, const char *mark) +{ + const char *pos; + const char *endl; + int i; + + if (LITE_get_loglevel() < level) { + return 1; + } + + LITE_printf("[%s] %s(%d): %s (Length: %d Bytes)\r\n", + lvl_names[LITE_get_loglevel()], f, l, title, (int)strlen(payload)); + + pos = payload; + while (pos && *pos) { + LITE_printf("%s ", mark); + + if (*pos == '\r') { + LITE_printf("\r\n"); + pos += 2; + continue; + } + + endl = strchr(pos + 1, '\r'); + if (endl == NULL) { + endl = pos; + do { + ++endl; + } while (*endl); + } + + for (i = 0; i < endl - pos; ++i) { + LITE_printf("%c", pos[i]); + } + LITE_printf("\r\n"); + + pos = *endl ? endl + 2 : 0; + } + + return 0; +} + +#define LITE_HEXDUMP_DRAWLINE(start_mark, len, end_mark) \ + do { \ + int i; \ + \ + LITE_printf("%s", start_mark); \ + for(i = 0; i < len; ++i) { LITE_printf("-"); } \ + LITE_printf("%s", end_mark); \ + LITE_printf("\r\n"); \ + \ + } while(0) + +int LITE_hexdump(const char *title, const void *buff, const int len) +{ + int i, j, written; + unsigned char ascii[20] = {0}; + char header[64] = {0}; + unsigned char *buf = (unsigned char *)buff; + + LITE_snprintf(header, sizeof(header), "| %s: (len=%d) |\r\n", title, (int)len); + + LITE_HEXDUMP_DRAWLINE("+", strlen(header) - 4, "+"); + LITE_printf("%s", header); + LITE_printf("%s\r\n", HEXDUMP_SEP_LINE); + + written = 0; + for (i = 0; i < len; ++ i) { + if (i % 16 == 0) { + LITE_printf("| %08X: ", (unsigned int)(i + (long)buff)); + written += 8; + } + + LITE_printf("%02X", buf[i]); + written += 2; + + if (i % 2 == 1) { + LITE_printf(" "); + written += 1; + } + LITE_snprintf((char *)ascii + i % 16, (1 + 1), "%c", ((buf[i] >= ' ' && buf[i] <= '~') ? buf[i] : '.')); + + if (((i + 1) % 16 == 0) || (i == len - 1)) { + for (j = 0; j < 48 - written; ++j) { + LITE_printf(" "); + } + + LITE_printf(" %s", ascii); + LITE_printf("\r\n"); + + written = 0; + memset(ascii, 0, sizeof(ascii)); + } + } + LITE_printf("%s\r\n", HEXDUMP_SEP_LINE); + + return 0; +} + +void IOT_SetLogLevel(IOT_LogLevel level) +{ + int lvl = (int)level; + + if (lvl > LOG_DEBUG_LEVEL) { + HAL_Printf("Invalid input level: %d out of [%d, %d]", level, + LOG_NONE_LEVEL, + LOG_DEBUG_LEVEL); + return; + } + + LITE_set_loglevel(lvl); + HAL_Printf("[prt] log level set as: [ %d ]\r\n", lvl); +} + +#else + +void IOT_SetLogLevel(IOT_LogLevel level) +{ + return; +} + +int log_multi_line_internal(const char *f, const int l, + const char *title, int level, char *payload, const char *mark) +{ + return 0; +} + +void LITE_rich_hexdump(const char *f, const int l, + const int level, + const char *buf_str, + const void *buf_ptr, + const int buf_len) +{ + return; +} + +#endif /* #if defined(INFRA_LOG) && !defined(INFRA_LOG_ALL_MUTED) */ + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_log.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_log.h new file mode 100644 index 00000000..1a8572ea --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_md5.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_md5.c new file mode 100644 index 00000000..cd8dc648 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_md5.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include "infra_config.h" + +#ifdef INFRA_MD5 + +#include +#include + +#include "infra_md5.h" + +#define MD5_KEY_IOPAD_SIZE (64) +#define MD5_DIGEST_SIZE (16) + +/* Implementation that should never be optimized out by the compiler */ +static void utils_md5_zeroize(void *v, size_t n) +{ + volatile unsigned char *p = v; + while (n--) { + *p++ = 0; + } +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef IOT_MD5_GET_UINT32_LE +#define IOT_MD5_GET_UINT32_LE(n,b,i) \ + { \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ + } +#endif + +#ifndef IOT_MD5_PUT_UINT32_LE +#define IOT_MD5_PUT_UINT32_LE(n,b,i) \ + { \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ + } +#endif + +void utils_md5_init(iot_md5_context *ctx) +{ + memset(ctx, 0, sizeof(iot_md5_context)); +} + +void utils_md5_free(iot_md5_context *ctx) +{ + if (ctx == NULL) { + return; + } + + utils_md5_zeroize(ctx, sizeof(iot_md5_context)); +} + +void utils_md5_clone(iot_md5_context *dst, + const iot_md5_context *src) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +void utils_md5_starts(iot_md5_context *ctx) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]) +{ + uint32_t X[16], A, B, C, D; + + IOT_MD5_GET_UINT32_LE(X[ 0], data, 0); + IOT_MD5_GET_UINT32_LE(X[ 1], data, 4); + IOT_MD5_GET_UINT32_LE(X[ 2], data, 8); + IOT_MD5_GET_UINT32_LE(X[ 3], data, 12); + IOT_MD5_GET_UINT32_LE(X[ 4], data, 16); + IOT_MD5_GET_UINT32_LE(X[ 5], data, 20); + IOT_MD5_GET_UINT32_LE(X[ 6], data, 24); + IOT_MD5_GET_UINT32_LE(X[ 7], data, 28); + IOT_MD5_GET_UINT32_LE(X[ 8], data, 32); + IOT_MD5_GET_UINT32_LE(X[ 9], data, 36); + IOT_MD5_GET_UINT32_LE(X[10], data, 40); + IOT_MD5_GET_UINT32_LE(X[11], data, 44); + IOT_MD5_GET_UINT32_LE(X[12], data, 48); + IOT_MD5_GET_UINT32_LE(X[13], data, 52); + IOT_MD5_GET_UINT32_LE(X[14], data, 56); + IOT_MD5_GET_UINT32_LE(X[15], data, 60); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ + { \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P(A, B, C, D, 0, 7, 0xD76AA478); + P(D, A, B, C, 1, 12, 0xE8C7B756); + P(C, D, A, B, 2, 17, 0x242070DB); + P(B, C, D, A, 3, 22, 0xC1BDCEEE); + P(A, B, C, D, 4, 7, 0xF57C0FAF); + P(D, A, B, C, 5, 12, 0x4787C62A); + P(C, D, A, B, 6, 17, 0xA8304613); + P(B, C, D, A, 7, 22, 0xFD469501); + P(A, B, C, D, 8, 7, 0x698098D8); + P(D, A, B, C, 9, 12, 0x8B44F7AF); + P(C, D, A, B, 10, 17, 0xFFFF5BB1); + P(B, C, D, A, 11, 22, 0x895CD7BE); + P(A, B, C, D, 12, 7, 0x6B901122); + P(D, A, B, C, 13, 12, 0xFD987193); + P(C, D, A, B, 14, 17, 0xA679438E); + P(B, C, D, A, 15, 22, 0x49B40821); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P(A, B, C, D, 1, 5, 0xF61E2562); + P(D, A, B, C, 6, 9, 0xC040B340); + P(C, D, A, B, 11, 14, 0x265E5A51); + P(B, C, D, A, 0, 20, 0xE9B6C7AA); + P(A, B, C, D, 5, 5, 0xD62F105D); + P(D, A, B, C, 10, 9, 0x02441453); + P(C, D, A, B, 15, 14, 0xD8A1E681); + P(B, C, D, A, 4, 20, 0xE7D3FBC8); + P(A, B, C, D, 9, 5, 0x21E1CDE6); + P(D, A, B, C, 14, 9, 0xC33707D6); + P(C, D, A, B, 3, 14, 0xF4D50D87); + P(B, C, D, A, 8, 20, 0x455A14ED); + P(A, B, C, D, 13, 5, 0xA9E3E905); + P(D, A, B, C, 2, 9, 0xFCEFA3F8); + P(C, D, A, B, 7, 14, 0x676F02D9); + P(B, C, D, A, 12, 20, 0x8D2A4C8A); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P(A, B, C, D, 5, 4, 0xFFFA3942); + P(D, A, B, C, 8, 11, 0x8771F681); + P(C, D, A, B, 11, 16, 0x6D9D6122); + P(B, C, D, A, 14, 23, 0xFDE5380C); + P(A, B, C, D, 1, 4, 0xA4BEEA44); + P(D, A, B, C, 4, 11, 0x4BDECFA9); + P(C, D, A, B, 7, 16, 0xF6BB4B60); + P(B, C, D, A, 10, 23, 0xBEBFBC70); + P(A, B, C, D, 13, 4, 0x289B7EC6); + P(D, A, B, C, 0, 11, 0xEAA127FA); + P(C, D, A, B, 3, 16, 0xD4EF3085); + P(B, C, D, A, 6, 23, 0x04881D05); + P(A, B, C, D, 9, 4, 0xD9D4D039); + P(D, A, B, C, 12, 11, 0xE6DB99E5); + P(C, D, A, B, 15, 16, 0x1FA27CF8); + P(B, C, D, A, 2, 23, 0xC4AC5665); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P(A, B, C, D, 0, 6, 0xF4292244); + P(D, A, B, C, 7, 10, 0x432AFF97); + P(C, D, A, B, 14, 15, 0xAB9423A7); + P(B, C, D, A, 5, 21, 0xFC93A039); + P(A, B, C, D, 12, 6, 0x655B59C3); + P(D, A, B, C, 3, 10, 0x8F0CCC92); + P(C, D, A, B, 10, 15, 0xFFEFF47D); + P(B, C, D, A, 1, 21, 0x85845DD1); + P(A, B, C, D, 8, 6, 0x6FA87E4F); + P(D, A, B, C, 15, 10, 0xFE2CE6E0); + P(C, D, A, B, 6, 15, 0xA3014314); + P(B, C, D, A, 13, 21, 0x4E0811A1); + P(A, B, C, D, 4, 6, 0xF7537E82); + P(D, A, B, C, 11, 10, 0xBD3AF235); + P(C, D, A, B, 2, 15, 0x2AD7D2BB); + P(B, C, D, A, 9, 21, 0xEB86D391); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +/* + * MD5 process buffer + */ +void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen) +{ + uint32_t fill; + uint32_t left; + + if (ilen == 0) { + return; + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < (uint32_t) ilen) { + ctx->total[1]++; + } + + if (left && ilen >= fill) { + memcpy((void *)(ctx->buffer + left), input, fill); + utils_md5_process(ctx, ctx->buffer); + input += fill; + ilen -= fill; + left = 0; + } + + while (ilen >= 64) { + utils_md5_process(ctx, input); + input += 64; + ilen -= 64; + } + + if (ilen > 0) { + memcpy((void *)(ctx->buffer + left), input, ilen); + } +} + +static const unsigned char iot_md5_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD5 final digest + */ +void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]) +{ + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + IOT_MD5_PUT_UINT32_LE(low, msglen, 0); + IOT_MD5_PUT_UINT32_LE(high, msglen, 4); + + last = ctx->total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + utils_md5_update(ctx, iot_md5_padding, padn); + utils_md5_update(ctx, msglen, 8); + + IOT_MD5_PUT_UINT32_LE(ctx->state[0], output, 0); + IOT_MD5_PUT_UINT32_LE(ctx->state[1], output, 4); + IOT_MD5_PUT_UINT32_LE(ctx->state[2], output, 8); + IOT_MD5_PUT_UINT32_LE(ctx->state[3], output, 12); +} + + +/* + * output = MD5( input buffer ) + */ +void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16]) +{ + iot_md5_context ctx; + + utils_md5_init(&ctx); + utils_md5_starts(&ctx); + utils_md5_update(&ctx, input, ilen); + utils_md5_finish(&ctx, output); + utils_md5_free(&ctx); +} + +static int8_t utils_hb2hex(uint8_t hb) +{ + hb = hb & 0xF; + return (int8_t)(hb < 10 ? '0' + hb : hb - 10 + 'a'); +} + +void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len) +{ + iot_md5_context context; + unsigned char k_ipad[MD5_KEY_IOPAD_SIZE]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[MD5_KEY_IOPAD_SIZE]; /* outer padding - key XORd with opad */ + unsigned char out[MD5_DIGEST_SIZE]; + int i; + + if ((NULL == msg) || (NULL == digest) || (NULL == key)) { + return; + } + + if (key_len > MD5_KEY_IOPAD_SIZE) { + return; + } + + /* start out by storing key in pads */ + memset(k_ipad, 0, sizeof(k_ipad)); + memset(k_opad, 0, sizeof(k_opad)); + memcpy(k_ipad, key, key_len); + memcpy(k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < MD5_KEY_IOPAD_SIZE; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + utils_md5_init(&context); /* init context for 1st pass */ + utils_md5_starts(&context); /* setup context for 1st pass */ + utils_md5_update(&context, k_ipad, MD5_KEY_IOPAD_SIZE); /* start with inner pad */ + utils_md5_update(&context, (unsigned char *) msg, msg_len); /* then text of datagram */ + utils_md5_finish(&context, out); /* finish up 1st pass */ + + /* perform outer MD5 */ + utils_md5_init(&context); /* init context for 2nd pass */ + utils_md5_starts(&context); /* setup context for 2nd pass */ + utils_md5_update(&context, k_opad, MD5_KEY_IOPAD_SIZE); /* start with outer pad */ + utils_md5_update(&context, out, MD5_DIGEST_SIZE); /* then results of 1st hash */ + utils_md5_finish(&context, out); /* finish up 2nd pass */ + + for (i = 0; i < MD5_DIGEST_SIZE; ++i) { + digest[i * 2] = utils_hb2hex(out[i] >> 4); + digest[i * 2 + 1] = utils_hb2hex(out[i]); + } +} + +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_md5.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_md5.h new file mode 100644 index 00000000..f850163e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_md5.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef _INFRA_MD5_H_ +#define _INFRA_MD5_H_ + +#include "infra_types.h" + +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} iot_md5_context; + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + */ +void utils_md5_init(iot_md5_context *ctx); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + */ +void utils_md5_free(iot_md5_context *ctx); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void utils_md5_clone(iot_md5_context *dst, + const iot_md5_context *src); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + */ +void utils_md5_starts(iot_md5_context *ctx); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void utils_md5_update(iot_md5_context *ctx, const unsigned char *input, uint32_t ilen); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + */ +void utils_md5_finish(iot_md5_context *ctx, unsigned char output[16]); + +/* Internal use */ +void utils_md5_process(iot_md5_context *ctx, const unsigned char data[64]); + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + */ +void utils_md5(const unsigned char *input, uint32_t ilen, unsigned char output[16]); + +void utils_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len); + +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_mem_stats.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_mem_stats.c new file mode 100644 index 00000000..21c96d31 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_mem_stats.c @@ -0,0 +1,711 @@ +/* + * 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 + +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); +LIST_HEAD(mem_module_statis); + +typedef struct { + char *func_name; + int line; + list_head_t func_head; +} calling_stack_t; + +typedef struct { + char module_name[32]; + calling_stack_t calling_stack; + int bytes_total_allocated; + int bytes_total_freed; + int bytes_total_in_use; + int bytes_max_allocated; + int bytes_max_in_use; + int iterations_allocated; + int iterations_freed; + int iterations_in_use; + int iterations_max_in_use; +} mem_statis_t; + +typedef struct { + mem_statis_t mem_statis; + list_head_t list; +} module_mem_t; + +/* 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 (a == NULL || b == NULL) { + return 0; + } + + /* 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 + + void *buffer[MAX_BT_LEVEL]; + + *level = backtrace(buffer, MAX_BT_LEVEL); + *trace = backtrace_symbols(buffer, *level); + if (*trace == NULL) { + utils_err("backtrace_symbols returns NULL!"); + return -1; + } + + return 0; +} + +void LITE_track_malloc_callstack(int state) +{ + tracking_malloc_callstack = state; +} + +#else +void LITE_track_malloc_callstack(int state) +{ + +} + +#endif /* defined(__UBUNTU_SDK_DEMO__) */ + +void *LITE_realloc_internal(const char *f, const int l, void *ptr, int size, ...) +{ + void *temp = NULL; + int magic = 0; + char *module_name = NULL; + va_list ap; + + if (size <= 0) { + return NULL; + } + + va_start(ap, size); + magic = va_arg(ap, int); + if (MEM_MAGIC == magic) { + module_name = va_arg(ap, char *); + } + va_end(ap); + + temp = LITE_malloc_internal(f, l, size, magic, module_name); + + if (NULL == temp) { + utils_err("allocate %d bytes from %s(%d) failed", size, f, l); + return NULL; + } + + if (ptr) { + memcpy(temp, ptr, size); + + LITE_free(ptr); + + } + + return temp; +} + +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 = HAL_Malloc(sizeof(module_mem_t)); + if (!pos) { + return NULL; + } + memset(pos, 0, sizeof(module_mem_t)); + 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); + + list_add_tail(&pos->list, list_head); + return (void *)pos; +} + +void *_find_mem_table(char *module_name, struct list_head *list_head) +{ + + module_mem_t *pos = NULL, *tmp = NULL; + + if (!module_name || !list_head) { + return NULL; + } + + list_for_each_entry_safe(pos, tmp, list_head, list, module_mem_t) { + if (!strcmp(module_name, pos->mem_statis.module_name)) { + return (void *)pos; + } + } + + return NULL; +} + +int _del_mem_table(char *module_name, struct list_head *list_head) +{ + int ret = -1; + + calling_stack_t *calling_stack_pos = NULL, *tmp = NULL; + module_mem_t *table_pos = (module_mem_t *)_find_mem_table(module_name, list_head); + if (table_pos) { + list_for_each_entry_safe(calling_stack_pos, tmp, \ + &table_pos->mem_statis.calling_stack.func_head, func_head, calling_stack_t) { + if (calling_stack_pos) { + list_del(&calling_stack_pos->func_head); + if (calling_stack_pos->func_name) { + HAL_Free(calling_stack_pos->func_name); + calling_stack_pos->func_name = NULL; + } + HAL_Free(calling_stack_pos); + calling_stack_pos = NULL; + } + } + + list_del(&table_pos->list); + HAL_Free(table_pos); + table_pos = NULL; + ret = 0; + } + return ret; +} + +int _count_malloc_internal(const char *f, const int l, OS_malloc_record *os_malloc_pos, va_list ap) +{ + int ret = -1; + + int magic = 0; + char is_repeat = 0; + char *module_name = NULL; + module_mem_t *pos = NULL; + calling_stack_t *call_pos, *call_tmp; + calling_stack_t *entry = NULL; + + magic = va_arg(ap, int); + if (MEM_MAGIC == magic) { + module_name = va_arg(ap, char *); + } else { + module_name = "unknown"; + } + + 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))) { + utils_err("create_mem_table:[%s] failed!", module_name); + return ret; + } + } + os_malloc_pos->mem_table = (void *)pos; + + if (!strcmp(pos->mem_statis.module_name, "unknown")) { + list_for_each_entry_safe(call_pos, call_tmp, &pos->mem_statis.calling_stack.func_head, func_head, calling_stack_t) { + if (!strcmp(call_pos->func_name, f) && (call_pos->line == l)) { + is_repeat = 1; + break; + } + } + if (!is_repeat) { + entry = HAL_Malloc(sizeof(calling_stack_t)); + if (!entry) { + return ret; + } + + memset(entry, 0, sizeof(calling_stack_t)); + entry->func_name = LITE_strdup(f); + entry->line = l; + list_add(&entry->func_head, &pos->mem_statis.calling_stack.func_head); + } + } + + pos->mem_statis.iterations_allocated += 1; + pos->mem_statis.bytes_total_allocated += os_malloc_pos->buflen; + pos->mem_statis.bytes_total_in_use += os_malloc_pos->buflen; + pos->mem_statis.bytes_max_in_use = (pos->mem_statis.bytes_max_in_use > pos->mem_statis.bytes_total_in_use) ? + pos->mem_statis.bytes_max_in_use : pos->mem_statis.bytes_total_in_use; + pos->mem_statis.bytes_max_allocated = (pos->mem_statis.bytes_max_allocated >= os_malloc_pos->buflen) ? + pos->mem_statis.bytes_max_allocated : os_malloc_pos->buflen; + + pos->mem_statis.iterations_in_use += 1; + pos->mem_statis.iterations_max_in_use = (pos->mem_statis.iterations_in_use > pos->mem_statis.iterations_max_in_use) ? + pos->mem_statis.iterations_in_use : pos->mem_statis.iterations_max_in_use; + ret = 0; + + return ret; +} + +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) { + utils_err("find mem_table faild"); + return; + } + + pos->mem_statis.iterations_freed += 1; + pos->mem_statis.iterations_in_use -= 1; + + pos->mem_statis.bytes_total_freed += os_malloc_pos->buflen; + pos->mem_statis.bytes_total_in_use -= os_malloc_pos->buflen; +} + +void *LITE_malloc_internal(const char *f, const int l, int size, ...) +{ + void *ptr = NULL; + OS_malloc_record *pos; + + if (size <= 0) { + return NULL; + } + + 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; + bytes_max_in_use = (bytes_max_in_use > bytes_total_in_use) ? bytes_max_in_use : bytes_total_in_use; + bytes_max_allocated = (bytes_max_allocated >= size) ? bytes_max_allocated : size; + +#if defined(WITH_TOTAL_COST_WARNING) + if (bytes_total_in_use > WITH_TOTAL_COST_WARNING) { + utils_debug(" "); + utils_debug("==== PRETTY HIGH TOTAL IN USE: %d BYTES ====", bytes_total_in_use); + LITE_dump_malloc_free_stats(LOG_DEBUG_LEVEL); + } +#endif + + iterations_in_use += 1; + iterations_max_in_use = (iterations_in_use > iterations_max_in_use) ? iterations_in_use : iterations_max_in_use; + + pos = HAL_Malloc(sizeof(OS_malloc_record)); + if (NULL == pos) { + HAL_Free(ptr); + HAL_MutexUnlock(mutex_mem_stats); + return NULL; + } + memset(pos, 0, sizeof(OS_malloc_record)); + + pos->buf = ptr; + pos->buflen = size; + pos->func = (char *)f; + pos->line = (int)l; +#if defined(__UBUNTU_SDK_DEMO__) + if (tracking_malloc_callstack) { + record_backtrace(&pos->bt_level, &pos->bt_symbols); + } +#endif + + list_add_tail(&pos->list, &mem_recs); + + { + 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("utils", "large allocating @ %s(%d) for %04d bytes!", f, l, size); + LITE_printf("\r\n"); +#if defined(__UBUNTU_SDK_DEMO__) + for (k = 0; k < pos->bt_level; ++k) { + int m; + const char *p = strchr(pos->bt_symbols[k], '('); + + if (p[1] == ')') { + continue; + } + for (m = 0; m < k; ++m) { + LITE_printf(" "); + } + + LITE_printf("%s\r\n", p); + } +#endif + LITE_printf("\r\n"); + } +#endif + memset(ptr, 0, size); + HAL_MutexUnlock(mutex_mem_stats); + return ptr; +} + +void LITE_free_internal(void *ptr) +{ + 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_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("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; + _count_free_internal(ptr, pos); + + if (pos->buf && pos->buflen > 0) { + memset(pos->buf, 0xEE, pos->buflen); + } + pos->buf = 0; + pos->buflen = 0; + pos->func = ""; + pos->line = 0; +#if defined(__UBUNTU_SDK_DEMO__) + pos->bt_level = 0; + HAL_Free(pos->bt_symbols); + pos->bt_symbols = 0; +#endif + + list_del(&pos->list); + HAL_Free(pos); + } + HAL_MutexUnlock(mutex_mem_stats); + HAL_Free(ptr); +} + +void *LITE_malloc_routine(int size, ...) +{ + int magic = 0; + char *module_name = NULL; + + 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); + + return LITE_malloc(size, magic, module_name); +} + +void *LITE_calloc_routine(size_t n, size_t s, ...) +{ + int magic = 0; + char *module_name = NULL; + + va_list ap; + va_start(ap, s); + magic = va_arg(ap, int); + if (MEM_MAGIC == magic) { + module_name = va_arg(ap, char *); + } + va_end(ap); + + return LITE_malloc(n * s, magic, module_name);; +} + +void LITE_free_routine(void *ptr) +{ + LITE_free(ptr); +} + +void LITE_dump_malloc_free_stats(int level) +{ + OS_malloc_record *pos; + module_mem_t *module_pos, *tmp; + module_mem_t *unknown_mod = NULL; + + if (level > LITE_get_loglevel()) { + return; + } + + 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("| %-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); + } + } + } + + if (unknown_mod) { + calling_stack_t *call_pos, *tmp; + LITE_printf("\r\n"); + LITE_printf("\x1B[1;33mMissing module-name references:\x1B[0m\r\n"); + LITE_printf("---------------------------------------------------\r\n"); + + 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"); + } + + 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_get_loglevel() == level) { + int j; + int cnt = 0; + + list_for_each_entry(pos, &mem_recs, list, OS_malloc_record) { + if (pos->buf) { + LITE_printf("%4d. %-24s Ln:%-5d @ %p: %4d bytes [", + ++cnt, + pos->func, + pos->line, + pos->buf, + pos->buflen); + for (j = 0; j < 32 && j < pos->buflen; ++j) { + char c; + + c = *(char *)(pos->buf + j); + if (c < ' ' || c > '~') { + c = '.'; + } + LITE_printf("%c", c); + } + LITE_printf("]\r\n"); + +#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); + } + } +#endif + LITE_printf("\r\n"); + } + } + } + + return; +} + +void **LITE_get_mem_mutex(void) +{ + return &mutex_mem_stats; +} +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_mem_stats.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_mem_stats.h new file mode 100644 index 00000000..60adc1e3 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_net.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_net.c new file mode 100644 index 00000000..85556f06 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_net.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_net.h new file mode 100644 index 00000000..be83c518 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_net.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _INFRA_NET_H_ +#define _INFRA_NET_H_ + +#include "infra_types.h" + +/** + * @brief The structure of network connection(TCP or SSL). + * The user has to allocate memory for this structure. + */ + +struct utils_network; +typedef struct utils_network utils_network_t, *utils_network_pt; + +struct utils_network { + const char *pHostAddress; + uint16_t port; + uint16_t ca_crt_len; + + /**< NULL, TCP connection; NOT NULL, SSL connection */ + const char *ca_crt; + /**< NOT NULL,iTLS connection*/ + char *product_key; + /**< connection handle: 0, NOT connection; NOT 0, handle of the connection */ + uintptr_t handle; + + /**< Read data from server function pointer. */ + int (*read)(utils_network_pt, char *, uint32_t, uint32_t); + + /**< Send data to server function pointer. */ + int (*write)(utils_network_pt, const char *, uint32_t, uint32_t); + + /**< Disconnect the network */ + int (*disconnect)(utils_network_pt); + + /**< Establish the network */ + int (*connect)(utils_network_pt); +}; + +int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms); +int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms); +int iotx_net_disconnect(utils_network_pt pNetwork); +int iotx_net_connect(utils_network_pt pNetwork); +int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt); + +#endif /* IOTX_COMMON_NET_H */ + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_preauth.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_preauth.c new file mode 100644 index 00000000..4ec3f817 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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_sign_mqtt_t *output) +{ + int res = FAIL_RETURN; + char *p = json_string; + char *p_start, *p_end, *pt; + uint8_t len; + int code = 0; + + while (p < (json_string + string_len)) { + while (*(++p) != ':') { + if (p >= (json_string + string_len)) { + if (code != 200) { + return FAIL_RETURN; + } + else { + return SUCCESS_RETURN; + } + } + } + + pt = p; + p_start = p_end = NULL; + while (--pt > json_string) { + if (*pt == '\"') { + if (p_end != NULL) { + p_start = pt + 1; + break; + } else { + p_end = pt; + } + } + } + + if (p_start == NULL || p_end == NULL) { + return FAIL_RETURN; + } + len = p_end - p_start; + + if (strlen("code") == len && !memcmp(p_start, "code", len)) { + infra_str2int(++p, &code); + if (code != 200) { + return FAIL_RETURN; + } + } else if (strlen("iotId") == len && !memcmp(p_start, "iotId", len)) { + res = _preauth_get_string_value(p, output->username, PREAUTH_IOT_ID_MAXLEN); + if (res < SUCCESS_RETURN) { + return res; + } + } else if (strlen("iotToken") == len && !memcmp(p_start, "iotToken", len)) { + res = _preauth_get_string_value(p, output->password, PREAUTH_IOT_TOKEN_MAXLEN); + if (res < SUCCESS_RETURN) { + return res; + } + } else if (strlen("host") == len && !memcmp(p_start, "host", len)) { + res = _preauth_get_string_value(p, output->hostname, PREAUTH_IOT_HOST_MAXLEN); + if (res < SUCCESS_RETURN) { + return res; + } + } else if (strlen("port") == len && !memcmp(p_start, "port", len)) { + int port_temp; + infra_str2int(++p, &port_temp); + output->port = port_temp; + } + } + + return SUCCESS_RETURN; +} + +int preauth_get_connection_info(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *dev_meta, + const char *sign, const char *device_id, iotx_sign_mqtt_t *preauth_output) +{ + char http_url[128] = "http://"; + char http_url_frag[] = "/auth/devicename"; +#ifdef SUPPORT_TLS + int http_port = 443; +#else + int http_port = 80; +#endif + int res = FAIL_RETURN; + httpclient_t httpc; + httpclient_data_t httpc_data; + char request_buff[PREAUTH_HTTP_REQ_LEN] = {0}; + char response_buff[PREAUTH_HTTP_RSP_LEN] = {0}; + + if (g_infra_http_domain[region] == NULL) { + return FAIL_RETURN; + } + + memset(&httpc, 0, sizeof(httpclient_t)); + memset(&httpc_data, 0, sizeof(httpclient_data_t)); + memcpy(http_url + strlen(http_url), g_infra_http_domain[region], strlen(g_infra_http_domain[region])); + memcpy(http_url + strlen(http_url), http_url_frag, sizeof(http_url_frag)); + + httpc.header = "Accept: text/xml,text/javascript,text/html,application/json\r\n"; + + _preauth_assemble_auth_req_string(dev_meta, sign, device_id, request_buff, sizeof(request_buff)); + + httpc_data.post_content_type = "application/x-www-form-urlencoded;charset=utf-8"; + httpc_data.post_buf = request_buff; + httpc_data.post_buf_len = strlen(request_buff); + httpc_data.response_buf = response_buff; + httpc_data.response_buf_len = sizeof(response_buff); + + res = httpclient_common(&httpc, + http_url, + http_port, +#ifdef SUPPORT_TLS + iotx_ca_crt, +#else + NULL, +#endif + HTTPCLIENT_POST, + CONFIG_GUIDER_AUTH_TIMEOUT, + &httpc_data); + if (res < SUCCESS_RETURN) { + return res; + } + +#ifdef INFRA_LOG_NETWORK_PAYLOAD + preauth_info("Downstream Payload:"); + iotx_facility_json_print(response_buff, LOG_INFO_LEVEL, '<'); +#endif + res = _preauth_parse_auth_rsp_string(response_buff, strlen(response_buff), preauth_output); + + return res; +} + +#endif /* #ifdef MQTT_PRE_AUTH */ diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_preauth.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_preauth.h new file mode 100644 index 00000000..55c3fe13 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_preauth.h @@ -0,0 +1,25 @@ +/* + * 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 + +int preauth_get_connection_info(iotx_mqtt_region_types_t region, iotx_dev_meta_info_t *dev_meta, + const char *sign, const char *device_id, iotx_sign_mqtt_t *preauth_output); + +#endif /* #ifndef __INFRA_PREAUTH__ */ \ No newline at end of file diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_prt_nwk_payload.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_prt_nwk_payload.c new file mode 100644 index 00000000..97c0bf9b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_report.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_report.c new file mode 100644 index 00000000..a989ae90 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_report.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_report.h new file mode 100644 index 00000000..8947fea5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha1.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha1.c new file mode 100644 index 00000000..eecb1a8b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha1.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha1.h new file mode 100644 index 00000000..c3fd35d2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha1.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + + + + +#ifndef _INFRA_SHA1_H_ +#define _INFRA_SHA1_H_ + +#include "infra_types.h" + +#define SHA1_DIGEST_SIZE (20) + +/** + * \brief SHA-1 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} iot_sha1_context; + +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +void utils_sha1_init(iot_sha1_context *ctx); + +/** + * \brief Clear SHA-1 context + * + * \param ctx SHA-1 context to be cleared + */ +void utils_sha1_free(iot_sha1_context *ctx); + +/** + * \brief Clone (the state of) a SHA-1 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void utils_sha1_clone(iot_sha1_context *dst, + const iot_sha1_context *src); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void utils_sha1_starts(iot_sha1_context *ctx); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void utils_sha1_update(iot_sha1_context *ctx, const unsigned char *input, uint32_t ilen); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void utils_sha1_finish(iot_sha1_context *ctx, unsigned char output[20]); + +/* Internal use */ +void utils_sha1_process(iot_sha1_context *ctx, const unsigned char data[64]); + +/** + * \brief Output = SHA-1( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void utils_sha1(const unsigned char *input, uint32_t ilen, unsigned char output[20]); + +void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len); +void utils_hmac_sha1_hex(const char *msg, int msg_len, char *digest, const char *key, int key_len); + +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha256.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha256.c new file mode 100644 index 00000000..f8cd83a5 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha256.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha256.h new file mode 100644 index 00000000..7fc337d1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_sha256.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOTX_COMMON_SHA256_H_ +#define _IOTX_COMMON_SHA256_H_ + +#include + +#define SHA256_DIGEST_LENGTH (32) +#define SHA256_BLOCK_LENGTH (64) +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) + +/** + * \brief SHA-256 context structure + */ +typedef struct { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[8]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ + int is224; /*!< 0 => SHA-256, else SHA-224 */ +} iot_sha256_context; + +typedef union { + char sptr[8]; + uint64_t lint; +} u_retLen; + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void utils_sha256_init(iot_sha256_context *ctx); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void utils_sha256_free(iot_sha256_context *ctx); + + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + */ +void utils_sha256_starts(iot_sha256_context *ctx); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void utils_sha256_update(iot_sha256_context *ctx, const unsigned char *input, uint32_t ilen); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-256 checksum result + */ +void utils_sha256_finish(iot_sha256_context *ctx, uint8_t output[32]); + +/* Internal use */ +void utils_sha256_process(iot_sha256_context *ctx, const unsigned char data[64]); + +/** + * \brief Output = SHA-256( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-256 checksum result + */ +void utils_sha256(const uint8_t *input, uint32_t ilen, uint8_t output[32]); + +void utils_hmac_sha256(const uint8_t *msg, uint32_t msg_len, const uint8_t *key, uint32_t key_len, uint8_t output[32]); + +#endif + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_string.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_string.c new file mode 100644 index 00000000..2b65d561 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_string.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_string.h new file mode 100644 index 00000000..5026b2de --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_timer.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_timer.c new file mode 100644 index 00000000..f1996cf6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_timer.c @@ -0,0 +1,95 @@ +#include "infra_config.h" + +#ifdef INFRA_TIMER +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ +#include "infra_types.h" +#include "infra_timer.h" + +uint64_t HAL_UptimeMs(void); + +void iotx_time_start(iotx_time_t *timer) +{ + if (!timer) { + return; + } + + timer->time = HAL_UptimeMs(); +} + +uint32_t utils_time_spend(iotx_time_t *start) +{ + uint32_t now, res; + + if (!start) { + return 0; + } + + now = HAL_UptimeMs(); + res = now - start->time; + return res; +} + +uint32_t iotx_time_left(iotx_time_t *end) +{ + uint32_t now, res; + + if (!end) { + return 0; + } + + if (utils_time_is_expired(end)) { + return 0; + } + + now = HAL_UptimeMs(); + res = end->time - now; + return res; +} + +uint32_t utils_time_is_expired(iotx_time_t *timer) +{ + uint32_t cur_time; + + if (!timer) { + return 1; + } + + cur_time = HAL_UptimeMs(); + /* + * WARNING: Do NOT change the following code until you know exactly what it do! + * + * check whether it reach destination time or not. + */ + if ((cur_time - timer->time) < (UINT32_MAX / 2)) { + return 1; + } else { + return 0; + } +} + +void iotx_time_init(iotx_time_t *timer) +{ + if (!timer) { + return; + } + + timer->time = 0; +} + +void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond) +{ + if (!timer) { + return; + } + + timer->time = HAL_UptimeMs() + millisecond; +} + +uint32_t utils_time_get_ms(void) +{ + return HAL_UptimeMs(); +} +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_timer.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_timer.h new file mode 100644 index 00000000..e018aab2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_types.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/infra_types.h new file mode 100644 index 00000000..7037296e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/iot.mk new file mode 100644 index 00000000..41e4cca0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/infra/iot.mk @@ -0,0 +1 @@ +LIBA_TARGET := libiot_infra.a diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/examples/mqtt_example.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/examples/mqtt_example.c new file mode 100644 index 00000000..2aa24ba8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/examples/mqtt_example_at.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/examples/mqtt_example_at.c new file mode 100644 index 00000000..3e2085b1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTConnect.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTConnect.h new file mode 100644 index 00000000..20ec833d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTConnectClient.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTConnectClient.c new file mode 100644 index 00000000..71cb8ac9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTDeserializePublish.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTDeserializePublish.c new file mode 100644 index 00000000..9713db3f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTPacket.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTPacket.c new file mode 100644 index 00000000..931a9305 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTPacket.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTPacket.h new file mode 100644 index 00000000..e93dfc50 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTPublish.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTPublish.h new file mode 100644 index 00000000..4cb4e6a6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTSerializePublish.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTSerializePublish.c new file mode 100644 index 00000000..4c068b70 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTSubscribe.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTSubscribe.h new file mode 100644 index 00000000..ecd04d6a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTSubscribeClient.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTSubscribeClient.c new file mode 100644 index 00000000..4a26ca29 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTUnsubscribe.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTUnsubscribe.h new file mode 100644 index 00000000..ab449115 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTUnsubscribeClient.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/MQTTUnsubscribeClient.c new file mode 100644 index 00000000..2463a4d8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_client.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_client.c new file mode 100644 index 00000000..c6eef705 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_client.c @@ -0,0 +1,3181 @@ +/* + * 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 = (userKeepAliveInterval * 2); + if(pClient->connect_data.keepAliveInterval > CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX) { + 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; + iotx_time_t timer; + MQTTString topic = MQTTString_initializer; + /*iotx_mc_topic_handle_t handler = {topicFilter, {messageHandler, pcontext}};*/ + iotx_mc_topic_handle_t *handler = NULL; +#ifndef PLATFORM_HAS_DYNMEM + int idx = 0; +#endif + + if (!c || !topicFilter || !messageHandler) { + return FAIL_RETURN; + } +#if !( WITH_MQTT_DYN_BUF) + if (!c->buf_send) { + return FAIL_RETURN; + } +#endif + + topic.cstring = (char *)topicFilter; + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, c->request_timeout_ms); + +#ifdef PLATFORM_HAS_DYNMEM + handler = mqtt_malloc(sizeof(iotx_mc_topic_handle_t)); + if (NULL == handler) { + return FAIL_RETURN; + } + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); + INIT_LIST_HEAD(&handler->linked_list); +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + if (c->list_sub_handle[idx].used == 0) { + handler = &c->list_sub_handle[idx]; + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); + c->list_sub_handle[idx].used = 1; + break; + } + } + + if (handler == NULL) { + return MQTT_SUBHANDLE_LIST_LEN_TOO_SHORT; + } +#endif + +#if !(WITH_MQTT_ZIP_TOPIC) +#ifdef PLATFORM_HAS_DYNMEM + handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1); + if (NULL == handler->topic_filter) { + mqtt_free(handler); + return FAIL_RETURN; + } + memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1); +#else + if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) { + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); + return MQTT_TOPIC_LEN_TOO_SHORT; + } + + memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN); +#endif + memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1); +#else + if (strstr(topicFilter, "/+") != NULL || strstr(topicFilter, "/#") != NULL) { +#ifdef PLATFORM_HAS_DYNMEM + handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1); + if (NULL == handler->topic_filter) { + mqtt_free(handler); + return FAIL_RETURN; + } + memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1); +#else + if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) { + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); + return MQTT_TOPIC_LEN_TOO_SHORT; + } + memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN); +#endif + handler->topic_type = TOPIC_FILTER_TYPE; + memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1); + } else { +#ifdef PLATFORM_HAS_DYNMEM + handler->topic_filter = mqtt_malloc(MQTT_ZIP_PATH_DEFAULT_LEN); + if (NULL == handler->topic_filter) { + mqtt_free(handler); + return FAIL_RETURN; + } + memset((char *)handler->topic_filter, 0, MQTT_ZIP_PATH_DEFAULT_LEN); +#else + if (MQTT_ZIP_PATH_DEFAULT_LEN >= CONFIG_MQTT_TOPIC_MAXLEN) { + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); + return MQTT_TOPIC_LEN_TOO_SHORT; + } + memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN); +#endif + handler->topic_type = TOPIC_NAME_TYPE; + if (iotx_mc_get_zip_topic(topicFilter, strlen(topicFilter), (char *)handler->topic_filter, + MQTT_ZIP_PATH_DEFAULT_LEN) != 0) { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); +#endif + return FAIL_RETURN; + } + } +#endif + handler->handle.h_fp = messageHandler; + handler->handle.pcontext = pcontext; + +#ifdef SUB_PERSISTENCE_ENABLED + if (qos == IOTX_MQTT_QOS3_SUB_LOCAL) { + uint8_t dup = 0; +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *node; +#endif + HAL_MutexLock(c->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM +#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG) +#if WITH_MQTT_ZIP_TOPIC + HEXDUMP_DEBUG(handler->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN); +#else + mqtt_warning("handler->topic: %s", handler->topic_filter); +#endif +#endif + list_for_each_entry(node, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) { + /* If subscribe the same topic and callback function, then ignore */ +#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG) +#if WITH_MQTT_ZIP_TOPIC + HEXDUMP_DEBUG(node->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN); +#else + mqtt_warning("node->topic: %s", node->topic_filter); +#endif +#endif + if (0 == iotx_mc_check_handle_is_identical(node, handler)) { + mqtt_warning("dup sub,topic = %s", topicFilter); + dup = 1; + } + } +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + /* If subscribe the same topic and callback function, then ignore */ + if (&c->list_sub_handle[idx] != handler && + 0 == iotx_mc_check_handle_is_identical(&c->list_sub_handle[idx], handler)) { + mqtt_warning("dup sub,topic = %s", topicFilter); + dup = 1; + } + } +#endif + if (dup == 0) { +#ifdef PLATFORM_HAS_DYNMEM + list_add_tail(&handler->linked_list, &c->list_sub_handle); +#endif + } else { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); +#endif + } + HAL_MutexUnlock(c->lock_generic); + return SUCCESS_RETURN; + } +#endif + + HAL_MutexLock(c->lock_write_buf); + + if (_alloc_send_buffer(c, strlen(topicFilter)) < 0) { + HAL_MutexUnlock(c->lock_write_buf); +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); +#endif + return FAIL_RETURN; + } + + len = MQTTSerialize_subscribe((unsigned char *)c->buf_send, c->buf_size_send, 0, (unsigned short)msgId, 1, &topic, + (int *)&qos); + if (len <= 0) { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); +#endif + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + return MQTT_SUBSCRIBE_PACKET_ERROR; + } + + mqtt_debug("%20s : %08d", "Packet Ident", msgId); + mqtt_debug("%20s : %s", "Topic", topicFilter); + mqtt_debug("%20s : %d", "QoS", (int)qos); + mqtt_debug("%20s : %d", "Packet Length", len); +#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG) + HEXDUMP_DEBUG(c->buf_send, len); +#endif + + if ((iotx_mc_send_packet(c, c->buf_send, len, &timer)) != SUCCESS_RETURN) { /* send the subscribe packet */ + /* If send failed, remove it */ + mqtt_err("run sendPacket error!"); +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); +#endif + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + return MQTT_NETWORK_ERROR; + } + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + + { + uint8_t dup = 0; +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *node; +#endif + HAL_MutexLock(c->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM +#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG) +#if WITH_MQTT_ZIP_TOPIC + HEXDUMP_DEBUG(handler->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN); +#else + mqtt_warning("handler->topic: %s", handler->topic_filter); +#endif +#endif + list_for_each_entry(node, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) { + /* If subscribe the same topic and callback function, then ignore */ +#if defined(INSPECT_MQTT_FLOW) && defined (INFRA_LOG) +#if WITH_MQTT_ZIP_TOPIC + HEXDUMP_DEBUG(node->topic_filter, MQTT_ZIP_PATH_DEFAULT_LEN); +#else + mqtt_warning("node->topic: %s", node->topic_filter); +#endif +#endif + if (0 == iotx_mc_check_handle_is_identical(node, handler)) { + mqtt_warning("dup sub,topic = %s", topicFilter); + dup = 1; + } + } +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + /* If subscribe the same topic and callback function, then ignore */ + if (&c->list_sub_handle[idx] != handler && + 0 == iotx_mc_check_handle_is_identical(&c->list_sub_handle[idx], handler)) { + mqtt_warning("dup sub,topic = %s", topicFilter); + dup = 1; + } + } +#endif + if (dup == 0) { +#ifdef PLATFORM_HAS_DYNMEM + list_add_tail(&handler->linked_list, &c->list_sub_handle); +#endif + } else { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); +#endif + } + HAL_MutexUnlock(c->lock_generic); + } + + return SUCCESS_RETURN; +} + +static int iotx_mc_get_next_packetid(iotx_mc_client_t *c) +{ + unsigned int id = 0; + + if (!c) { + return FAIL_RETURN; + } + + HAL_MutexLock(c->lock_generic); + c->packet_id = (c->packet_id == IOTX_MC_PACKET_ID_MAX) ? 1 : c->packet_id + 1; + id = c->packet_id; + HAL_MutexUnlock(c->lock_generic); + + return id; +} + +static int iotx_mc_check_rule(char *iterm, iotx_mc_topic_type_t type) +{ + int i = 0; + int len = 0; + + if (NULL == iterm) { + mqtt_err("iterm is NULL"); + return FAIL_RETURN; + } + + len = strlen(iterm); + + for (i = 0; i < len; i++) { + if (TOPIC_FILTER_TYPE == type) { + if ('+' == iterm[i] || '#' == iterm[i]) { + if (1 != len) { + mqtt_err("the character # and + is error"); + return FAIL_RETURN; + } + } + } else { + if ('+' == iterm[i] || '#' == iterm[i]) { + mqtt_err("has character # and + is error"); + return FAIL_RETURN; + } + } + + if (iterm[i] < 32 || iterm[i] >= 127) { + return FAIL_RETURN; + } + } + return SUCCESS_RETURN; +} + +static int iotx_mc_check_topic(const char *topicName, iotx_mc_topic_type_t type) +{ + int mask = 0; + char *delim = "/"; + char *iterm = NULL; + char topicString[CONFIG_MQTT_TOPIC_MAXLEN]; + if (NULL == topicName || '/' != topicName[0]) { + return FAIL_RETURN; + } + + if (strlen(topicName) > CONFIG_MQTT_TOPIC_MAXLEN) { + mqtt_err("len of topicName exceeds %d", CONFIG_MQTT_TOPIC_MAXLEN); + return FAIL_RETURN; + } + + memset(topicString, 0x0, CONFIG_MQTT_TOPIC_MAXLEN); + strncpy(topicString, topicName, CONFIG_MQTT_TOPIC_MAXLEN - 1); + + iterm = infra_strtok(topicString, delim); + + if (SUCCESS_RETURN != iotx_mc_check_rule(iterm, type)) { + mqtt_err("run iotx_check_rule error"); + return FAIL_RETURN; + } + + for (;;) { + iterm = infra_strtok(NULL, delim); + + if (iterm == NULL) { + break; + } + + /* The character '#' is not in the last */ + if (1 == mask) { + mqtt_err("the character # is error"); + return FAIL_RETURN; + } + + if (SUCCESS_RETURN != iotx_mc_check_rule(iterm, type)) { + mqtt_err("run iotx_check_rule error"); + return FAIL_RETURN; + } + + if (iterm[0] == '#') { + mask = 1; + } + } + + return SUCCESS_RETURN; +} + +static inline int _is_in_yield_cb() +{ + return _in_yield_cb; +} + +static int MQTTUnsubscribe(iotx_mc_client_t *c, const char *topicFilter, unsigned int msgId) +{ + MQTTString cur_topic; + iotx_time_t timer; + MQTTString topic = MQTTString_initializer; + int len = 0; + /*iotx_mc_topic_handle_t handler = {topicFilter, {NULL, NULL}};*/ + iotx_mc_topic_handle_t *handler = NULL; +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *node = NULL; + iotx_mc_topic_handle_t *next = NULL; +#else + int idx = 0; + iotx_mc_topic_handle_t s_handler; +#endif + if (!c || !topicFilter) { + return FAIL_RETURN; + } + + topic.cstring = (char *)topicFilter; + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, c->request_timeout_ms); + +#ifdef PLATFORM_HAS_DYNMEM + handler = mqtt_malloc(sizeof(iotx_mc_topic_handle_t)); + if (NULL == handler) { + return FAIL_RETURN; + } +#else + handler = &s_handler; +#endif + + memset(handler, 0, sizeof(iotx_mc_topic_handle_t)); + +#if !(WITH_MQTT_ZIP_TOPIC) +#ifdef PLATFORM_HAS_DYNMEM + handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1); + if (NULL == handler->topic_filter) { + mqtt_free(handler); + return FAIL_RETURN; + } + memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1); +#else + if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) { + return MQTT_TOPIC_LEN_TOO_SHORT; + } + memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN); +#endif + memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1); +#else + if (strstr(topicFilter, "/+") != NULL || strstr(topicFilter, "/#") != NULL) { +#ifdef PLATFORM_HAS_DYNMEM + handler->topic_filter = mqtt_malloc(strlen(topicFilter) + 1); + if (NULL == handler->topic_filter) { + mqtt_free(handler); + return FAIL_RETURN; + } + memset((char *)handler->topic_filter, 0, strlen(topicFilter) + 1); +#else + if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) { + return MQTT_TOPIC_LEN_TOO_SHORT; + } + memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN); +#endif + handler->topic_type = TOPIC_FILTER_TYPE; + memcpy((char *)handler->topic_filter, topicFilter, strlen(topicFilter) + 1); + } else { +#ifdef PLATFORM_HAS_DYNMEM + handler->topic_filter = mqtt_malloc(MQTT_ZIP_PATH_DEFAULT_LEN); + if (NULL == handler->topic_filter) { + mqtt_free(handler); + return FAIL_RETURN; + } + memset((char *)handler->topic_filter, 0, MQTT_ZIP_PATH_DEFAULT_LEN); +#else + if (MQTT_ZIP_PATH_DEFAULT_LEN >= CONFIG_MQTT_TOPIC_MAXLEN) { + return MQTT_TOPIC_LEN_TOO_SHORT; + } + memset((char *)handler->topic_filter, 0, CONFIG_MQTT_TOPIC_MAXLEN); +#endif + handler->topic_type = TOPIC_NAME_TYPE; + if (iotx_mc_get_zip_topic(topicFilter, strlen(topicFilter), (char *)handler->topic_filter, + MQTT_ZIP_PATH_DEFAULT_LEN) != 0) { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#endif + return FAIL_RETURN; + } + } +#endif + + HAL_MutexLock(c->lock_write_buf); + + if (_alloc_send_buffer(c, strlen(topicFilter)) < 0) { + HAL_MutexUnlock(c->lock_write_buf); +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#endif + return FAIL_RETURN; + } + + if ((len = MQTTSerialize_unsubscribe((unsigned char *)c->buf_send, c->buf_size_send, 0, (unsigned short)msgId, 1, + &topic)) <= 0) { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#endif + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + return MQTT_UNSUBSCRIBE_PACKET_ERROR; + } + + if ((iotx_mc_send_packet(c, c->buf_send, len, &timer)) != SUCCESS_RETURN) { /* send the subscribe packet */ +#ifdef PLATFORM_HAS_DYNMEM + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#endif + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + return MQTT_NETWORK_ERROR; + } + + cur_topic.cstring = NULL; + cur_topic.lenstring.data = (char *)handler->topic_filter; + +#if !(WITH_MQTT_ZIP_TOPIC) + cur_topic.lenstring.len = strlen(handler->topic_filter) + 1; +#else + if (handler->topic_type == TOPIC_FILTER_TYPE) { + cur_topic.lenstring.len = strlen(handler->topic_filter) + 1; + } else { + cur_topic.lenstring.len = MQTT_ZIP_PATH_DEFAULT_LEN; + } +#endif + /* we have to find the right message handler - indexed by topic */ + HAL_MutexLock(c->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM + list_for_each_entry_safe(node, next, &c->list_sub_handle, linked_list, iotx_mc_topic_handle_t) { + if (MQTTPacket_equals(&cur_topic, (char *)node->topic_filter) + || iotx_mc_is_topic_matched((char *)node->topic_filter, &cur_topic)) { + mqtt_debug("topic be matched"); + list_del(&node->linked_list); + mqtt_free(node->topic_filter); + mqtt_free(node); + } + } + mqtt_free(handler->topic_filter); + mqtt_free(handler); +#else + for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) { + if ((c->list_sub_handle[idx].used == 1) && + (MQTTPacket_equals(&cur_topic, (char *)c->list_sub_handle[idx].topic_filter) || + iotx_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, &cur_topic))) { + mqtt_debug("topic be matched"); + memset(&c->list_sub_handle[idx], 0, sizeof(iotx_mc_topic_handle_t)); + } + } +#endif + HAL_MutexUnlock(c->lock_generic); + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + return SUCCESS_RETURN; +} + +int MQTTPublish(iotx_mc_client_t *c, const char *topicName, iotx_mqtt_topic_info_pt topic_msg) + +{ + iotx_time_t timer; + MQTTString topic = MQTTString_initializer; + int len = 0; +#if !WITH_MQTT_ONLY_QOS0 + iotx_mc_pub_info_t *node = NULL; +#endif +#ifdef INFRA_LOG_NETWORK_PAYLOAD + const char *json_payload = NULL; +#endif + + if (!c || !topicName || !topic_msg) { + return FAIL_RETURN; + } + + topic.cstring = (char *)topicName; + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, c->request_timeout_ms); + + HAL_MutexLock(c->lock_list_pub); + HAL_MutexLock(c->lock_write_buf); + + if (_alloc_send_buffer(c, strlen(topicName) + topic_msg->payload_len) < 0) { + HAL_MutexUnlock(c->lock_write_buf); + HAL_MutexUnlock(c->lock_list_pub); + return FAIL_RETURN; + } + + len = MQTTSerialize_publish((unsigned char *)c->buf_send, + c->buf_size_send, + 0, + topic_msg->qos, + topic_msg->retain, + topic_msg->packet_id, + topic, + (unsigned char *)topic_msg->payload, + topic_msg->payload_len); + if (len <= 0) { + mqtt_err("MQTTSerialize_publish is error, len=%d, buf_size_send=%u, payloadlen=%u", + len, + c->buf_size_send, + topic_msg->payload_len); + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + HAL_MutexUnlock(c->lock_list_pub); + return MQTT_PUBLISH_PACKET_ERROR; + } + +#if !WITH_MQTT_ONLY_QOS0 + node = NULL; + /* If the QOS >1, push the information into list of wait publish ACK */ + if (topic_msg->qos > IOTX_MQTT_QOS0) { + /* push into list */ + if (SUCCESS_RETURN != iotx_mc_push_pubInfo_to(c, len, topic_msg->packet_id, &node)) { + mqtt_err("push publish into to pubInfolist failed!"); + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + HAL_MutexUnlock(c->lock_list_pub); + return MQTT_PUSH_TO_LIST_ERROR; + } + } +#endif + /* send the publish packet */ + if (iotx_mc_send_packet(c, c->buf_send, len, &timer) != SUCCESS_RETURN) { +#if !WITH_MQTT_ONLY_QOS0 + if (topic_msg->qos > IOTX_MQTT_QOS0) { + /* If not even successfully sent to IP stack, meaningless to wait QOS1 ack, give up waiting */ +#ifdef PLATFORM_HAS_DYNMEM + list_del(&node->linked_list); + mqtt_free(node); +#else + memset(node, 0, sizeof(iotx_mc_pub_info_t)); +#endif + } +#endif + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + HAL_MutexUnlock(c->lock_list_pub); + return MQTT_NETWORK_ERROR; + } + +#ifdef INFRA_LOG_NETWORK_PAYLOAD + json_payload = (const char *)topic_msg->payload; + + mqtt_info("Upstream Topic: '%s'", topicName); + mqtt_info("Upstream Payload:"); + iotx_facility_json_print(json_payload, LOG_INFO_LEVEL, '>'); + +#endif /* #ifdef INFRA_LOG */ + + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + HAL_MutexUnlock(c->lock_list_pub); + + return SUCCESS_RETURN; +} + +static int MQTTDisconnect(iotx_mc_client_t *c) +{ + int rc = FAIL_RETURN; + int len = 0; + iotx_time_t timer; /* we might wait for incomplete incoming publishes to complete */ + + if (!c) { + return FAIL_RETURN; + } + + HAL_MutexLock(c->lock_write_buf); + + if (_alloc_send_buffer(c, 0) < 0) { + HAL_MutexUnlock(c->lock_write_buf); + return FAIL_RETURN; + } + + len = MQTTSerialize_disconnect((unsigned char *)c->buf_send, c->buf_size_send); + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, c->request_timeout_ms); + + if (len > 0) { + rc = iotx_mc_send_packet(c, c->buf_send, len, &timer); /* send the disconnect packet */ + } + _reset_send_buffer(c); + HAL_MutexUnlock(c->lock_write_buf); + return rc; +} + +static int iotx_mc_disconnect(iotx_mc_client_t *pClient) +{ + int rc = -1; + + if (NULL == pClient) { + return NULL_VALUE_ERROR; + } + + if (wrapper_mqtt_check_state(pClient)) { + rc = MQTTDisconnect(pClient); + mqtt_debug("rc = MQTTDisconnect() = %d", rc); + rc = rc; + } + + /* close tcp/ip socket or free tls resources */ + pClient->ipstack.disconnect(&pClient->ipstack); + + iotx_mc_set_client_state(pClient, IOTX_MC_STATE_INITIALIZED); + + mqtt_info("mqtt disconnect!"); + return SUCCESS_RETURN; +} + +/************************ Public Interface ************************/ +void *wrapper_mqtt_init(iotx_mqtt_param_t *mqtt_params) +{ + int err; + iotx_mc_client_t *pclient = NULL; +#ifndef PLATFORM_HAS_DYNMEM + int idx; +#endif + +#ifdef PLATFORM_HAS_DYNMEM + pclient = (iotx_mc_client_t *)mqtt_malloc(sizeof(iotx_mc_client_t)); + if (NULL == pclient) { + mqtt_err("not enough memory."); + return NULL; + } + memset(pclient, 0, sizeof(iotx_mc_client_t)); +#else + for (idx = 0; idx < IOTX_MC_CLIENT_MAX_COUNT; idx++) { + if (g_iotx_mc_client[idx].used == 0) { + g_iotx_mc_client[idx].used = 1; + pclient = &g_iotx_mc_client[idx]; + break; + } + } + + if (NULL == pclient) { + mqtt_err("IOTX_MC_CLIENT_MAX_COUNT too short: %d", IOTX_MC_CLIENT_MAX_COUNT); + return NULL; + } +#endif + + err = iotx_mc_init(pclient, mqtt_params); + + if (SUCCESS_RETURN != err) { + mqtt_err("iotx_mc_init failed"); + iotx_mc_release(pclient); + return NULL; + } + + return pclient; +} + +int wrapper_mqtt_connect(void *client) +{ + int rc = FAIL_RETURN; + int retry_max = 3; + int retry_cnt = 1; + int retry_interval = 1000; + iotx_mc_client_t *pClient = (iotx_mc_client_t *)client; + + if (NULL == pClient) { + return NULL_VALUE_ERROR; + } + + /* Establish TCP or TLS connection */ + do { + mqtt_debug("calling TCP or TLS connect HAL for [%d/%d] iteration", retry_cnt, retry_max); + + rc = pClient->ipstack.connect(&pClient->ipstack); + if (SUCCESS_RETURN != rc) { + pClient->ipstack.disconnect(&pClient->ipstack); + mqtt_err("TCP or TLS Connection failed"); + + if (ERROR_CERTIFICATE_EXPIRED == rc) { + mqtt_err("certificate is expired! rc = %d", rc); + rc = ERROR_CERT_VERIFY_FAIL; + HAL_SleepMs(retry_interval); + continue; + } else { + rc = MQTT_NETWORK_CONNECT_ERROR; + HAL_SleepMs(retry_interval); + continue; + } + } else { + mqtt_debug("rc = pClient->ipstack.connect() = %d, success @ [%d/%d] iteration", rc, retry_cnt, retry_max); + break; + } + } while (++retry_cnt <= retry_max); + +#ifdef ASYNC_PROTOCOL_STACK + iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECT_BLOCK); + rc = MQTT_CONNECT_BLOCK; +#else + rc = _mqtt_connect(pClient); +#endif + return rc; +} + +int wrapper_mqtt_release(void **c) +{ + iotx_mc_client_t *pClient; +#ifdef PLATFORM_HAS_DYNMEM + iotx_mc_topic_handle_t *node = NULL, *next = NULL; +#endif + if (NULL == c) { + return NULL_VALUE_ERROR; + } + + pClient = (iotx_mc_client_t *)*c; + if (NULL == pClient) { + return NULL_VALUE_ERROR; + } + /* iotx_delete_thread(pClient); */ + HAL_SleepMs(100); + + iotx_mc_disconnect(pClient); + iotx_mc_set_client_state(pClient, IOTX_MC_STATE_INVALID); + HAL_SleepMs(100); + +#ifdef PLATFORM_HAS_DYNMEM + list_for_each_entry_safe(node, next, &pClient->list_sub_handle, linked_list, iotx_mc_topic_handle_t) { + list_del(&node->linked_list); + mqtt_free(node->topic_filter); + mqtt_free(node); + } +#else + memset(pClient->list_sub_handle, 0, sizeof(iotx_mc_topic_handle_t) * IOTX_MC_SUBHANDLE_LIST_MAX_LEN); +#endif + HAL_MutexDestroy(pClient->lock_generic); + HAL_MutexDestroy(pClient->lock_list_pub); + HAL_MutexDestroy(pClient->lock_write_buf); + HAL_MutexDestroy(pClient->lock_yield); + HAL_MutexDestroy(pClient->lock_read_buf); + +#if !WITH_MQTT_ONLY_QOS0 + iotx_mc_pub_wait_list_deinit(pClient); +#endif +#ifdef PLATFORM_HAS_DYNMEM + if (pClient->buf_send != NULL) { + mqtt_free(pClient->buf_send); + pClient->buf_send = NULL; + } + if (pClient->buf_read != NULL) { + mqtt_free(pClient->buf_read); + pClient->buf_read = NULL; + } + mqtt_free(pClient); +#else + memset(pClient, 0, sizeof(iotx_mc_client_t)); +#endif + *c = NULL; + mqtt_info("mqtt release!"); + return SUCCESS_RETURN; +} + +int wrapper_mqtt_yield(void *client, int timeout_ms) +{ + iotx_mc_client_t *pClient = (iotx_mc_client_t *)client; + + if (pClient == NULL) { + return NULL_VALUE_ERROR; + } + + if (timeout_ms < 0) { + mqtt_err("Invalid argument, timeout_ms = %d", timeout_ms); + return -1; + } + if (timeout_ms == 0) { + timeout_ms = 10; + } + + HAL_MutexLock(pClient->lock_yield); + pClient->cycle_timeout_ms = timeout_ms; + /* Keep MQTT alive or reconnect if connection abort */ + iotx_mc_keepalive(pClient); + HAL_MutexUnlock(pClient->lock_yield); + +#ifndef ASYNC_PROTOCOL_STACK + _mqtt_cycle(client); +#else + if (pClient->client_state == IOTX_MC_STATE_CONNECTED) { +#if !WITH_MQTT_ONLY_QOS0 + /* check list of wait publish ACK to remove node that is ACKED or timeout */ + MQTTPubInfoProc(pClient); +#endif + } + HAL_SleepMs(timeout_ms); +#endif + + return 0; +} + + +/* check MQTT client is in normal state */ +/* 0, in abnormal state; 1, in normal state */ +int wrapper_mqtt_check_state(void *client) +{ + if (!client) { + return 0; + } + + if (iotx_mc_get_client_state((iotx_mc_client_t *)client) == IOTX_MC_STATE_CONNECTED) { + return 1; + } + + return 0; +} + +int wrapper_mqtt_subscribe(void *client, + const char *topicFilter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext) +{ + int rc = FAIL_RETURN; + unsigned int msgId; + iotx_mc_client_t *c; + + if (NULL == client || NULL == topicFilter || strlen(topicFilter) == 0 || !topic_handle_func) { + mqtt_err(" paras error"); + return NULL_VALUE_ERROR; + } + + c = (iotx_mc_client_t *)client; + + msgId = iotx_mc_get_next_packetid(c); + + if (!wrapper_mqtt_check_state(c)) { + mqtt_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c)); + return MQTT_STATE_ERROR; + } + + if (0 != iotx_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) { + mqtt_err("topic format is error,topicFilter = %s", topicFilter); + return MQTT_TOPIC_FORMAT_ERROR; + } + + mqtt_debug("PERFORM subscribe to '%s' (msgId=%d)", topicFilter, msgId); + rc = MQTTSubscribe(c, topicFilter, qos, msgId, topic_handle_func, pcontext); + if (rc != SUCCESS_RETURN) { + if (rc == MQTT_NETWORK_ERROR) { + iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); + } + + mqtt_err("run MQTTSubscribe error, rc = %d", rc); + return rc; + } + + mqtt_info("mqtt subscribe packet sent,topic = %s!", topicFilter); + return msgId; +} + +int wrapper_mqtt_subscribe_sync(void *c, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms) +{ + int subed; + int ret; + iotx_time_t timer; + iotx_mc_client_t *client = (iotx_mc_client_t *)c; + int cnt = 0; + mqtt_sub_sync_node_t *node = NULL; +#ifdef PLATFORM_HAS_DYNMEM + mqtt_sub_sync_node_t *next = NULL; +#else + int idx = 0; +#endif + if (client == NULL) { + return NULL_VALUE_ERROR; + } + +#ifdef SUB_PERSISTENCE_ENABLED + if (qos > IOTX_MQTT_QOS3_SUB_LOCAL) { + mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d", + qos, + IOTX_MQTT_QOS0, IOTX_MQTT_QOS3_SUB_LOCAL, IOTX_MQTT_QOS0); + qos = IOTX_MQTT_QOS0; + } +#else + if (qos > IOTX_MQTT_QOS2) { + mqtt_warning("Invalid qos(%d) out of [%d, %d], using %d", + qos, + IOTX_MQTT_QOS0, IOTX_MQTT_QOS2, IOTX_MQTT_QOS0); + qos = IOTX_MQTT_QOS0; + } +#endif + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, timeout_ms); + + ret = -1; + subed = 0; + cnt = 0; + cnt = cnt; + do { +#ifdef PLATFORM_HAS_DYNMEM + mqtt_sub_sync_node_t *node = NULL; + mqtt_sub_sync_node_t *next = NULL; +#else + int idx = 0; +#endif + if (ret < 0) { + ret = wrapper_mqtt_subscribe(client, topic_filter, qos, topic_handle_func, pcontext); + if (_is_in_yield_cb() != 0 || qos == IOTX_MQTT_QOS3_SUB_LOCAL) { + return ret; + } + } + + if (!subed && ret >= 0) { + mqtt_sub_sync_node_t *node = NULL; +#ifndef PLATFORM_HAS_DYNMEM + int idx = 0; +#endif +#ifdef PLATFORM_HAS_DYNMEM + node = (mqtt_sub_sync_node_t *)mqtt_malloc(sizeof(mqtt_sub_sync_node_t)); +#else + for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) { + if (client->list_sub_sync_ack[idx].used == 0) { + memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t)); + client->list_sub_sync_ack[idx].used = 1; + node = &client->list_sub_sync_ack[idx]; + break; + } + } +#endif + if (node != NULL) { + mqtt_debug("packet_id = %d", ret); + node->packet_id = ret; + node->ack_type = IOTX_MQTT_EVENT_UNDEF; +#ifdef PLATFORM_HAS_DYNMEM + HAL_MutexLock(client->lock_generic); + list_add_tail(&node->linked_list, &client->list_sub_sync_ack); + HAL_MutexUnlock(client->lock_generic); +#endif + subed = 1; + } + + } + wrapper_mqtt_yield(client, 100); + + HAL_MutexLock(client->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM + list_for_each_entry_safe(node, next, &client->list_sub_sync_ack, linked_list, mqtt_sub_sync_node_t) { + if (node->packet_id == ret) { + mqtt_debug("node->ack_type=%d cnt=%d", node->ack_type, cnt++); + if (node->ack_type == IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS) { + list_del(&node->linked_list); + mqtt_free(node); + mqtt_debug("success!!"); + HAL_MutexUnlock(client->lock_generic); + return ret; + } else if (node->ack_type == IOTX_MQTT_EVENT_SUBCRIBE_NACK) { + list_del(&node->linked_list); + mqtt_free(node); + ret = -1; /* resub */ + subed = 0; + } else if (node->ack_type == IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT) { + list_del(&node->linked_list); + mqtt_free(node); + ret = -1; /* resub */ + subed = 0; + } + } + break; + } +#else + for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) { + if (client->list_sub_sync_ack[idx].used == 0) { + continue; + } + + if (client->list_sub_sync_ack[idx].packet_id == ret) { + mqtt_debug("client->list_sub_sync_ack[%d].ack_type=%d cnt=%d", idx, client->list_sub_sync_ack[idx].ack_type, cnt++); + if (client->list_sub_sync_ack[idx].ack_type == IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS) { + memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t)); + mqtt_debug("success!!"); + HAL_MutexUnlock(client->lock_generic); + return ret; + } else if (client->list_sub_sync_ack[idx].ack_type == IOTX_MQTT_EVENT_SUBCRIBE_NACK) { + memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t)); + ret = -1; /* resub */ + subed = 0; + } else if (client->list_sub_sync_ack[idx].ack_type == IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT) { + memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t)); + ret = -1; /* resub */ + subed = 0; + } + } + break; + } +#endif + HAL_MutexUnlock(client->lock_generic); + } while (!utils_time_is_expired(&timer)); + mqtt_warning("sync subscribe time out!!"); + + HAL_MutexLock(client->lock_generic); +#ifdef PLATFORM_HAS_DYNMEM + list_for_each_entry_safe(node, next, &client->list_sub_sync_ack, linked_list, mqtt_sub_sync_node_t) { + if (node->packet_id == ret) { + list_del(&node->linked_list); + mqtt_free(node); + } + } +#else + for (idx = 0; idx < IOTX_MC_SUBSYNC_LIST_MAX_LEN; idx++) { + if (client->list_sub_sync_ack[idx].used && node->packet_id == ret) { + memset(&client->list_sub_sync_ack[idx], 0, sizeof(mqtt_sub_sync_node_t)); + } + } +#endif + HAL_MutexUnlock(client->lock_generic); + + return -1; +} + +int wrapper_mqtt_unsubscribe(void *client, const char *topicFilter) +{ + int rc = FAIL_RETURN; + iotx_mc_client_t *c = (iotx_mc_client_t *)client; + unsigned int msgId; + + if (NULL == c || NULL == topicFilter) { + return NULL_VALUE_ERROR; + } + msgId = iotx_mc_get_next_packetid(c); + + if (0 != iotx_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) { + mqtt_err("topic format is error,topicFilter = %s", topicFilter); + return MQTT_TOPIC_FORMAT_ERROR; + } + + if (!wrapper_mqtt_check_state(c)) { + mqtt_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c)); + return MQTT_STATE_ERROR; + } + + rc = MQTTUnsubscribe(c, topicFilter, msgId); + if (rc != SUCCESS_RETURN) { + if (rc == MQTT_NETWORK_ERROR) { /* send the subscribe packet */ + iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); + } + + mqtt_err("run MQTTUnsubscribe error!, rc = %d", rc); + return rc; + } + + mqtt_info("mqtt unsubscribe packet sent,topic = %s!", topicFilter); + return (int)msgId; +} + +int wrapper_mqtt_publish(void *client, const char *topicName, iotx_mqtt_topic_info_pt topic_msg) +{ + uint16_t msg_id = 0; + int rc = FAIL_RETURN; + iotx_mc_client_t *c = (iotx_mc_client_t *)client; + if (c == NULL || topicName == NULL || topic_msg == NULL || topic_msg->payload == NULL) { + return NULL_VALUE_ERROR; + } + + if (0 != iotx_mc_check_topic(topicName, TOPIC_NAME_TYPE)) { + mqtt_err("topic format is error,topicFilter = %s", topicName); + return MQTT_TOPIC_FORMAT_ERROR; + } + + if (!wrapper_mqtt_check_state(c)) { + mqtt_err("mqtt client state is error,state = %d", iotx_mc_get_client_state(c)); + return MQTT_STATE_ERROR; + } + +#if !WITH_MQTT_ONLY_QOS0 + if (topic_msg->qos == IOTX_MQTT_QOS1 || topic_msg->qos == IOTX_MQTT_QOS2) { + msg_id = iotx_mc_get_next_packetid(c); + topic_msg->packet_id = msg_id; + } + if (topic_msg->qos == IOTX_MQTT_QOS2) { + mqtt_err("MQTTPublish return error,MQTT_QOS2 is now not supported."); + return MQTT_PUBLISH_QOS_ERROR; + } +#else + topic_msg->qos = IOTX_MQTT_QOS0; +#endif + +#if defined(INSPECT_MQTT_FLOW) && defined(INFRA_LOG) + HEXDUMP_DEBUG(topicName, strlen(topicName)); + HEXDUMP_DEBUG(topic_msg->payload, topic_msg->payload_len); +#endif + + rc = MQTTPublish(c, topicName, topic_msg); + if (rc != SUCCESS_RETURN) { /* send the subscribe packet */ + if (rc == MQTT_NETWORK_ERROR) { + iotx_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED); + } + mqtt_err("MQTTPublish is error, rc = %d", rc); + return rc; + } + + return (int)msg_id; +} + +#ifdef ASYNC_PROTOCOL_STACK +int wrapper_mqtt_nwk_event_handler(void *client, iotx_mqtt_nwk_event_t event, iotx_mqtt_nwk_param_t *param) +{ + int rc = FAIL_RETURN; + iotx_mc_client_t *pClient = (iotx_mc_client_t *)client; + if (client == NULL || event >= IOTX_MQTT_SOC_MAX) { + return NULL_VALUE_ERROR; + } + + switch (event) { + case IOTX_MQTT_SOC_CONNECTED: { + rc = _mqtt_connect(pClient); + if (rc == SUCCESS_RETURN) { + iotx_mc_set_client_state(pClient, IOTX_MC_STATE_CONNECTED); + } + } + break; + case IOTX_MQTT_SOC_CLOSE: { + iotx_mc_set_client_state(pClient, IOTX_MC_STATE_DISCONNECTED); + } + break; + case IOTX_MQTT_SOC_READ: { + HAL_MutexLock(pClient->lock_yield); + _mqtt_cycle(pClient); + HAL_MutexUnlock(pClient->lock_yield); + rc = SUCCESS_RETURN; + } + break; + case IOTX_MQTT_SOC_WRITE: { + + } + break; + default: { + mqtt_err("unknown event: %d", event); + } + break; + } + + return rc; +} +#endif + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_client.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_client.h new file mode 100644 index 00000000..3a313733 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/iotx_mqtt_config.h new file mode 100644 index 00000000..c135d7e7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/mqtt_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/impl/mqtt_internal.h new file mode 100644 index 00000000..1dd3507c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/iot.mk new file mode 100644 index 00000000..c5f26e28 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/iot.mk @@ -0,0 +1,13 @@ +LIBA_TARGET := libiot_mqtt.a +HDR_REFS := src/infra +LIB_SRCS_PATTERN := *.c + +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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_api.c new file mode 100644 index 00000000..38f52004 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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_sign_mqtt_t *preauth_out) +{ + uint16_t length = 0; + char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = {0}; + char sign_string[65] = {0}; + int res; + + memset(preauth_out, 0, sizeof(iotx_sign_mqtt_t)); + + /* setup device_id */ + memcpy(device_id, meta->product_key, strlen(meta->product_key)); + memcpy(device_id + strlen(device_id), ".", strlen(".")); + memcpy(device_id + strlen(device_id), meta->device_name, strlen(meta->device_name)); + + /* setup 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_sign_mqtt_t *)&g_default_sign); /* type convert */ + if (ret < SUCCESS_RETURN) { + mqtt_err("ret = _iotx_preauth() = %d, abort", ret); + return NULL; + } +#else /* direct mode */ + ret = IOT_Sign_MQTT(region, &meta_info, &g_default_sign); + if (ret < SUCCESS_RETURN) { + mqtt_err("ret = IOT_Sign_MQTT() = %d, abort", ret); + return NULL; + } +#endif /* #ifdef MQTT_PRE_AUTH */ + + /* 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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_api.h new file mode 100644 index 00000000..54e8a3b2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_api.h @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef _IOT_EXPORT_MQTT_H_ +#define _IOT_EXPORT_MQTT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "infra_types.h" +#include "infra_defs.h" + +#define MUTLI_SUBSCIRBE_MAX (5) + +/* From mqtt_client.h */ +typedef enum { + IOTX_MQTT_QOS0 = 0, + IOTX_MQTT_QOS1, + IOTX_MQTT_QOS2, + IOTX_MQTT_QOS3_SUB_LOCAL +} iotx_mqtt_qos_t; + +typedef enum { + + /* Undefined event */ + IOTX_MQTT_EVENT_UNDEF = 0, + + /* MQTT disconnect event */ + IOTX_MQTT_EVENT_DISCONNECT = 1, + + /* MQTT reconnect event */ + IOTX_MQTT_EVENT_RECONNECT = 2, + + /* A ACK to the specific subscribe which specify by packet-id be received */ + IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS = 3, + + /* No ACK to the specific subscribe which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT = 4, + + /* A failed ACK to the specific subscribe which specify by packet-id be received*/ + IOTX_MQTT_EVENT_SUBCRIBE_NACK = 5, + + /* A ACK to the specific unsubscribe which specify by packet-id be received */ + IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS = 6, + + /* No ACK to the specific unsubscribe which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT = 7, + + /* A failed ACK to the specific unsubscribe which specify by packet-id be received*/ + IOTX_MQTT_EVENT_UNSUBCRIBE_NACK = 8, + + /* A ACK to the specific publish which specify by packet-id be received */ + IOTX_MQTT_EVENT_PUBLISH_SUCCESS = 9, + + /* No ACK to the specific publish which specify by packet-id be received in timeout period */ + IOTX_MQTT_EVENT_PUBLISH_TIMEOUT = 10, + + /* A failed ACK to the specific publish which specify by packet-id be received*/ + IOTX_MQTT_EVENT_PUBLISH_NACK = 11, + + /* MQTT packet published from MQTT remote broker be received */ + IOTX_MQTT_EVENT_PUBLISH_RECEIVED = 12, + + /* MQTT packet buffer overflow which the remaining space less than to receive byte */ + IOTX_MQTT_EVENT_BUFFER_OVERFLOW = 13, +} iotx_mqtt_event_type_t; + +/* topic information */ +typedef struct { + uint16_t packet_id; + uint8_t qos; + uint8_t dup; + uint8_t retain; + uint16_t topic_len; + uint32_t payload_len; + const char *ptopic; + const char *payload; +} iotx_mqtt_topic_info_t, *iotx_mqtt_topic_info_pt; + + +typedef struct { + + /* Specify the event type */ + iotx_mqtt_event_type_t event_type; + + /* + * Specify the detail event information. @msg means different to different event types: + * + * 1) IOTX_MQTT_EVENT_UNKNOWN, + * IOTX_MQTT_EVENT_DISCONNECT, + * IOTX_MQTT_EVENT_RECONNECT : + * Its data type is string and the value is detail information. + * + * 2) IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS, + * IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT, + * IOTX_MQTT_EVENT_SUBCRIBE_NACK, + * IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS, + * IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT, + * IOTX_MQTT_EVENT_UNSUBCRIBE_NACK + * IOTX_MQTT_EVENT_PUBLISH_SUCCESS, + * IOTX_MQTT_EVENT_PUBLISH_TIMEOUT, + * IOTX_MQTT_EVENT_PUBLISH_NACK : + * Its data type is @uint32_t and the value is MQTT packet identifier. + * + * 3) IOTX_MQTT_EVENT_PUBLISH_RECEIVED: + * Its data type is @iotx_mqtt_topic_info_pt and see detail at the declare of this type. + * + * */ + void *msg; +} iotx_mqtt_event_msg_t, *iotx_mqtt_event_msg_pt; + + +/** + * @brief It define a datatype of function pointer. + * This type of function will be called when a related event occur. + * + * @param pcontext : The program context. + * @param pclient : The MQTT client. + * @param msg : The event message. + * + * @return none + */ +typedef void (*iotx_mqtt_event_handle_func_fpt)(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg); + + +/* The structure of MQTT event handle */ +typedef struct { + iotx_mqtt_event_handle_func_fpt h_fp; + void *pcontext; +} iotx_mqtt_event_handle_t, *iotx_mqtt_event_handle_pt; + + +/* The structure of MQTT initial parameter */ +typedef struct { + + uint16_t port; /* Specify MQTT broker port */ + const char *host; /* Specify MQTT broker host */ + const char *client_id; /* Specify MQTT connection client id*/ + const char *username; /* Specify MQTT user name */ + const char *password; /* Specify MQTT password */ + 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 */ + uint32_t write_buf_size; /* Specify size of write-buffer in byte */ + uint32_t read_buf_size; /* Specify size of read-buffer in byte */ + + iotx_mqtt_event_handle_t handle_event; /* Specify MQTT event handle */ + +} iotx_mqtt_param_t, *iotx_mqtt_param_pt; + +typedef enum { + IOTX_MQTT_SOC_CONNECTED, + IOTX_MQTT_SOC_CLOSE, + IOTX_MQTT_SOC_READ, + IOTX_MQTT_SOC_WRITE, + IOTX_MQTT_SOC_MAX +} iotx_mqtt_nwk_event_t; + +typedef struct { + uintptr_t fd; +} iotx_mqtt_nwk_param_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_mqtt mqtt + * @{ + */ + +/** + * @brief Construct the MQTT client + * This function initialize the data structures, establish MQTT connection. + * + * @param [in] pInitParams: specify the MQTT client parameter. + * + * @retval NULL : Construct failed. + * @retval NOT_NULL : The handle of MQTT client. + * @see None. + */ +void *IOT_MQTT_Construct(iotx_mqtt_param_t *pInitParams); + + +/** + * @brief Deconstruct the MQTT client + * This function disconnect MQTT connection and release the related resource. + * + * @param [in] phandle: pointer of handle, specify the MQTT client. + * + * @retval 0 : Deconstruct success. + * @retval -1 : Deconstruct failed. + * @see None. + */ +int IOT_MQTT_Destroy(void **phandle); + + +/** + * @brief Handle MQTT packet from remote server and process timeout request + * which include the MQTT subscribe, unsubscribe, publish(QOS >= 1), reconnect, etc.. + * + * @param [in] handle: specify the MQTT client. + * @param [in] timeout_ms: specify the timeout in millisecond in this loop. + * + * @return status. + * @see None. + */ +int IOT_MQTT_Yield(void *handle, int timeout_ms); + +/** + * @brief check whether MQTT connection is established or not. + * + * @param [in] handle: specify the MQTT client. + * + * @retval true : MQTT in normal state. + * @retval false : MQTT in abnormal state. + * @see None. + */ +int IOT_MQTT_CheckStateNormal(void *handle); + + +/** + * @brief Subscribe MQTT topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] topic_handle_func: specify the topic handle callback-function. + * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back. + * + * @retval -1 : Subscribe failed. + * @retval >=0 : Subscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +int IOT_MQTT_Subscribe(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext); + +/** + * @brief Subscribe MQTT topic and wait suback. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] topic_handle_func: specify the topic handle callback-function. + * @param [in] pcontext: specify context. When call 'topic_handle_func', it will be passed back. + * @param [in] timeout_ms: time in ms to wait. + * + * @retval -1 : Subscribe failed. + * @retval >=0 : Subscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +int IOT_MQTT_Subscribe_Sync(void *handle, + const char *topic_filter, + iotx_mqtt_qos_t qos, + iotx_mqtt_event_handle_func_fpt topic_handle_func, + void *pcontext, + int timeout_ms); + + +/** + * @brief Unsubscribe MQTT topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_filter: specify the topic filter. + * + * @retval -1 : Unsubscribe failed. + * @retval >=0 : Unsubscribe successful. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +int IOT_MQTT_Unsubscribe(void *handle, const char *topic_filter); + + +/** + * @brief Publish message to specific topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_name: specify the topic name. + * @param [in] topic_msg: specify the topic message. + * + * @retval -1 : Publish failed. + * @retval 0 : Publish successful, where QoS is 0. + * @retval >0 : Publish successful, where QoS is >= 0. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +int IOT_MQTT_Publish(void *handle, const char *topic_name, iotx_mqtt_topic_info_pt topic_msg); +/** + * @brief Publish message to specific topic. + * + * @param [in] handle: specify the MQTT client. + * @param [in] topic_name: specify the topic name. + * @param [in] qos: specify the MQTT Requested QoS. + * @param [in] data: specify the topic message payload. + * @param [in] len: specify the topic message payload len. + * + * @retval -1 : Publish failed. + * @retval 0 : Publish successful, where QoS is 0. + * @retval >0 : Publish successful, where QoS is >= 0. + The value is a unique ID of this request. + The ID will be passed back when callback 'iotx_mqtt_param_t:handle_event'. + * @see None. + */ +int IOT_MQTT_Publish_Simple(void *handle, const char *topic_name, int qos, void *data, int len); +/* From mqtt_client.h */ +/** @} */ /* end of api_mqtt */ + +/** @} */ /* end of api */ + +/** + * @brief Only used in async network stack and FEATURE_ASYNC_PROTOCOL_STACK must be selected + * + * @param [in] handle: specify the MQTT client. + * @param [in] event: specify the network event. + * @param [in] param: specify the network params. + * + * @retval -1 : Handle failed. + * @retval 0 : Handle successful. + * + */ +int IOT_MQTT_Nwk_Event_Handler(void *handle, iotx_mqtt_nwk_event_t event, iotx_mqtt_nwk_param_t *param); + +/* MQTT Configurations + * + * These switches will affect mqtt_api.c and IOT_MQTT_XXX() functions' behaviour + * + */ + +/* Default message length in bytes when PLATFORM_HAS_DYNMEM is not set */ +#define CONFIG_MQTT_MESSAGE_MAXLEN (1024) + +/* Default maximum length of topic name in byte when PLATFORM_HAS_DYNMEM is not set */ +#ifdef PLATFORM_HAS_DYNMEM +#define CONFIG_MQTT_TOPIC_MAXLEN (128) +#else +#define CONFIG_MQTT_TOPIC_MAXLEN (50) +#endif + +/* Default keepalive interval of MQTT request in second */ +#define CONFIG_MQTT_KEEPALIVE_INTERVAL (60) + + +/* Default offline subscribe list max length when PLATFORM_HAS_DYNMEM is not set */ +#ifndef CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM +#define CONFIG_MQTT_OFFLINE_TOPIC_MAXNUM (5) +#endif + +/* Default timeout interval of MQTT request in millisecond */ +#define CONFIG_MQTT_REQUEST_TIMEOUT (2000) + +/* Minimum timeout interval of MQTT request in millisecond */ +#define CONFIG_MQTT_REQ_TIMEOUT_MIN (500) + +/* Maximum timeout interval of MQTT request in millisecond */ +#define CONFIG_MQTT_REQ_TIMEOUT_MAX (5000) + +/* Minimum keepalive interval of MQTT request in second */ +#define CONFIG_MQTT_KEEPALIVE_INTERVAL_MIN (30) + +/* Maximum keepalive interval of MQTT request in second */ +#define CONFIG_MQTT_KEEPALIVE_INTERVAL_MAX (1200) + +#if defined(__cplusplus) +} +#endif +#endif + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/mqtt/mqtt_wrapper.h new file mode 100644 index 00000000..0f228d24 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/examples/ota_example_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/examples/ota_example_mqtt.c new file mode 100644 index 00000000..d6f820f6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/examples/ota_example_mqtt.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include +#include +#include +#include + +#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) + +#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_RECEIVED: + 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 int _ota_mqtt_client(void) +{ +#define OTA_BUF_LEN (5000) + + int rc = 0, ota_over = 0; + void *pclient = NULL, *h_ota = NULL; + iotx_conn_info_pt pconn_info; + iotx_mqtt_param_t mqtt_params; + char *msg_buf = NULL, *msg_readbuf = NULL; + FILE *fp; + char buf_ota[OTA_BUF_LEN]; + + if (NULL == (fp = fopen("ota.bin", "wb+"))) { + EXAMPLE_TRACE("open file failed"); + goto do_exit; + } + + + if (NULL == (msg_buf = (char *)HAL_Malloc(OTA_MQTT_MSGLEN))) { + EXAMPLE_TRACE("not enough memory"); + rc = -1; + goto do_exit; + } + + if (NULL == (msg_readbuf = (char *)HAL_Malloc(OTA_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.read_buf_size = OTA_MQTT_MSGLEN; + mqtt_params.write_buf_size = OTA_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; + } + 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.1.0")) { */ + /* rc = -1; */ + /* EXAMPLE_TRACE("report OTA version failed"); */ + /* goto do_exit; */ + /* } */ + + HAL_SleepMs(1000); + + do { + uint32_t firmware_valid; + + EXAMPLE_TRACE("wait ota upgrade command...."); + + /* handle the MQTT packet received from TCP or SSL connection */ + IOT_MQTT_Yield(pclient, 200); + + if (IOT_OTA_IsFetching(h_ota)) { + uint32_t last_percent = 0, percent = 0; + char md5sum[33]; + char version[128] = {0}; + uint32_t len, size_downloaded, size_file; + 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_MQTT_Yield(pclient, 100); + } while (!IOT_OTA_IsFetchFinish(h_ota)); + + IOT_OTA_Ioctl(h_ota, IOT_OTAG_CHECK_FIRMWARE, &firmware_valid, 4); + if (0 == firmware_valid) { + EXAMPLE_TRACE("The firmware is invalid"); + } else { + EXAMPLE_TRACE("The firmware is valid"); + } + + ota_over = 1; + } + HAL_SleepMs(2000); + } while (!ota_over); + + HAL_SleepMs(200); + + + +do_exit: + + if (NULL != h_ota) { + IOT_OTA_Deinit(h_ota); + } + + if (NULL != pclient) { + IOT_MQTT_Destroy(&pclient); + } + + if (NULL != msg_buf) { + HAL_Free(msg_buf); + } + + if (NULL != msg_readbuf) { + HAL_Free(msg_readbuf); + } + + if (NULL != fp) { + fclose(fp); + } + + return rc; +} + +int main(int argc, char *argv[]) +{ + EXAMPLE_TRACE("hello main func"); + IOT_SetLogLevel(IOT_LOG_DEBUG); + + user_argc = argc; + user_argv = argv; + + _ota_mqtt_client(); + + IOT_DumpMemoryStats(IOT_LOG_DEBUG); + + EXAMPLE_TRACE("out of sample!"); + return 0; +} + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iot.mk new file mode 100644 index 00000000..479fe345 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iot.mk @@ -0,0 +1,13 @@ +LIBA_TARGET := libiot_ota.a + +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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota.c new file mode 100644 index 00000000..49d8bc57 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota.h new file mode 100644 index 00000000..816e31ea --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota_config.h new file mode 100644 index 00000000..3536a436 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/iotx_ota_internal.h new file mode 100644 index 00000000..8bb6c587 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_api.h new file mode 100644 index 00000000..26d88372 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_api.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __OTA_EXPORT_H__ +#define __OTA_EXPORT_H__ + +#include "infra_types.h" +#include "infra_defs.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define OTA_CH_SIGNAL_MQTT (0) +#define OTA_CH_SIGNAL_COAP (1) +#define OTA_CH_FETCH_HTTP (1) + + +typedef enum { + + IOT_OTAE_GENERAL = -1, + IOT_OTAE_INVALID_PARAM = -2, + IOT_OTAE_INVALID_STATE = -3, + IOT_OTAE_STR_TOO_LONG = -4, + IOT_OTAE_FETCH_FAILED = -5, + IOT_OTAE_NOMEM = -6, + IOT_OTAE_OSC_FAILED = -7, + IOT_OTAE_NONE = 0, + +} IOT_OTA_Err_t; + + +/* State of OTA */ +typedef enum { + IOT_OTAS_UNINITED = 0, /* Uninitialized State */ + IOT_OTAS_INITED, /* Initialized State */ + IOT_OTAS_FETCHING, /* Fetching firmware */ + IOT_OTAS_FETCHED /* Fetching firmware finish */ +} IOT_OTA_State_t; + +typedef enum { + IOT_OTAT_NONE, + IOT_OTAT_COTA, + IOT_OTAT_FOTA +} IOT_OTA_Type_t; + +/* Progress of OTA */ +typedef enum { + + /* Burn firmware file failed */ + IOT_OTAP_BURN_FAILED = -4, + + /* Check firmware file failed */ + IOT_OTAP_CHECK_FALIED = -3, + + /* Fetch firmware file failed */ + IOT_OTAP_FETCH_FAILED = -2, + + /* Initialized failed */ + IOT_OTAP_GENERAL_FAILED = -1, + + + /* [0, 100], percentage of fetch progress */ + + /* The minimum percentage of fetch progress */ + IOT_OTAP_FETCH_PERCENTAGE_MIN = 0, + + /* The maximum percentage of fetch progress */ + IOT_OTAP_FETCH_PERCENTAGE_MAX = 100 + +} IOT_OTA_Progress_t; + + +typedef enum { + IOT_OTAG_COTA_CONFIG_ID, + IOT_OTAG_COTA_CONFIG_SIZE, + IOT_OTAG_COTA_SIGN, + IOT_OTAG_COTA_SIGN_METHOD, + IOT_OTAG_COTA_URL, + IOT_OTAG_COTA_GETTYPE, + IOT_OTAG_OTA_TYPE, + IOT_OTAG_FETCHED_SIZE, /* option for get already fetched size */ + IOT_OTAG_FILE_SIZE, /* size of file */ + IOT_OTAG_MD5SUM, /* md5 in string format */ + IOT_OTAG_VERSION, /* version in string format */ + IOT_OTAG_CHECK_FIRMWARE, /* Check firmware is valid or not */ + IOT_OTAG_CHECK_CONFIG, /* Check config file is valid or not */ + IOT_OTAG_RESET_FETCHED_SIZE /* reset the size_fetched parameter to be 0 */ +} IOT_OTA_CmdType_t; + +/** @defgroup group_api api + * @{ + */ + +/** @defgroup group_api_ota ota + * @{ + */ + +/** + * @brief Initialize OTA module, and return handle. + * The MQTT client must be construct before calling this interface. + * + * @param [in] product_key: specify the product key. + * @param [in] device_name: specify the device name. + * @param [in] ch_signal: specify the signal channel. + * + * @retval 0 : Successful. + * @retval -1 : Failed. + * @see None. + */ +void *IOT_OTA_Init(const char *product_key, const char *device_name, void *ch_signal); + + +/** + * @brief Deinitialize OTA module specified by the 'handle', and release the related resource. + * You must call this interface to release resource if reboot is not invoked after downloading. + * + * @param [in] handle: specify the OTA module. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +int IOT_OTA_Deinit(void *handle); + + +/** + * @brief Report firmware version information to OTA server (optional). + * NOTE: please + * + * @param [in] handle: specify the OTA module. + * @param [in] version: specify the firmware version in string format. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +int IOT_OTA_ReportVersion(void *handle, const char *version); + +/** + * @brief Report detail progress to OTA server (optional). + * NOTE: please + * + * @param [in] handle: specify the OTA module. + * @param [in] progress: specify the progress defined by 'IOT_OTA_Progress_t'. + * @param [in] msg: detail progress information in string. + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +int IOT_OTA_ReportProgress(void *handle, IOT_OTA_Progress_t progress, const char *msg); + + +/** + * @brief Check whether is on fetching state + * + * @param [in] handle: specify the OTA module. + * + * @retval 1 : Yes. + * @retval 0 : No. + * @see None. + */ +int IOT_OTA_IsFetching(void *handle); + + +/** + * @brief Check whether is on end-of-fetch state. + * + * @param [in] handle: specify the OTA module. + * + * @retval 1 : Yes. + * @retval 0 : False. + * @see None. + */ +int IOT_OTA_IsFetchFinish(void *handle); + + +/** + * @brief fetch firmware from remote server with specific timeout value. + * NOTE: If you want to download more faster, the bigger 'buf' should be given. + * + * @param [in] handle: specify the OTA module. + * @param [out] buf: specify the space for storing firmware data. + * @param [in] buf_len: specify the length of 'buf' in bytes. + * @param [in] timeout_s: specify the timeout value in second. + * + * @retval < 0 : Error occur.. + * @retval 0 : No any data be downloaded in 'timeout_s' timeout period. + * @retval (0, len] : The length of data be downloaded in 'timeout_s' timeout period in bytes. + * @see None. + */ +int IOT_OTA_FetchYield(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s); + + +/** + * @brief Get OTA information specified by 'type'. + * By this interface, you can get information like state, size of file, md5 of file, etc. + * + * @param [in] handle: handle of the specific OTA + * @param [in] type: specify what information you want, see detail 'IOT_OTA_CmdType_t' + * @param [out] buf: specify buffer for data exchange + * @param [in] buf_len: specify the length of 'buf' in byte. + * @return + @verbatim + NOTE: + 1) When type is IOT_OTAG_FETCHED_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 2) When type is IOT_OTAG_FILE_SIZE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 3) When type is IOT_OTAG_MD5SUM, 'buf' should be a buffer, and 'buf_len' should be 33. + 4) When type is IOT_OTAG_VERSION, 'buf' should be a buffer, and 'buf_len' should be OTA_VERSION_LEN_MAX. + 5) When type is IOT_OTAG_CHECK_FIRMWARE, 'buf' should be pointer of uint32_t, and 'buf_len' should be 4. + 0, firmware is invalid; 1, firmware is valid. + @endverbatim + * + * @retval 0 : Successful. + * @retval < 0 : Failed, the value is error code. + * @see None. + */ +int IOT_OTA_Ioctl(void *handle, IOT_OTA_CmdType_t type, void *buf, int buf_len); + + +/** + * @brief Get last error code. + * + * @param [in] handle: specify the OTA module. + * + * @return The error code. + * @see None. + */ +int IOT_OTA_GetLastError(void *handle); + +/** @} */ /* end of api_ota */ +/** @} */ /* end of api */ + +#if defined(__cplusplus) +} +#endif + +#endif /* __OTA_EXPORT_H__ */ + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_coap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_coap.c new file mode 100644 index 00000000..70ce80a6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_coap.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#ifndef __OTA_COAP_C_H__ +#define __OTA_COAP_C_H__ +#if (OTA_SIGNAL_CHANNEL) == 2 + +#include "iotx_ota_internal.h" + +/* OSC, OTA signal channel */ + +/* Specify the maximum characters of version */ +#define OSC_COAP_URI_MAX_LEN (135) /* IoTx CoAP uri maximal length */ + + +typedef struct { + void *coap; + const char *product_key; + const char *device_name; + ota_cb_fpt cb; + void *context; +} otacoap_Struct_t, *otacoap_Struct_pt; + + +static otacoap_Struct_pt h_osc_coap = NULL; + +static void otacoap_response_handler(void *arg, void *p_response) +{ + int len = 0; + unsigned char *p_payload = NULL; + iotx_coap_resp_code_t resp_code; + IOT_CoAP_GetMessageCode(p_response, &resp_code); + IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len); + OTA_LOG_DEBUG("CoAP response code = %d", resp_code); + OTA_LOG_DEBUG("[CoAP msg_len=%d, msg=%s\r\n", len, p_payload); + + if ((NULL != h_osc_coap) && (NULL != p_payload)) { + h_osc_coap->cb(h_osc_coap->context, (const char *)p_payload, (uint32_t)len); + } +} + + +/* Generate topic name according to @ota_topic_type, @product_key, @device_name */ +/* and then copy to @buf. */ +/* 0, successful; -1, failed */ +static int otacoap_GenTopicName(char *buf, size_t buf_len, const char *ota_topic_type, const char *product_key, + const char *device_name) +{ + int ret; + + ret = OTA_SNPRINTF(buf, + buf_len, + "/topic/ota/device/%s/%s/%s", + ota_topic_type, + product_key, + device_name); + + if (ret >= buf_len) { + return -1; + } + + if (ret < 0) { + OTA_LOG_ERROR("snprintf failed"); + return -1; + } + + return 0; +} + +/* report progress of OTA */ +static int otacoap_Publish(otacoap_Struct_pt handle, const char *topic_type, const char *msg) +{ + int ret; + char uri[IOTX_URI_MAX_LEN + 1] = {0}; + iotx_message_t message; + message.p_payload = (unsigned char *)msg; + message.payload_len = (unsigned short)strlen(msg); + message.resp_callback = otacoap_response_handler; + message.msg_type = IOTX_MESSAGE_CON; + message.content_type = IOTX_CONTENT_TYPE_JSON; + + /* topic name: /topic/ota/device/${topic_type}/${productKey}/${deviceName} */ + ret = otacoap_GenTopicName(uri, OSC_COAP_URI_MAX_LEN, topic_type, handle->product_key, handle->device_name); + if (ret < 0) { + OTA_LOG_ERROR("generate topic name failed"); + return -1; + } + + if (IOTX_SUCCESS != (ret = IOT_CoAP_SendMessage(handle->coap, (char *)uri, &message))) { + OTA_LOG_ERROR("send CoAP msg failed%d", ret); + return -1; + } + + return 0; +} + + +void *osc_Init(const char *product_key, const char *device_name, void *ch_signal, ota_cb_fpt cb, void *context) +{ + otacoap_Struct_pt h_osc = NULL; + + if (NULL == (h_osc = OTA_MALLOC(sizeof(otacoap_Struct_t)))) { + OTA_LOG_ERROR("allocate for h_osc failed"); + return NULL; + } + + memset(h_osc, 0, sizeof(otacoap_Struct_t)); + + h_osc->coap = ch_signal; + h_osc->product_key = product_key; + h_osc->device_name = device_name; + h_osc->cb = cb; + h_osc->context = context; + + h_osc_coap = h_osc; + + return h_osc; +} + + +int osc_Deinit(void *handle) +{ + if (NULL != handle) { + OTA_FREE(handle); + } + + return 0; +} + +/* report progress of OTA */ +int osc_ReportProgress(void *handle, const char *msg) +{ + return otacoap_Publish(handle, "progress", msg); +} + + +/* report version of OTA firmware */ +int osc_ReportVersion(void *handle, const char *msg) +{ + static int state = 0; + int ret; + + if (0 == state) { /* report version in initial state */ + ret = otacoap_Publish(handle, "inform", msg); + if (0 != ret) { + return ret; + } + state = 1; + } + + /* request new firmware after initial state */ + return otacoap_Publish(handle, "request", msg); +} + +#endif /* #if (OTA_SIGNAL_CHANNEL) == 2 */ +#endif + + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_fetch.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_fetch.c new file mode 100644 index 00000000..b80a5f55 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_fetch.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include "iotx_ota_internal.h" + +/* ofc, OTA fetch channel */ + +typedef struct { + + const char *url; + httpclient_t http; /* http client */ + httpclient_data_t http_data; /* http client data */ + +} otahttp_Struct_t, *otahttp_Struct_pt; + +extern int httpclient_common(httpclient_t *client, + const char *url, + int port, + const char *ca_crt, + HTTPCLIENT_REQUEST_TYPE method, + uint32_t timeout_ms, + httpclient_data_t *client_data); + +void *ofc_Init(char *url) +{ + otahttp_Struct_pt h_odc; + + if (NULL == (h_odc = OTA_MALLOC(sizeof(otahttp_Struct_t)))) { + OTA_LOG_ERROR("allocate for h_odc failed"); + return NULL; + } + + memset(h_odc, 0, sizeof(otahttp_Struct_t)); + + /* set http request-header parameter */ + h_odc->http.header = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \ + "Accept-Encoding: gzip, deflate\r\n"; +#if defined(SUPPORT_ITLS) + char *s_ptr = strstr(url, "://"); + if (strlen("https") == (s_ptr - url) && (0 == strncmp(url, "https", strlen("https")))) { + strncpy(url + 1, url, strlen("http")); + url++; + } +#endif + h_odc->url = url; + + return h_odc; +} + + +extern const char *iotx_ca_crt; + +int32_t ofc_Fetch(void *handle, char *buf, uint32_t buf_len, uint32_t timeout_s) +{ + int diff; + otahttp_Struct_pt h_odc = (otahttp_Struct_pt)handle; + + h_odc->http_data.response_buf = buf; + h_odc->http_data.response_buf_len = buf_len; + diff = h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len; + +#if !defined(SUPPORT_TLS) + if (0 != httpclient_common(&h_odc->http, h_odc->url, 80, 0, HTTPCLIENT_GET, timeout_s * 1000, + &h_odc->http_data)) { +#else + if (0 != httpclient_common(&h_odc->http, h_odc->url, 443, iotx_ca_crt, HTTPCLIENT_GET, timeout_s * 1000, + &h_odc->http_data)) { +#endif + OTA_LOG_ERROR("fetch firmware failed"); + return -1; + } + + return h_odc->http_data.response_content_len - h_odc->http_data.retrieve_len - diff; +} + + +int ofc_Deinit(void *handle) +{ + if (NULL != handle) { + OTA_FREE(handle); + } + + return 0; +} + + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_lib.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_lib.c new file mode 100644 index 00000000..0bd8c46e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_lib.c @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2015-2018 Alibaba Group Holding Limited + */ + +#include "iotx_ota_internal.h" + +const char *otalib_JsonValueOf(const char *json, uint32_t json_len, const char *key, uint32_t *val_len) +{ + int length; + const char *val; + val = json_get_value_by_name((char *)json, json_len, (char *)key, &length, NULL); + if (NULL != val) { + *val_len = (uint32_t) length; + } + return val; +} + +void *otalib_MD5Init(void) +{ + iot_md5_context *ctx = OTA_MALLOC(sizeof(iot_md5_context)); + if (NULL == ctx) { + return NULL; + } + + utils_md5_init(ctx); + utils_md5_starts(ctx); + + return ctx; +} + +void otalib_MD5Update(void *md5, const char *buf, size_t buf_len) +{ + utils_md5_update(md5, (unsigned char *)buf, buf_len); +} + +void otalib_MD5Finalize(void *md5, char *output_str) +{ + int i; + unsigned char buf_out[16]; + utils_md5_finish(md5, buf_out); + + for (i = 0; i < 16; ++i) { + output_str[i * 2] = infra_hex2char(buf_out[i] >> 4); + output_str[i * 2 + 1] = infra_hex2char(buf_out[i]); + } + output_str[32] = '\0'; +} + +void otalib_MD5Deinit(void *md5) +{ + if (NULL != md5) { + OTA_FREE(md5); + } +} + +void *otalib_Sha256Init(void) +{ + iot_sha256_context *ctx = OTA_MALLOC(sizeof(iot_sha256_context)); + if (NULL == ctx) { + return NULL; + } + + utils_sha256_init(ctx); + utils_sha256_starts(ctx); + + return ctx; +} + +void otalib_Sha256Update(void *sha256, const char *buf, size_t buf_len) +{ + utils_sha256_update(sha256, (unsigned char *)buf, buf_len); +} + +void otalib_Sha256Finalize(void *sha256, char *output_str) +{ + int i; + unsigned char buf_out[32]; + utils_sha256_finish(sha256, buf_out); + + for (i = 0; i < 32; ++i) { + output_str[i * 2] = infra_hex2char(buf_out[i] >> 4); + output_str[i * 2 + 1] = infra_hex2char(buf_out[i]); + } + output_str[64] = '\0'; +} + +void otalib_Sha256Deinit(void *sha256) +{ + utils_sha256_free(sha256); + if (NULL != sha256) { + OTA_FREE(sha256); + } +} +/* Get the specific @key value, and copy to @dest */ +/* 0, successful; -1, failed */ +int otalib_GetFirmwareFixlenPara(const char *json_doc, + size_t json_doc_len, + const char *key, + char *dest, + size_t dest_len) +{ + const char *pvalue; + uint32_t val_len; + + if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len))) { + OTA_LOG_ERROR("Not '%s' key in json doc of OTA", key); + return -1; + } + + if (val_len > dest_len) { + OTA_LOG_ERROR("value length of the key is too long"); + return -1; + } + + memcpy(dest, pvalue, val_len); + + return 0; +} + + +/* Get variant length parameter of firmware, and copy to @dest */ +/* 0, successful; -1, failed */ +int otalib_GetFirmwareVarlenPara(const char *json_doc, + size_t json_doc_len, + const char *key, + char **dest) +{ + const char *pvalue; + uint32_t val_len; + + if (NULL == (pvalue = otalib_JsonValueOf(json_doc, json_doc_len, key, &val_len))) { + OTA_LOG_ERROR("Not %s key in json doc of OTA", key); + return -1; + } + + if (NULL == (*dest = OTA_MALLOC(val_len + 1))) { + OTA_LOG_ERROR("allocate for dest failed"); + return -1; + } + + memcpy(*dest, pvalue, val_len); + (*dest)[val_len] = '\0'; + + return 0; +} + +int otalib_GetParams(const char *json_doc, uint32_t json_len, char **url, char **version, char *md5, + uint32_t *file_size) +{ +#define OTA_FILESIZE_STR_LEN (16) + char file_size_str[OTA_FILESIZE_STR_LEN + 1] = {0}; + + /* get version */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "version", version)) { + OTA_LOG_ERROR("get value of version key failed"); + return -1; + } + + /* get URL */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) { + OTA_LOG_ERROR("get value of url key failed"); + return -1; + } + + /* get md5 */ + if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "md5", md5, 32)) { + OTA_LOG_ERROR("get value of md5 key failed"); + return -1; + } + + /* get file size */ + if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "size", file_size_str, OTA_FILESIZE_STR_LEN)) { + OTA_LOG_ERROR("get value of size key failed"); + return -1; + } + file_size_str[OTA_FILESIZE_STR_LEN] = '\0'; + *file_size = atoi(file_size_str); + + return 0; + +#undef OTA_FILESIZE_STR_LEN +} + +int otalib_GetConfigParams(const char *json_doc, uint32_t json_len, char **configId, uint32_t *configSize, char **sign, + char **signMethod, char **url, char **getType) +{ +#define OTA_FILESIZE_STR_LEN (16) + char file_size_str[OTA_FILESIZE_STR_LEN + 1]; + + /* get configId */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "configId", configId)) { + OTA_LOG_ERROR("get value of configId key failed"); + return -1; + } + + /* get configSize */ + if (0 != otalib_GetFirmwareFixlenPara(json_doc, json_len, "configSize", file_size_str, OTA_FILESIZE_STR_LEN)) { + OTA_LOG_ERROR("get value of size key failed"); + return -1; + } + file_size_str[OTA_FILESIZE_STR_LEN] = '\0'; + *configSize = atoi(file_size_str); + + /* get sign */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "sign", sign)) { + OTA_LOG_ERROR("get value of sign key failed"); + return -1; + } + + /* get signMethod */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "signMethod", signMethod)) { + OTA_LOG_ERROR("get value of signMethod key failed"); + return -1; + } + + /* get url */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "url", url)) { + OTA_LOG_ERROR("get value of url key failed"); + return -1; + } + + /* get getType */ + if (0 != otalib_GetFirmwareVarlenPara(json_doc, json_len, "getType", getType)) { + OTA_LOG_ERROR("get value of getType key failed"); + return -1; + } + return 0; + +#undef OTA_FILESIZE_STR_LEN +} + +/* Generate firmware information according to @id, @version */ +/* and then copy to @buf. */ +/* 0, successful; -1, failed */ +int otalib_GenInfoMsg(char *buf, size_t buf_len, uint32_t id, const char *version) +{ + int ret; + ret = HAL_Snprintf(buf, + buf_len, + "{\"id\":%d,\"params\":{\"version\":\"%s\"}}", + id, + version); + + if (ret < 0) { + OTA_LOG_ERROR("HAL_Snprintf failed"); + return -1; + } + + return 0; +} + +/* Generate report information according to @id, @msg */ +/* and then copy to @buf. */ +/* 0, successful; -1, failed */ +int otalib_GenReportMsg(char *buf, size_t buf_len, uint32_t id, int progress, const char *msg_detail) +{ + int ret; + if (NULL == msg_detail) { + ret = HAL_Snprintf(buf, + buf_len, + "{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"\"}}", + id, + progress); + } else { + ret = HAL_Snprintf(buf, + buf_len, + "{\"id\":%d,\"params\":{\"step\":\"%d\",\"desc\":\"%s\"}}", + id, + progress, + msg_detail); + } + + + if (ret < 0) { + OTA_LOG_ERROR("HAL_Snprintf failed"); + return -1; + } else if (ret >= buf_len) { + OTA_LOG_ERROR("msg is too long"); + return IOT_OTAE_STR_TOO_LONG; + } + + return 0; +} + + diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_mqtt.c new file mode 100644 index 00000000..ceea75c7 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/ota/ota_wrapper.h new file mode 100644 index 00000000..d5a0794b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/dev_ap/awss_dev_ap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/dev_ap/awss_dev_ap.c new file mode 100644 index 00000000..efc4322d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/dev_ap/awss_dev_ap.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/dev_ap/awss_dev_ap.h new file mode 100644 index 00000000..0250ca2b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/dev_ap/dev_ap_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/dev_ap/dev_ap_wrapper.h new file mode 100644 index 00000000..7f591f35 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/aplist/awss_aplist.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/aplist/awss_aplist.c new file mode 100644 index 00000000..e7a1a0c0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/aplist/awss_aplist.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/aplist/awss_aplist.h new file mode 100644 index 00000000..8ec3927b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/aws_lib.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/aws_lib.h new file mode 100644 index 00000000..a713a8bb --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss.c new file mode 100644 index 00000000..54e70606 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss.c @@ -0,0 +1,219 @@ +/* + * 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; +} + +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; +} + +#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG) + +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; +} + + +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; +} + +#endif +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_main.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_main.c new file mode 100644 index 00000000..13d40ac2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_main.c @@ -0,0 +1,133 @@ +/* + * 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 + +#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG) + +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; +} + +#endif +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_main.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_main.h new file mode 100644 index 00000000..6175213a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_smartconfig.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/awss_smartconfig.h new file mode 100644 index 00000000..13e0a7e4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.c new file mode 100644 index 00000000..07f4a9f8 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/ieee80211/zconfig_ieee80211.h new file mode 100644 index 00000000..bf329fb6 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/statics/awss_statis.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/statics/awss_statis.c new file mode 100644 index 00000000..f3e364b1 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/statics/awss_statis.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/statics/awss_statis.h new file mode 100644 index 00000000..19afd4dd --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_aes_wrapper.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_aes_wrapper.c new file mode 100644 index 00000000..9aa78557 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_aes_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_aes_wrapper.h new file mode 100644 index 00000000..d8bbe41f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_crypt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_crypt.c new file mode 100644 index 00000000..3786c1ba --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_crypt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/awss_crypt.h new file mode 100644 index 00000000..8b80c27e --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/zconfig_utils.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/zconfig_utils.c new file mode 100644 index 00000000..54b2ac64 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/zconfig_utils.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/utils/zconfig_utils.h new file mode 100644 index 00000000..d738bb7a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_lib.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_lib.h new file mode 100644 index 00000000..32da0cfa --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_protocol.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_protocol.c new file mode 100644 index 00000000..0a693c15 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_protocol.c @@ -0,0 +1,341 @@ +/* + * 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 + +#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG) + +/* 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); +} +#endif + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_protocol.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_protocol.h new file mode 100644 index 00000000..57024637 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_vendor_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_vendor_common.c new file mode 100644 index 00000000..bd143805 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/frameworks/zconfig_vendor_common.c @@ -0,0 +1,577 @@ +/* + * 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 + +#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG) + +/* 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; +} + +#endif +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/ht40/awss_ht40.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/ht40/awss_ht40.c new file mode 100644 index 00000000..38386901 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/ht40/awss_ht40.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/ht40/awss_ht40.h new file mode 100644 index 00000000..b4943d4a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/iot.mk new file mode 100644 index 00000000..fbce0c37 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/p2p/awss_wps.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/p2p/awss_wps.c new file mode 100644 index 00000000..0f451296 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/p2p/awss_wps.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/p2p/awss_wps.h new file mode 100644 index 00000000..0cb7feec --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/p2p/p2p_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/p2p/p2p_wrapper.h new file mode 100644 index 00000000..30f348b0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/aha_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/aha_wrapper.h new file mode 100644 index 00000000..2524ab6b --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_aha.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_aha.c new file mode 100644 index 00000000..44bacaf9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_aha.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_aha.h new file mode 100644 index 00000000..3d92cf70 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_wifimgr.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_wifimgr.c new file mode 100644 index 00000000..81dcf09d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_wifimgr.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/phone_ap/awss_wifimgr.h new file mode 100644 index 00000000..19d41967 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/router_ap/awss_adha.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/router_ap/awss_adha.c new file mode 100644 index 00000000..ae637f46 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/router_ap/awss_adha.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/router_ap/awss_adha.h new file mode 100644 index 00000000..68730518 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/smartconfig/awss_smartconfig.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/smartconfig/awss_smartconfig.c new file mode 100644 index 00000000..0cb4e337 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/smartconfig/smartconfig_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/smartconfig/smartconfig_wrapper.h new file mode 100644 index 00000000..30f348b0 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/wifi_provision_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/wifi_provision_api.h new file mode 100644 index 00000000..30bb95f2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/wifi_provision_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/wifi_provision_internal.h new file mode 100644 index 00000000..4badb9b2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/awss_enrollee.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/awss_enrollee.c new file mode 100644 index 00000000..2cbb0e2d --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/awss_enrollee.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/awss_enrollee.h new file mode 100644 index 00000000..884da241 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/awss_registrar.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/awss_registrar.c new file mode 100644 index 00000000..7e11dc91 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/zeroconfig_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/wifi_provision/zero_config/zeroconfig_wrapper.h new file mode 100644 index 00000000..210a2355 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/Config.in b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/Config.in new file mode 100644 index 00000000..62d0e47f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/board/config.alios.esp8266 b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/board/config.alios.esp8266 new file mode 100644 index 00000000..98acaf90 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/board/config.alios.mk3080 b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/board/config.alios.mk3080 new file mode 100644 index 00000000..b0cb00df --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/board/config.ubuntu.x86 b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/board/config.ubuntu.x86 new file mode 100644 index 00000000..eb30ce1c --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-complib.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-complib.mk new file mode 100644 index 00000000..def6a77a --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-coverage.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-coverage.mk new file mode 100644 index 00000000..e47cd145 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-dist.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-dist.mk new file mode 100644 index 00000000..1f7029f9 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-flat.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-flat.mk new file mode 100644 index 00000000..8967b553 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-kmod.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-kmod.mk new file mode 100644 index 00000000..8df3d3ca --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-libs.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-libs.mk new file mode 100644 index 00000000..bae9a4f4 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-modinfo.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-modinfo.mk new file mode 100644 index 00000000..4f54ef56 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-origin.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-origin.mk new file mode 100644 index 00000000..5efea638 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-prefix.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-prefix.mk new file mode 100644 index 00000000..68c9066f --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-prog.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-prog.mk new file mode 100644 index 00000000..72c79586 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-repo.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-repo.mk new file mode 100644 index 00000000..a97d2071 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-submods.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-submods.mk new file mode 100644 index 00000000..cc9bb3ca --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-top.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/_rules-top.mk new file mode 100644 index 00000000..71bf1440 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/docs/Help.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/docs/Help.md new file mode 100644 index 00000000..256c1254 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/funcs.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/funcs.mk new file mode 100644 index 00000000..ad668009 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/hooks/pre-commit b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/hooks/pre-commit new file mode 100644 index 00000000..d1888f10 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/misc/Doxyfile.tpl b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/tools/build-rules/misc/Doxyfile.tpl new file mode 100644 index 00000000..869123e2 --- /dev/null +++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/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 +# , /