zqy 2 years ago
parent
commit
598216b708
100 changed files with 14488 additions and 0 deletions
  1. 24 0
      iot_link/BUILD.gn
  2. 24 0
      iot_link/LICENSE
  3. 8 0
      iot_link/README.md
  4. 24 0
      iot_link/bundle.json
  5. 23 0
      iot_link/inc/BUILD.gn
  6. 77 0
      iot_link/inc/atiny_log.h
  7. 146 0
      iot_link/inc/dtls_al.h
  8. 74 0
      iot_link/inc/link_endian.h
  9. 183 0
      iot_link/inc/link_list.h
  10. 154 0
      iot_link/inc/link_log.h
  11. 44 0
      iot_link/inc/link_version.h
  12. 345 0
      iot_link/inc/mqtt_al.h
  13. 108 0
      iot_link/inc/shell.h
  14. 114 0
      iot_link/inc/stimer.h
  15. 27 0
      iot_link/link_log/BUILD.gn
  16. 106 0
      iot_link/link_log/link_log.c
  17. 29 0
      iot_link/link_misc/BUILD.gn
  18. 255 0
      iot_link/link_misc/link_misc.h
  19. 69 0
      iot_link/link_misc/link_random.c
  20. 210 0
      iot_link/link_misc/link_ring_buffer.c
  21. 259 0
      iot_link/link_misc/link_string.c
  22. 46 0
      iot_link/link_misc/link_time.h
  23. 49 0
      iot_link/network/dtls/BUILD.gn
  24. 143 0
      iot_link/network/dtls/dtls_al/dtls_al.c
  25. 552 0
      iot_link/network/dtls/mbedtls/mbedtls_port/dtls_interface.c
  26. 169 0
      iot_link/network/dtls/mbedtls/mbedtls_port/dtls_interface.h
  27. 159 0
      iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config.h
  28. 250 0
      iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_cert.h
  29. 250 0
      iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_cert.h.bak
  30. 293 0
      iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_dtls.h
  31. 246 0
      iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_psk.h
  32. 209 0
      iot_link/network/dtls/mbedtls/mbedtls_port/mbed_port.c
  33. 101 0
      iot_link/network/dtls/mbedtls/mbedtls_port/timing_alt.c
  34. 97 0
      iot_link/network/dtls/mbedtls/mbedtls_port/timing_alt.h
  35. 58 0
      iot_link/network/mqtt/BUILD.gn
  36. 213 0
      iot_link/network/mqtt/mqtt_al/mqtt_al.c
  37. 22 0
      iot_link/network/mqtt/paho_mqtt/Readme.md
  38. 184 0
      iot_link/network/mqtt/paho_mqtt/paho/.cproject
  39. 8 0
      iot_link/network/mqtt/paho_mqtt/paho/.gitignore
  40. 26 0
      iot_link/network/mqtt/paho_mqtt/paho/.project
  41. 163 0
      iot_link/network/mqtt/paho_mqtt/paho/.settings/org.eclipse.cdt.core.prefs
  42. 3 0
      iot_link/network/mqtt/paho_mqtt/paho/.settings/org.eclipse.cdt.ui.prefs
  43. 29 0
      iot_link/network/mqtt/paho_mqtt/paho/.travis.yml
  44. 46 0
      iot_link/network/mqtt/paho_mqtt/paho/CMakeLists.txt
  45. 66 0
      iot_link/network/mqtt/paho_mqtt/paho/CONTRIBUTING.md
  46. 45 0
      iot_link/network/mqtt/paho_mqtt/paho/Debug/makefile
  47. 8 0
      iot_link/network/mqtt/paho_mqtt/paho/Debug/objects.mk
  48. 18 0
      iot_link/network/mqtt/paho_mqtt/paho/Debug/sources.mk
  49. 4 0
      iot_link/network/mqtt/paho_mqtt/paho/Debug/src/MQTTDeserializeConnect.d
  50. 48 0
      iot_link/network/mqtt/paho_mqtt/paho/Debug/src/subdir.mk
  51. 21 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/CMakeLists.txt
  52. 17 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/CMakeLists.txt
  53. 95 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/FreeRTOS/MQTTEcho.c
  54. 24 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/linux/CMakeLists.txt
  55. 3 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/linux/build.sh
  56. 254 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/linux/stdoutsub.c
  57. 30 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/CMakeLists.txt
  58. 241 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/FreeRTOS/MQTTFreeRTOS.c
  59. 72 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/FreeRTOS/MQTTFreeRTOS.h
  60. 952 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/MQTTClient.c
  61. 256 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/MQTTClient.h
  62. 196 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/cc3200/MQTTCC3200.c
  63. 58 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/cc3200/MQTTCC3200.h
  64. 166 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/linux/MQTTLinux.c
  65. 74 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/linux/MQTTLinux.h
  66. 20 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/test/CMakeLists.txt
  67. 1050 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/test/test1.c
  68. 21 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/CMakeLists.txt
  69. 17 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/CMakeLists.txt
  70. 131 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/arduino/Hello/Hello.ino
  71. 31 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/CMakeLists.txt
  72. 3 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/build.sh
  73. 104 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/hello.cpp
  74. 291 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/main.cpp
  75. 265 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/stdoutsub.cpp
  76. 208 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/FP.h
  77. 1046 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/MQTTClient.h
  78. 55 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/MQTTLogging.h
  79. 57 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/arduino/Countdown.h
  80. 79 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/arduino/IPStack.h
  81. 69 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/arduino/WifiIPStack.h
  82. 213 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/linux/linux.cpp
  83. 40 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/mbed/MQTTEthernet.h
  84. 57 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/mbed/MQTTSocket.h
  85. 20 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/test/CMakeLists.txt
  86. 943 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/test/test1.cpp
  87. 21 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/CMakeLists.txt
  88. 37 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/CMakeLists.txt
  89. 3 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/build
  90. 267 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/ping_nb.c
  91. 285 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/pub0sub1_nb.c
  92. 122 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/transport.c
  93. 70 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/transport.h
  94. 6 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/build
  95. 4 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/null.c
  96. 142 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/ping.c
  97. 157 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/ping_nb.c
  98. 153 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/pub0sub1.c
  99. 158 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/pub0sub1_nb.c
  100. 76 0
      iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/qos0pub.c

+ 24 - 0
iot_link/BUILD.gn

@@ -0,0 +1,24 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# 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.
+
+group("iot_link") {
+    deps = [
+        "inc:inc",
+        "link_log:link_log",
+        "link_misc:link_misc",
+        "network/dtls:dtls",
+        "network/mqtt:mqtt",
+        "oc_mqtt:oc_mqtt",
+        "queue:queue"
+    ]
+}

+ 24 - 0
iot_link/LICENSE

@@ -0,0 +1,24 @@
+ * Copyright (c) <2013-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+

+ 8 - 0
iot_link/README.md

@@ -0,0 +1,8 @@
+## SDK简介
+iot_link是连接华为云IoTDA平台的SDK,SDK提供端云协同能力,集成了MQTT、LwM2M、CoAP、mbedtls、LwIP 全套 IoT 互联互通协议栈,且在这些协议栈的基础上,提供了开放 API,用户只需关注自身的应用,而不必关注协议内部实现细节,直接使用SDK封装的API,通过连接、数据上报、命令接收和断开四个步骤就能简单快速地实现与华为IoTDA平台的安全可靠连接。使用SDK,用户可以大大减少开发周期,聚焦自己的业务开发,快速构建自己的产品。
+
+## 开源协议
+
+* 遵循BSD-3开源许可协议
+* [Huawei LiteOS 知识产权政策](http://developer.huawei.com/ict/cn/site-iot/article/iot-intellectual-property-rights)
+

+ 24 - 0
iot_link/bundle.json

@@ -0,0 +1,24 @@
+{
+    "name": "@bearpi/hm_nano_iot_link",
+    "version": "1.0.1",
+    "description": "iot_link",
+    "publishAs": "code-segment",
+    "scripts": {
+        "install": "DEST_PATH=${DEP_BUNDLE_BASE}/third_party/iot_link && mkdir -p $DEST_PATH && cp -r ./* $DEST_PATH"
+    },
+    "keywords": [
+        "bearpi",
+        "iotlink"
+    ],
+    "author": {},
+    "repository": "",
+    "license": "BSD-3-Clause License",
+    "tags": [
+        "third_party"
+    ],
+    "ohos": {
+        "os": "0.0.1",
+        "kernel": "",
+        "board": ""
+    }
+}

+ 23 - 0
iot_link/inc/BUILD.gn

@@ -0,0 +1,23 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# 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.
+
+static_library("inc") {
+
+    
+    cflags = [ "-Wno-unused-variable" ]
+    cflags += [ "-Wno-unused-but-set-variable" ]
+    include_dirs = [
+        "../inc",
+        "//kernel/liteos_m/components/cmsis/2.0",
+    ]
+}

+ 77 - 0
iot_link/inc/atiny_log.h

@@ -0,0 +1,77 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+#ifndef ATINY_LOG_H
+#define ATINY_LOG_H
+
+#include <link_log.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOG_DEBUG             EN_LINK_LOG_LEVEL_DEBUG
+#define LOG_INFO              EN_LINK_LOG_LEVEL_INFO
+#define LOG_WARNING           EN_LINK_LOG_LEVEL_WARN
+#define LOG_ERR               EN_LINK_LOG_LEVEL_ERROR
+#define LOG_FATAL             EN_LINK_LOG_LEVEL_FATAL
+
+/**
+ * @brief: you could use this as the main printf for your own log
+ *
+ *       :the input parameters is just as the printf does, and this function should be deserted
+ *       :this function should not use as advised
+ * */
+
+//#define CONFIG_ATINY_DEUG
+
+#ifdef CONFIG_ATINY_DEUG
+
+#define ATINY_LOG     LINK_LOG
+
+#else
+
+#define ATINY_LOG(level,fmt, ...)
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+

+ 146 - 0
iot_link/inc/dtls_al.h

@@ -0,0 +1,146 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-10-17 19:50  zhangqianfu  The first version
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_NETWORK_DTLS_DTLS_AL_DTLS_AL_H_
+#define LITEOS_LAB_IOT_LINK_NETWORK_DTLS_DTLS_AL_DTLS_AL_H_
+
+
+#include <stdint.h>
+#include <stddef.h>
+
+typedef enum
+{
+    EN_DTLS_AL_ERR_OK = 0,
+    EN_DTLS_AL_ERR_PARA,
+    EN_DTLS_AL_ERR_SYS,
+    EN_DTLS_AL_ERR_SYSMEM,
+    EN_DTLS_AL_ERR_NOCONFIG,
+    EN_DTLS_AL_ERR_NETWORK,
+    EN_DTLS_AL_ERR_SERVERCERTPARSE,
+    EN_DTLS_AL_ERR_CLIENTCERTPARSE,
+    EN_DTLS_AL_ERR_CLIENTPKPARSE,
+}en_dtls_al_err_t;
+
+/** @brief  this enum all the transport encode we support now*/
+typedef enum
+{
+    EN_DTLS_AL_SECURITY_TYPE_NONE = 0,   ///< no encode
+    EN_DTLS_AL_SECURITY_TYPE_PSK,        ///< use the psk mode in transport layer
+    EN_DTLS_AL_SECURITY_TYPE_CERT,       ///< use the ca mode in transport layer,only check the server
+}en_dtls_al_security_type_t;
+
+/** @brief this data defines for the psk mode*/
+typedef struct
+{
+    uint8_t     *psk_id;           ///< the psk id
+    uint8_t     *psk_key;          ///< the psk key
+    int          psk_id_len;       ///< the psk id length
+    int          psk_key_len;      ///< the psk key length
+}dtls_al_security_psk_t;
+
+
+/** @brief this data defines for the cas mode:only check the server  */
+typedef struct
+{
+    uint8_t    *server_ca;
+    uint8_t    *client_ca;
+    uint8_t    *client_pk;
+    uint8_t    *client_pk_pwd;
+    int         server_ca_len;
+    int         client_ca_len;
+    int         client_pk_len;
+    int         client_pk_pwd_len;
+    char       *server_name;
+}dtls_al_security_cert_t;
+
+
+/** @brief this data defines for the encode parameter for the connect */
+typedef struct
+{
+    en_dtls_al_security_type_t    type;         ///< which security type of the data
+    union
+    {
+        dtls_al_security_psk_t     psk;         ///< psk data  if the type is EN_DTSL_SECURITY_TYPE_PSK
+        dtls_al_security_cert_t    cert;         ///< cert data  if the type is EN_DTSL_SECURITY_TYPE_CERT
+    }u;
+}dtls_al_security_t;
+
+typedef struct
+{
+    int                 istcp;
+    int                 isclient;
+    dtls_al_security_t  security;
+}dtls_al_para_t;
+
+en_dtls_al_err_t  dtls_al_new(dtls_al_para_t *para,void **handle);
+int   dtls_al_connect(void *handle,const char *ip, const char *port, int timeout );
+int   dtls_al_write(void *handle, uint8_t *msg, size_t len, int timeout );
+int   dtls_al_read(void *handle,uint8_t *buf, size_t len,int timeout );
+en_dtls_al_err_t   dtls_al_destroy(void *handle);
+
+typedef en_dtls_al_err_t (*fn_dtls_al_new)(dtls_al_para_t *para,void **handle);
+typedef int (*fn_dtls_al_connect)(void *handle,const char *server_ip, const char *server_port,int timeout);
+typedef int (*fn_dtls_al_write)(void *handle,uint8_t *msg, size_t len, int timeout);
+typedef int (*fn_dtls_al_read)(void *handle, uint8_t *buf, size_t len, int timeout);
+typedef en_dtls_al_err_t (*fn_dtls_al_destroy)(void *handle);
+
+typedef struct
+{
+    fn_dtls_al_new            io_new;
+    fn_dtls_al_connect        io_connect;
+    fn_dtls_al_write          io_write;
+    fn_dtls_al_read           io_read;
+    fn_dtls_al_destroy        io_destroy;
+}dtls_al_io_t;
+
+typedef struct
+{
+    const char     *name;
+    dtls_al_io_t    io;
+}dtls_al_t;
+
+int dtls_al_install(const dtls_al_t *dtls);
+int dtls_al_uninstall(const char*name);
+
+///< this function should implemented by the developer of the tls
+int dtls_imp_init(void);
+int dtls_al_init(void) ;  ///< this function will call dtls_imp_init()
+
+
+
+#endif /* LITEOS_LAB_IOT_LINK_NETWORK_DTLS_DTLS_AL_DTLS_AL_H_ */

+ 74 - 0
iot_link/inc/link_endian.h

@@ -0,0 +1,74 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-07-09 14:28  zhangqianfu  The first version
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_INC_LINK_ENDIAN_H_
+#define LITEOS_LAB_IOT_LINK_INC_LINK_ENDIAN_H_
+
+
+//define the normal addres function
+#define swaps(value) ((((value)&((uint16_t)0xff00))>>8)|(((value)&((uint16_t)0x00ff))<<8))
+
+#define swapl(value)  ((((value)&((uint32_t)0xff000000))>>24)|(((value)&((uint32_t)0xff0000))>>8)|\
+                      (((value)&((uint32_t)0xff00))<<8)|(((value)&((uint32_t)0xff))<<24))
+
+
+#define htoles(value)  (value)
+#define htolel(value)  (value)
+#define htobes(value)  swaps(value)
+#define htobel(value)  swapl(value)
+
+
+#ifndef htons
+#define htons      htobes      //translate the host endian to network endian (2 Bytes)
+#endif
+
+#ifndef htonl
+#define htonl      htobel      //translate the host endian to network endian (4 Bytes)
+#endif
+
+#ifndef ntohs
+#define ntohs      htobes      //translate the network endian to host endian (2 Bytes)
+#endif
+
+#ifndef ntohl
+#define ntohl      htobel      //translate the network endian to host endian (4 Bytes)
+#endif
+
+
+
+#endif /* LITEOS_LAB_IOT_LINK_INC_LINK_ENDIAN_H_ */

+ 183 - 0
iot_link/inc/link_list.h

@@ -0,0 +1,183 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2020-04-22 17:08  zhangqianfu  The first version
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_INC_LINK_LIST_H_
+#define LITEOS_LAB_IOT_LINK_INC_LINK_LIST_H_
+
+
+#include <stdint.h>
+#include <stddef.h>
+
+
+///< this is common double-list , and you could implement the one yourself
+
+/*
+ * you could add the node to the data entry like
+ *
+ * struct {
+ *
+ *  link_node_t node;
+ *
+ *  xxx value;
+ *
+ * }
+ *
+ *
+ * */
+
+typedef struct link_node
+{
+    struct link_node *nxt, *pre;
+}link_node_t;
+
+
+#define LINK_NODE_ENTRY(node, type, member)   \
+    ((type *)((char *)(node) - (size_t)&((type *)0)->member))
+
+typedef void (*fn_link_list_iterate)(link_node_t *node, void *args);
+
+
+typedef struct
+{
+    link_node_t root;
+}link_list_t;
+
+static inline void link_list_init(link_list_t *list)
+{
+    list->root.nxt  = &list->root;
+    list->root.pre =  &list->root;
+}
+
+static inline int link_list_isempty(link_list_t *list)
+{
+    return list->root.pre == &list->root?1:0;
+}
+
+static inline int link_list_ishead(link_list_t *list, link_node_t *node)
+{
+    return list->root.nxt == node?1:0;
+}
+
+static inline int link_list_istail(link_list_t *list, link_node_t *node)
+{
+    return list->root.pre == node?1:0;
+}
+
+///< insert the new_node before the old_node
+static inline void link_list_insert(link_node_t *old_node, link_node_t *new_node)
+{
+    new_node->pre = old_node->pre;
+    new_node->nxt = old_node;
+    new_node->pre->nxt = new_node;
+    old_node->pre = new_node;
+}
+
+static inline void link_list_addhead(link_list_t *list, link_node_t *node)
+{
+    link_list_insert(list->root.nxt,node);
+}
+
+static inline void link_list_addtail(link_list_t *list, link_node_t *node)
+{
+    link_list_insert(&list->root,node);
+}
+
+///< node could not bee root
+static inline void link_list_removenode( link_node_t *node)
+{
+    node->pre->nxt = node->nxt;
+    node->nxt->pre = node->pre;
+
+}
+
+static inline link_node_t *link_list_removehead(link_list_t *list)
+{
+    link_node_t *node = list->root.nxt;
+
+    link_list_removenode(node);
+
+    return node;
+}
+
+static inline link_node_t *link_list_removetail(link_list_t *list)
+{
+    link_node_t *node = list->root.pre;
+
+    link_list_removenode(node);
+
+    return node;
+}
+
+static inline void link_list_replace(link_node_t *new_node, link_node_t *old_node)
+{
+    new_node->nxt = old_node->nxt;
+    new_node->nxt->pre = new_node;
+    new_node->pre = old_node->pre;
+    new_node->pre->nxt = new_node;
+}
+
+#define LINK_LIST_FOREACH(node, list) \
+    for(node = (list)->root.nxt;   \
+        node != &(list)->root;     \
+        node = (node)->nxt )
+
+#define LINK_LIST_FOREACH_SAFE(node, tmp,list)  \
+        for(node = (list)->root.nxt, tmp = (node)->nxt;   \
+            node != &(list)->root;     \
+            node = tmp,tmp = (node)->nxt )
+
+static inline void link_list_iterate(link_list_t *list, fn_link_list_iterate fn_iterate, void *args)
+{
+    link_node_t *node;
+    LINK_LIST_FOREACH(node, list)
+    {
+        fn_iterate(node, args);
+    }
+}
+
+static inline void link_list_iteratesafe(link_list_t *list, fn_link_list_iterate fn_iterate, void *args)
+{
+    link_node_t *node;
+    link_node_t *tmp;
+    LINK_LIST_FOREACH_SAFE(node, tmp,list)
+    {
+        fn_iterate(node, args);
+    }
+}
+
+#endif /* LITEOS_LAB_IOT_LINK_INC_LINK_LIST_H_ */

+ 154 - 0
iot_link/inc/link_log.h

@@ -0,0 +1,154 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+#ifndef LITEOS_LAB_IOT_LINK_LINK_LOG_LINK_LOG_H_
+#define LITEOS_LAB_IOT_LINK_LINK_LOG_LINK_LOG_H_
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include "cmsis_os2.h"
+// #include <iot_link_config.h>
+/**
+ * @brief:this defines for the log module, and  LINK_LOG_TRACE/LINK_LOG_DEBUG will not participate the compile in the release version
+ *
+ *
+ * */
+typedef enum
+{
+    EN_LINK_LOG_LEVEL_TRACE = 0,    ///< this is used as the trace function,like the function enter and function out
+    EN_LINK_LOG_LEVEL_DEBUG,        ///< this is used as the debug, you could add any debug as you wish
+    EN_LINK_LOG_LEVEL_INFO,         ///< which means it is import message, and you should known
+    EN_LINK_LOG_LEVEL_WARN,      ///< this is used as the executed result,which means the status is not what we expected,but could accept
+    EN_LINK_LOG_LEVEL_ERROR,        ///< this is used as the executed result,which means the status is not what we expected,could not accepta
+    EN_LINK_LOG_LEVEL_FATAL,        ///< this is used as the parameters input for the api interface, which could not accepted
+    EN_LINK_LOG_LEVEL_MAX,
+}en_link_log_level_t;
+
+/**
+ * @brief:use this function to get the current output log
+ *
+ * @return: the current output mask log, defined by en_link_log_level_t
+ * */
+en_link_log_level_t link_log_level_get(void);
+
+/**
+ * @brief: use this function to get the debug level name
+ *
+ * @parameter[in]:level, the level to get
+ *
+ * @return: the mapped level name
+ * */
+const char *link_log_level_name(en_link_log_level_t level);
+
+/**
+ * @brief:use this function to set the current output log
+ *
+ *@parameter[in] level:defined by en_link_log_level_t
+ *
+ * @return: 0 success while -1 failed
+ * */
+int link_log_level_set(en_link_log_level_t level);
+
+
+/*
+ * @brief: this is a weak function ,and you could rewrite one
+ *
+ * @param fmt: same use as the fmt for printf
+ *
+ * @param unfixed: same use for printf
+ *
+ * @return: don't care about it
+ *
+ * @attention: and the components should not call this function directly, you'd better
+ *
+ *             call LINK_LOG groups
+ *
+ * */
+//__attribute__((weak)) void link_printf(const char *format, ...);
+
+#ifndef link_printf
+#define link_printf(fmt, ...) \
+    do \
+    { \
+        printf(fmt, ##__VA_ARGS__); \
+        \
+    }while(0)
+#endif
+
+// #ifdef CONFIG_LINKLOG_ENABLE
+
+#define osal_sys_time() (osKernelGetTickCount() * (1000 / 100))
+#define LINK_LOG(level,fmt, ...) \
+    do \
+    { \
+        link_printf("[%s][%u][%s] " fmt "\r\n", \
+        link_log_level_name((level)), (unsigned int)osal_sys_time(),__FUNCTION__, ##__VA_ARGS__); \
+    } while (0)
+
+#define LINK_LOG_TRACE(fmt, ...) \
+    do \
+    { \
+        if ((EN_LINK_LOG_LEVEL_TRACE) >= link_log_level_get()) \
+        { \
+            LINK_LOG(EN_LINK_LOG_LEVEL_TRACE,fmt,##__VA_ARGS__); \
+        } \
+    } while (0)
+
+#define LINK_LOG_DEBUG(fmt, ...) \
+    do \
+    { \
+        if ((EN_LINK_LOG_LEVEL_DEBUG) >= link_log_level_get()) \
+        { \
+            LINK_LOG(EN_LINK_LOG_LEVEL_DEBUG,fmt,##__VA_ARGS__); \
+        } \
+    } while (0)
+
+// #else
+
+// #define LINK_LOG(level,fmt, ...)
+// #define LINK_LOG_TRACE(fmt, ...)
+// #define LINK_LOG_DEBUG(fmt, ...)
+
+// #endif
+
+
+#define LINK_LOG_INFO(fmt, ...)   LINK_LOG(EN_LINK_LOG_LEVEL_INFO,fmt,##__VA_ARGS__)
+#define LINK_LOG_WARN(fmt, ...)   LINK_LOG(EN_LINK_LOG_LEVEL_WARN,fmt,##__VA_ARGS__)
+#define LINK_LOG_ERROR(fmt, ...)  LINK_LOG(EN_LINK_LOG_LEVEL_ERROR,fmt,##__VA_ARGS__)
+#define LINK_LOG_FATAL(fmt, ...)  LINK_LOG(EN_LINK_LOG_LEVEL_FATAL,fmt,##__VA_ARGS__)
+
+
+#endif /* LITEOS_LAB_IOT_LINK_LINK_LOG_LINK_LOG_H_ */

+ 44 - 0
iot_link/inc/link_version.h

@@ -0,0 +1,44 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-11-17 12:09  zhangqianfu  The first version  
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_INC_LINK_VERSION_H_
+#define LITEOS_LAB_IOT_LINK_INC_LINK_VERSION_H_
+
+const char *linkmain_version();
+
+#endif /* LITEOS_LAB_IOT_LINK_INC_LINK_VERSION_H_ */

+ 345 - 0
iot_link/inc/mqtt_al.h

@@ -0,0 +1,345 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+#ifndef MQTT_AL_H
+#define MQTT_AL_H
+
+#include <stdint.h>
+#include <dtls_al.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/** brief defines for all the ascii or data used in the mqtt engine */
+typedef struct
+{
+    char *data;      ///< buffer to storage the data
+    int   len;       ///< buffer data length
+}mqtt_al_string_t;   //used to represent any type string (maybe not ascii)
+
+///** @brief  this enum all the transport encode we support now*/
+//typedef enum
+//{
+//  en_mqtt_al_security_none = 0,    ///< no encode
+//  en_mqtt_al_security_psk,         ///< use the psk mode in transport layer
+//  en_mqtt_al_security_cas,         ///< use the ca mode in transport layer,only check the server
+//  en_mqtt_al_security_cacs,        ///< use the ca mode in transport layer,both check the server and client
+//  en_mqtt_al_security_end,         ///< the end for the mqtt
+//}en_mqtt_al_security_t;
+//
+///** @brief this data defines for the psk mode*/
+//typedef struct
+//{
+//  mqtt_al_string_t  psk_id;   ///< the psk id
+//  mqtt_al_string_t  psk_key;  ///< the psk key
+//}mqtt_al_security_psk_t;
+//
+///** @brief this data defines for the cas mode:only check the server  */
+//typedef struct
+//{
+//    mqtt_al_string_t  ca_crt;  ///<  the ca crt
+//}mqtt_al_security_cas_t;
+//
+//
+///** @brief this data defines for the cacs mode:both check the server and client */
+//typedef struct
+//{
+//  mqtt_al_string_t ca_s_crt;     ///< the server crt
+//  mqtt_al_string_t ca_c_crt;     ///< the client crt
+//  mqtt_al_string_t ca_c_key;     ///< the client ca key
+//  mqtt_al_string_t ca_host;      ///< for peer certificate, maybe they need this
+//}mqtt_al_security_cacs_t;
+//
+///** @brief this data defines for the encode parameter for the connect */
+//typedef struct
+//{
+//  en_mqtt_al_security_t type;         ///< which security type of the data
+//    union
+//    {
+//      mqtt_al_security_psk_t   psk;   ///< psk data  if the type is en_mqtt_security_psk
+//      mqtt_al_security_cas_t   cas;   ///< cas data  if the type is en_mqtt_security_cas
+//      mqtt_al_security_cacs_t  cacs;  ///< cacs data if the type is en_mqtt_security_cacs
+//    }u;
+//}mqtt_al_security_para_t;
+
+/** @brief enum all the qos supported for the application */
+typedef enum
+{
+    en_mqtt_al_qos_0 = 0,     ///< mqtt QOS 0
+    en_mqtt_al_qos_1,         ///< mqtt QOS 1
+    en_mqtt_al_qos_2,         ///< mqtt QOS 2
+    en_mqtt_al_qos_err
+}en_mqtt_al_qos_t;
+
+/** @brief defines the parameter used for the will message used in connect */
+typedef struct
+{
+    mqtt_al_string_t  topic;    ///< will topic
+    mqtt_al_string_t  msg;      ///< will message
+    en_mqtt_al_qos_t  qos;      ///< will message qos
+    int               retain;   ///< will message retain or not:1 retain while 0 not
+}mqtt_al_willmsg_t;
+
+/** @brief enum the mqtt version*/
+typedef enum
+{
+    en_mqtt_al_version_3_1_0 = 0,
+    en_mqtt_al_version_3_1_1,
+}en_mqtt_al_verison;
+
+
+
+/** @brief defines the paramter for the mqtt connect */
+typedef struct
+{
+    mqtt_al_string_t               serveraddr;   ///< mqtt server:support domain name and dot format
+    int                            serverport;   ///< mqtt server port
+    dtls_al_security_t            *security;     ///< if NULL,will use en_mqtt_security_none
+    en_mqtt_al_verison             version;      ///< mqtt version will be used
+    mqtt_al_string_t               clientid;     ///< mqtt connect client identifier
+    mqtt_al_string_t               user;         ///< mqtt connect user
+    mqtt_al_string_t               passwd;       ///< mqtt connect pwd
+    int                            cleansession; ///< 1 clean the session while 0 not
+    mqtt_al_willmsg_t             *willmsg;      ///< mqtt connect will message
+    unsigned short                 keepalivetime;///< keep alive time
+    char                           conret;       ///< mqtt connect code, return by server
+    int                            timeout;      ///< how much time will be blocked
+}mqtt_al_conpara_t;
+
+/** @brief defines for the mqtt publish */
+typedef struct
+{
+    mqtt_al_string_t    topic;    ///< selected publish topic
+    mqtt_al_string_t    msg;      ///< message to be published
+    en_mqtt_al_qos_t    qos;      ///< message qos
+    int                 retain;   ///< message retain :1 retain while 0 not
+    int                 timeout;  ///< how much time will blocked
+}mqtt_al_pubpara_t;
+
+
+/** @brief  defines for the message will be passed to the application dealer*/
+typedef struct
+{
+    mqtt_al_string_t       topic; ///< message topic
+    mqtt_al_string_t       msg;   ///< the topic message payload
+    en_mqtt_al_qos_t       qos;   ///< message qos
+    int                    dup;   ///< message dup times
+    int                    retain;///< retain or not
+}mqtt_al_msgrcv_t;
+
+/** @brief  defines the mqtt received message dealer, called by mqtt engine*/
+typedef void (*fn_mqtt_al_msg_dealer)(void *arg,mqtt_al_msgrcv_t *msg);
+
+/** @brief defines the mqtt subscribe parameter*/
+typedef struct
+{
+    mqtt_al_string_t       topic;     ///< topic will be subscribe
+    en_mqtt_al_qos_t       qos;       ///< qos requested
+    fn_mqtt_al_msg_dealer  dealer;    ///< message dealer:used to deal the received message
+    void                  *arg;       ///< used for the message dealer
+    char                   subret;    ///< subscribe result code
+    int                    timeout;   ///< how much time will be blocked
+}mqtt_al_subpara_t;
+
+/** @brief defines the mqtt unsubscribe parameter*/
+typedef struct
+{
+    mqtt_al_string_t       topic;    ///< the unsubscribe topic
+    uint32_t               timeout;  ///< how much time will be blocked
+}mqtt_al_unsubpara_t;
+
+/** @brief  descript the mqtt engine status */
+typedef enum
+{
+    en_mqtt_al_connect_ok     = 0,      ///< which means the mqtt is ok and could supply the service
+    en_mqtt_al_connect_err,             ///< the mqtt no start or connect err
+}en_mqtt_al_connect_state;
+
+/** @brief defines for the mqtt connect code returned by the server */
+#define cn_mqtt_al_con_code_ok                0   ///< has been accepted by the server
+#define cn_mqtt_al_con_code_err_version       1   ///< server not support the version
+#define cn_mqtt_al_con_code_err_clientID      2   ///< client identifier is error
+#define cn_mqtt_al_con_code_err_netrefuse     3   ///< server service not ready yet
+#define cn_mqtt_al_con_code_err_u_p           4   ///< bad user name or pwd
+#define cn_mqtt_al_con_code_err_auth          5   ///< the client is not authorized
+#define cn_mqtt_al_con_code_err_unkown        -1  ///< unknown reason
+#define cn_mqtt_al_con_code_err_network      0x80 ///< network reason,you could try once more
+
+
+/** @brief defines for the mqtt subscribe code returned by the server */
+#define cn_mqtt_al_sub_code_qos0      0     ///< success and max qos is QOS 0
+#define cn_mqtt_al_sub_code_qos1      1     ///< success and max qos is QOS 1
+#define cn_mqtt_al_sub_code_qos2      2     ///< success and max qos is QOS 2
+#define cn_mqtt_al_sub_code_err       0x80  ///< subscribe failure
+
+/**
+ *@brief defines the operation will be registered  to the mqtt service
+ *@brief parameter and return code refere to the corresponding api
+ *
+ */
+typedef struct
+{
+//  ///< the mqtt init function
+//  int  (*  init)      (void);
+//  ///< the mqtt deinit function
+//  int   (* deinit)    (void );  ---TODO, have a thought if we really need it
+    ///< connect to the server
+    void* (* connect)   (mqtt_al_conpara_t *param);
+    ///< disconnect from the server
+    int    (* disconnect)(void *handle );
+    ///< publish a message to the server
+    int    (* publish)    (void *handle, mqtt_al_pubpara_t *msg);
+    ///< subscribe a topic to the server
+    int    (* subscribe)   (void *handle, mqtt_al_subpara_t *subpara);
+    ///< unsubscribe a topic to the server
+    int    (* unsubscribe) (void *handle, mqtt_al_unsubpara_t *unsubpara);
+    ///< check the mqtt engine status
+    en_mqtt_al_connect_state (* check_status) (void *handle);
+
+}mqtt_al_op_t;
+
+
+//////////////////////API USED FOR THE MQTT APPLICAITON/////////////////////////
+
+/**
+ * @brief maybe the mqtt lib need do some initialize
+ *
+ * @return 0 success while -1 failed
+ *
+ */
+int mqtt_al_init(void);
+
+/**
+ * @brief     :when you don't want to use the mqtt service ,please call this function
+ *
+ * @return 0 success while -1 failed
+ */
+int  mqtt_al_deinit(void);
+/**
+ *@brief: you could use this function to connect to the mqtt server
+ *
+ *@param[in] conparam  the parameter we will use in connect, refer to the data mqtt_al_conpara_t
+ *@
+ *@return: first you should check the return value then the return code in conparam
+ *
+ *@retval NULL which means you could not get the connect to the server,maybe network reason
+ *@retval handle, which means you get the context, please check the conparam for more
+ */
+void * mqtt_al_connect( mqtt_al_conpara_t *conparam);
+
+/**
+ * @brief  : you could use this function to disconnect from the mqtt server
+ *
+ * @param[in] handle  the handle we get from mqtt_al_connect
+
+ * @return  0 success -1 failed
+
+ */
+int mqtt_al_disconnect(void *handle);
+
+
+/**
+ * @brief you could use this function to publish a message to the server
+ *
+ * @param[in] handle the handle we get from mqtt_al_connect
+ *
+ * @param[in] msg  the message we will publish, see the data mqtt_al_pubpara_t
+ *
+ * @return 0 success  -1  failed
+ *
+ */
+int mqtt_al_publish(void *handle, mqtt_al_pubpara_t *pubpara);
+
+/**
+ * @brief you could use this function subscribe a topic from the server
+ *
+ * @param[in] handle the handle we get from mqtt_al_connect
+ *
+ * @param[in] subpara  refer to the data mqtt_al_subpara_t
+ *
+ * @return 0 success  -1  failed
+ *
+ */
+int mqtt_al_subscribe(void *handle, mqtt_al_subpara_t *subpara);
+
+/**
+ * @brief you could use this function unsubscribe a topic from the server
+ *
+ * @param[in] handle the handle we get from mqtt_al_connect
+ *
+ * @param[in] unsubpara  refer to the data mqtt_al_unsubpara_t
+ *
+ * @return 0 success  -1  failed
+ *
+ */
+int mqtt_al_unsubscribe(void *handle, mqtt_al_unsubpara_t *unsubpara);
+
+/**
+ *  @brief the mqtt engine state now
+ *
+ *  @param[in]  handle the handle we get from mqtt_al_connect
+ *
+ *  @return refer to  en_mqtt_al_connect_state
+ */
+en_mqtt_al_connect_state mqtt_al_check_status(void *handle);
+
+//////////////////////API USED FOR THE MQTT IMPLEMENT/////////////////////////
+
+/**
+ *@brief the mqtt lib should call this function to register its implement as a service
+ *
+ *@param[in] op  refer to the data  mqtt_al_op_t
+ *
+ *@return 0 success while -1 failed
+ *
+ */
+int mqtt_al_install(mqtt_al_op_t *op);
+/**
+ *@brief call this function to unregister the mqtt service
+ *
+ *@param[in] op  refer to the data  mqtt_al_op_t
+ *
+ *@return 0 success while -1 failed
+ *
+ */
+int mqtt_al_uninstall(void);
+
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* MQTT_AL_H */

+ 108 - 0
iot_link/inc/shell.h

@@ -0,0 +1,108 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-05-14 17:22  zhangqianfu  The first version
+ *
+ */
+
+#ifndef __OSSHELL_H
+#define __OSSHELL_H
+
+
+#include <stdint.h>
+#include <stddef.h>
+#include <link_log.h>
+
+#if CONFIG_SHELL_ENABLE
+
+//this is a shell module designed for the os
+//this is a shell type,maybe a command or the data variables
+enum en_os_shell_type
+{
+	EN_OSSHELL_CMD = 0,
+	EN_OSSHELL_VAR,       //up till now, we only support 4 bytes
+	EN_OSSHELL_LAST,
+};
+
+#define BUILD_VAR_NAME(A,B)         A##B
+#define  MAX_TAB_MATCHES			16
+struct shell_tab_matches
+{
+	const char *matches[MAX_TAB_MATCHES];
+	unsigned short len;
+};
+
+//this is the shell function module.the register function must have the same type
+//uptils now, we don't care the return value
+struct shell_item_t
+{
+	const char     *name;   //point to the shell name string
+	const char     *help;   //point to the shell description string
+	void           *addr;   //point to the shell function or the shell data
+	unsigned short  type;   //used to  point the shell type:command or a data
+	unsigned short  len;    //used to  point the shell command or data length
+};
+//this define will create  a shell command with the specified cmdname
+#define OSSHELL_EXPORT_CMD(cmdentry,cmdname,cmdhelp)      \
+    static const struct shell_item_t BUILD_VAR_NAME(__oshell_,cmdentry) __attribute__((used,section("oshell")))= \
+    {                           \
+        .name=cmdname,    \
+        .help=cmdhelp,    \
+        .addr=(void *)&cmdentry,              \
+		.type=EN_OSSHELL_CMD,           \
+		.len = sizeof(void *),             \
+    }
+//this define will create  a create a shell data with the specified name
+#define OSSHELL_EXPORT_VAR(var,varname,varhelp)      \
+    static const struct shell_item_t BUILD_VAR_NAME(__oshell_,var) __attribute__((used,section("oshell")))= \
+    {                           \
+        .name=varname,    \
+        .help=varhelp,    \
+        .addr=(void *)&var,              \
+		.type=EN_OSSHELL_VAR,                   \
+		.len =sizeof(var),               \
+    }
+    
+void shell_init(void);
+#else
+
+#define OSSHELL_EXPORT_CMD(cmdentry,cmdname,cmdhelp)
+#define OSSHELL_EXPORT_VAR(var,varname,varhelp)
+#define shell_init()
+
+#endif   //end for the shell_config
+
+
+#endif /* __OSSHELL_H */

+ 114 - 0
iot_link/inc/stimer.h

@@ -0,0 +1,114 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-07-26 18:05  zhangqianfu  The first version
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_STIMER_STIMER_H_
+#define LITEOS_LAB_IOT_LINK_STIMER_STIMER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+////////////////DEFINES FOR THE STIMER HEADER///////////////////////////////////
+///< defines for the soft timer operation method,you could use it with the stimer_ioctl function
+typedef enum
+{
+    en_stimer_opt_stop = 0,   ///< stop the soft timer
+    en_stimer_opt_start,      ///< start the soft timer
+    en_stimer_opt_gettime,    ///< get the left time
+    en_stimer_opt_recycle,    ///< reset the cycle
+    en_stimer_opt_reflag,     ///< reset the flag
+}en_stimer_opt_t;
+
+///< defines for the soft timer handle returned by the create function and used for ioctl and delete function
+///< the user should never supposed any data structure for the handle, you could only use the api supplied
+typedef void* stimer_t;
+
+///< defines for the flag when create the soft timer
+#define cn_stimer_flag_once  (1<<0)
+#define cn_stimer_flag_start (1<<1)
+///< define the soft timer interrupt service function
+typedef void  (*fn_stimer_handler)(void *arg);
+
+
+/**
+ * @brief: this function used for initialize the timer component, should be called after the os
+ *
+ * @return: 0 success while -1 failed
+ * */
+int32_t stimer_init();
+
+/**
+ * @brief: you could use this function for create a soft timer as you wished
+ *
+ * @param[in]:name, the soft timer name
+ * @param[in]:handler, the soft timer handler when the timer is activated
+ * @param[in]:arg, the argument will supplied for the handler
+ * @param[in]:cycle, the soft timer cycle
+ * @param[in]:flag, you could use cn_stimer_flag_once or cn_stimer_flag_start or both
+ *
+ * @return:soft timer handler, you could use it for ioctl or delete;if failed NULL
+ *         will be returned
+ *
+ * */
+stimer_t stimer_create(const char *name,fn_stimer_handler handler, \
+                                 void *arg,uint32_t cycle,uint32_t flag);
+
+/**
+ * @brief: you could use this function to delete the soft timer you created
+ *
+ * @param[in]:timer handler,returned by the create function
+ *
+ * @return:0 success while -1 or others failed
+ *
+ * */
+int32_t       stimer_delete(stimer_t timer);
+
+/**
+ * @brief: you could use this function to control the function
+ *
+ * @param[in]:timer,returned by the create function
+ * @param[in]:opt,defined by en_stimer_opt_t, and the arg is corresponding parameters
+ * @param[in]:arg, corresponding to the opt
+ *
+ * @return:0 success while -1 or others failed
+ *
+ * */
+int32_t       stimer_ioctl(stimer_t timer,en_stimer_opt_t opt, void *arg);
+
+
+
+#endif /* LITEOS_LAB_IOT_LINK_STIMER_STIMER_H_ */

+ 27 - 0
iot_link/link_log/BUILD.gn

@@ -0,0 +1,27 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# 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.
+
+static_library("link_log") {
+    sources = [
+        "link_log.c",
+    ]
+    
+    cflags = [ "-Wno-unused-variable" ]
+    cflags += [ "-Wno-unused-but-set-variable" ]
+    include_dirs = [
+        "../link_log",
+        "../inc",
+        "//kernel/liteos_m/components/cmsis/2.0",
+    ]
+
+}

+ 106 - 0
iot_link/link_log/link_log.c

@@ -0,0 +1,106 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-12-19 14:34  zhangqianfu  The first version
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <link_log.h>
+
+static en_link_log_level_t s_link_log_level = EN_LINK_LOG_LEVEL_TRACE;
+static const char *s_link_log_names[] =
+{
+    "TRACE",
+    "DEBUG",
+    "INFO ",
+    "WARN ",
+    "ERROR",
+    "FATAL"
+};
+
+int link_log_level_set(en_link_log_level_t level)
+{
+    int ret = -1;
+    if(level < EN_LINK_LOG_LEVEL_MAX )
+    {
+        s_link_log_level = level;
+        ret = 0;
+    }
+    return ret;
+}
+
+en_link_log_level_t link_log_level_get(void)
+{
+    return s_link_log_level;
+}
+
+const char *link_log_level_name(en_link_log_level_t log_level)
+{
+    if (log_level >= EN_LINK_LOG_LEVEL_MAX)
+    {
+        return "NULL ";
+    }
+    else
+    {
+        return s_link_log_names[log_level];
+    }
+
+}
+
+/*
+
+#ifndef CONFIG_LINK_LOGBUF_LEN
+#define CONFIG_LINK_LOGBUF_LEN      256  ///< you could modify it
+#endif
+
+__attribute__((weak)) void link_printf(const char *format, ...)
+{
+    char str_buf[CONFIG_LINK_LOGBUF_LEN] = {0};
+    va_list list;
+
+    (void) (void) memset(str_buf, 0, CONFIG_LINK_LOGBUF_LEN);
+
+    va_start(list, format);
+    (void) vsnprintf(str_buf, sizeof(str_buf), format, list);
+    va_end(list);
+
+    (void) printf("%s", str_buf);
+
+    return;
+}
+
+*/

+ 29 - 0
iot_link/link_misc/BUILD.gn

@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# 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.
+
+
+static_library("link_misc") {
+    sources = [
+        "link_random.c",
+        "link_ring_buffer.c",
+        "link_string.c",
+    ]
+    
+    cflags = [ "-Wno-unused-variable" ]
+    cflags += [ "-Wno-unused-but-set-variable" ]
+    include_dirs = [
+        "../link_misc",
+        "//kernel/liteos_m/components/cmsis/2.0",
+    ]
+
+}

+ 255 - 0
iot_link/link_misc/link_misc.h

@@ -0,0 +1,255 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-04-29 10:10  zhangqianfu  The first version  
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_LINK_MISC_LINK_MISC_H_
+#define LITEOS_LAB_IOT_LINK_LINK_MISC_LINK_MISC_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+/**
+ * @brief:use this function to make a string to argc and args mode
+ *
+ * @param[in/out]:argc, how many buffer in the argc
+ *
+ * @param[in/out]:argv, the buffer for the args
+ *
+ * @param[in]:string, the string to be format
+ *
+ *
+ * @return:how many parameters in the string
+ *
+ * */
+int string_buffer_to_arg(int *argc, const char *argv[],char *string);
+
+/**
+ *
+ * @brief: use this function to clone a string
+ *
+ * @param[in]: source string
+ *
+ * @return: the clone string
+ *
+ * */
+
+char *osal_strdup(const char *ch);
+
+
+
+/**
+ *
+ *                       dataoff
+ * ring buffer map:       |  ----datalen-------
+ *                        | /                   \
+ *                        |/                     \
+ *   ----------------------------------------------------------
+ *   |     empty space    |//////valid data///////|           |
+ *   ----------------------------------------------------------
+ *   | \                                                      /
+ *   |  \                                                    /
+ *   |   \                                                  /
+ *   |     ---------------buflen--------------------------
+ *  buf
+ *
+ *  attention that do dump read or write means no data will really write or read,
+ *  it only changed the dataoff or datalen, and you make sure that the dump read
+ *  or write length  is legal
+ *
+ * */
+
+/**
+ * @brief: this is the ring buffer data structure, implement as the common function
+ *
+ * */
+typedef struct
+{
+    unsigned char   *buf;      ///< which means the buffer
+    int              buflen;   ///< which means the buffer limit
+    int              datalen;  ///< which means how many data in the buffer
+    int              dataoff;  ///< which means the valid data offset in the buffer
+}tag_ring_buffer_t;
+
+typedef tag_ring_buffer_t  ring_buffer_t;
+
+/**
+ * @brief:use this function to make a new ring handle
+ *
+ * @param[in]:ring,which will be initialized
+ *
+ * @param[in]:buf, which will be used as the cache for the ring
+ *
+ * @param[in]:buflen, the length of buf
+ *
+ * @param[in]:offset, the initialize data offset
+ *
+ * @param[in]:datalen, the initialize data length
+ *
+ * @return: 0 success while -1 failed
+ *
+ * */
+
+
+int ring_buffer_init(tag_ring_buffer_t *ring,unsigned char *buf, int buflen,int offset,int datalen);
+
+
+
+/**
+ * @brief:use this function to write data to the ring buffer
+ *
+ * @param[in]:ring,which will be written
+ *
+ * @param[in]:buf, the data buffer
+ *
+ * @param[in]:len, the buffer length
+ *
+ * @return: how many bytes has been written while -1 means failed
+ *
+ * */
+int ring_buffer_write(tag_ring_buffer_t *ring,unsigned char *buf, int len);
+
+/**
+ * @brief:use this function to read data from the ring buffer
+ *
+ * @param[in]:ring,which will be read
+ *
+ * @param[in]:buf, the data buffer
+ *
+ * @param[in]:len, the buffer length
+ *
+ * @return: how many bytes has been read while -1 failed
+ *
+ * */
+
+int ring_buffer_read(tag_ring_buffer_t *ring,unsigned char *buf, int len);
+
+#define ring_buffer_buf(x)          (x->buf)
+#define ring_buffer_buflen(x)       (x->buflen)
+#define ring_buffer_data(x)         (x->buf + x->dataoff)
+//#define ring_buffer_datalen(x)      (x->datalen)
+//#define ring_buffer_freespace(x)    (x->buflen - x->datalen)
+
+#define ring_buffer_dataoff(x)      (x->dataoff)
+#define ring_buffer_dumpread(x,y)   do{x->dataoff = (x->dataoff + y)%x->buflen; x->datalen -= y;}while(0)
+#define ring_buffer_dumpwrite(x,y)  do{x->datalen += y;)while(0)
+
+/**
+ * @brief:use this function check out how many data in the ring buffer
+ *
+ * @param[in]:ring,which will be checked
+
+ * @return: how many data bytes while -1 failed
+ *
+ * */
+int ring_buffer_datalen(tag_ring_buffer_t *ring);
+
+/**
+ * @brief:use this function check out how many free space in the ring buffer
+ *
+ * @param[in]:ring,which will be checked
+
+ * @return: how many free space  bytes while -1 failed
+ *
+ * */
+int ring_buffer_freespace(tag_ring_buffer_t *ring);
+
+/**
+ * @brief:use this function to reset the ring buffer
+ *
+ * @param[in]:ring,which will be reset
+
+ * @return: 0 success while -1 failed
+ *
+ * */
+int ring_buffer_reset(tag_ring_buffer_t *ring);
+
+/**
+ * @brief:use this function to deinit the ring buffer
+ *
+ * @param[in]:ring,which will be deinit
+
+ * @return: 0 success while -1 failed
+ *
+ * */
+int ring_buffer_deinit(tag_ring_buffer_t *ring);
+
+
+///< random
+/**
+ * @brief: use this function to generate the random ,could be reprogramed by yourelf
+ *
+ * @param[in]:output, this is the random data storage buffer
+ * @param[in]:len, the output buffer length
+ *
+ * @retrun:0 success while -1 failed
+ *
+ * */
+int link_random(void* output, int len);
+
+
+/**
+ * @brief: use this function to translate the string to argv mode
+ *
+ * @param[in]:string , the string to translate
+ * @param[inout]:argc, the sizeof argv and how many prarameters has been splited
+ * @param[inout]:argv, used to storage the parameters splited
+ *
+ * @retrun:how many parameters geted
+ *
+ * */
+int string_to_arg(int *argc, const char *argv[],char *string);
+
+/**
+ * @brief: use this function to add the string list to one string
+ *
+ * @param[in]:str[] the array to add, end with NULL
+ *
+ * @retrun:the str added, NULL if failed
+ *
+ * */
+
+char *osal_strcat(char *str[]);
+
+int hexstr2byte(const char *bufin, int len, char *bufout);
+
+int byte2hexstr(uint8_t *bufin, int len, char *bufout);
+
+
+
+
+
+#endif /* LITEOS_LAB_IOT_LINK_LINK_MISC_LINK_MISC_H_ */

+ 69 - 0
iot_link/link_misc/link_random.c

@@ -0,0 +1,69 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-05-10 10:26  zhangqianfu  The first version  
+ *
+ */
+#include <stdint.h>
+#include <stddef.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "cmsis_os2.h"
+
+__attribute__((weak)) int link_random(void* output, int len)
+{
+    int i;
+    int random_number;
+    char* pbuf;
+
+    if (NULL == output)
+    {
+        return -1;
+    }
+
+    pbuf = output;
+    srand(osKernelGetTickCount() * (1000 / 100));
+
+    for (i = 0; i < len; i += sizeof(int))
+    {
+        random_number = rand();
+        (void) memcpy(pbuf + i, &random_number,
+               sizeof(int) > (unsigned int)(len - i)? (unsigned int)(len - i): sizeof(int));
+    }
+
+    return 0;
+}

+ 210 - 0
iot_link/link_misc/link_ring_buffer.c

@@ -0,0 +1,210 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-04-29 10:34  zhangqianfu  The first version  
+ *
+ */
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <link_misc.h>
+
+
+int ring_buffer_init(tag_ring_buffer_t *ring,unsigned char *buf, int buflen,int offset,int datalen)
+{
+    int ret = -1;
+    if((NULL == ring))
+    {
+        return ret;
+    }
+    ring->buf     = buf;
+    ring->buflen  = buflen;
+    ring->datalen = datalen;
+    ring->dataoff = offset;
+    ret = 0;
+    return ret;
+}
+
+
+int ring_buffer_write(tag_ring_buffer_t *ring,unsigned char *buf, int len)
+{
+    int ret = -1;
+    int cpylen;  //the current time we should move
+    int lenleft;  //and how many data still left to move
+    int offset;
+    unsigned char *src;
+    unsigned char *dst;
+    if((NULL == ring)||(NULL == buf)||(0 == len))
+    {
+        return ret;//which means parameters error
+    }
+    if((ring->datalen == ring->buflen)|| (ring->buflen <= 0))
+    {
+        ret = 0;
+        return  ret;//which means you could copy nothing here
+    }
+    ret = len > (ring->buflen-ring->datalen)?(ring->buflen-ring->datalen):len;
+    //now let us think the method to fill the data,take care of the roll back
+    lenleft = ret;
+    src = buf;
+    if((ring->dataoff+ring->datalen)>ring->buflen) //which means the data has roll back
+    {
+        offset = (ring->dataoff+ring->datalen)%ring->buflen; //we could move it one time
+        cpylen = lenleft;
+        dst = ring->buf + offset;
+        if(cpylen > 0)
+        {
+            (void) memcpy(dst,src,cpylen);
+            ring->datalen += cpylen;
+            lenleft -= cpylen;
+        }
+    }
+    else if((ring->dataoff+ring->datalen + lenleft)>ring->buflen) //which means the data will be roll back
+    {
+        //which means roll back,we should copy some here to the tail
+        offset = ring->dataoff + ring->datalen;
+        cpylen = ring->buflen - offset;
+        dst = ring->buf + offset;
+        (void) memcpy(dst,src,cpylen);
+        src += cpylen;
+        ring->datalen += cpylen;
+        lenleft -= cpylen;
+    }
+    //here means we could move it by one time
+    if(lenleft > 0)
+    {
+        offset = (ring->dataoff+ring->datalen)%ring->buflen; //we could move it one time
+        cpylen = lenleft;
+        dst = ring->buf + offset;
+        (void) memcpy(dst,src,cpylen);
+        ring->datalen += cpylen;
+    }
+    return ret;
+}
+
+
+int ring_buffer_read(tag_ring_buffer_t *ring,unsigned char *buf, int len)
+{
+    int ret = -1;
+    int cpylen;  //the current time we should move
+    int lenleft;  //and how many data still left to move
+    int offset;
+    unsigned char *src;
+    unsigned char *dst;
+    if((NULL == ring)||(NULL == buf)||(0 == len))
+    {
+        return ret;//which means parameters error
+    }
+    if((ring->datalen == 0) || (ring->buflen <= 0))
+    {
+        ret = 0;
+        return  ret;//which means you could copy nothing here
+    }
+    ret = len > ring->datalen?ring->datalen:len;
+    //now let us think the method to fill the data,take care of the roll back
+    lenleft = ret;
+    dst = buf;
+    if(ring->dataoff >= (ring->buflen - lenleft)) //which means the data has roll back
+    {
+        offset =ring->dataoff; //we cpy part
+        cpylen = ring->buflen - ring->dataoff;
+        src = ring->buf + offset;
+
+        if(cpylen > 0)
+        {
+            (void) memcpy(dst,src,cpylen);
+            ring->dataoff = (ring->dataoff + cpylen)%ring->buflen;
+            ring->datalen -= cpylen;
+            lenleft -= cpylen;
+            dst += cpylen;
+        }
+    }
+    //here means we could move it by one time
+    if(lenleft > 0)
+    {
+        offset =ring->dataoff; //we cpy part
+        cpylen = lenleft;
+        src = ring->buf + offset;
+        (void) memcpy(dst,src,cpylen);
+        ring->dataoff = ring->dataoff + cpylen;
+        ring->datalen -= cpylen;
+    }
+    return ret;
+}
+
+
+int ring_buffer_datalen(tag_ring_buffer_t *ring)
+{
+    int ret = -1;
+    if(NULL != ring)
+    {
+        ret = ring->datalen;
+    }
+    return ret;
+}
+
+int ring_buffer_freespace(tag_ring_buffer_t *ring)
+{
+    int ret = -1;
+    if(NULL != ring)
+    {
+        ret = ring->buflen-ring->datalen;
+    }
+    return ret;
+}
+
+int ring_buffer_reset(tag_ring_buffer_t *ring)
+{
+    int ret = -1;
+    if(NULL != ring)
+    {
+        ring->datalen = 0;
+        ring->dataoff = 0;
+        ret = 0;
+    }
+    return ret;
+}
+
+int ring_buffer_deinit(tag_ring_buffer_t *ring)
+{
+    int ret = -1;
+    if(NULL != ring)
+    {
+        (void) memset(ring,0,sizeof(tag_ring_buffer_t));
+        ret = 0;
+    }
+    return ret;
+}

+ 259 - 0
iot_link/link_misc/link_string.c

@@ -0,0 +1,259 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-04-29 09:50  zhangqianfu  The first version  
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+// #include <osal.h>    修改
+//this function is used to format the char string to the argc mode
+//this function will changed the original string, used it carefully
+//return how many arguments has been
+int string_to_arg(int *argc, const char *argv[],char *string)
+{
+    int argvlen = 0;
+    int paramnum = 0;
+    char *tmp = NULL;
+    char bak;
+    int len;
+
+    argvlen = *argc;
+    *argc = paramnum;
+    if(NULL == string)
+    {
+        return paramnum;
+    }
+
+    //use the '\0' to replace the ' '
+    len = strlen(string);
+    tmp = string;
+    while(tmp < (string + len))
+    {
+        if(*tmp == ' ')
+        {
+            *tmp = '\0';
+        }
+        tmp++;
+    }
+    bak = '\0';
+    tmp = string;
+    while(tmp < (string + len))
+    {
+        if((*tmp != '\0')&&(bak =='\0'))
+        {
+            if(paramnum < argvlen)
+            {
+                argv[paramnum] = tmp;
+                paramnum++;
+            }
+        }
+        bak = *tmp;
+        tmp++;
+    }
+    *argc = paramnum;
+
+    return paramnum;
+}
+
+
+char *osal_strdup(const char *ch)
+{
+    char *copy;
+    size_t length;
+
+    if(NULL == ch)
+        return NULL;
+
+    length = strlen(ch);
+    copy = (char *)malloc(length + 1);   //修改
+    if(NULL == copy)
+        return NULL;
+    (void) strncpy(copy, ch, length);
+    copy[length] = '\0';
+
+    return copy;
+}
+
+char *osal_strcat(char *str[])
+{
+    char *ret = NULL;
+    int str_tnum = 0;
+    int str_tlen = 0;
+    int str_off = 0;
+    int i = 0;
+
+    if(NULL == str)
+    {
+        return ret;
+    }
+
+    while(NULL != str[i])
+    {
+        str_tlen += strlen(str[i]);
+        str_tnum++;
+        i++;
+    }
+
+    ret = malloc(str_tlen);  //修改
+    if(NULL != ret)
+    {
+        for(i =0;i< str_tnum;i++)
+        {
+
+            (void) memcpy(ret + str_off,str[i],strlen(str[i]));
+            str_off += strlen(str[i]);
+        }
+        ret[str_off] = '\0';
+    }
+
+    return ret;
+}
+
+/*
+int hexstr2byte(const char *bufin, int len, char *bufout)
+{
+    int i = 0;
+    unsigned char tmp2 = 0x0;
+    unsigned int tmp = 0;
+    char cc;
+
+    if (NULL == bufin || len <= 0 || NULL == bufout)
+    {
+        return -1;
+    }
+    for(i = 0; i < len; i = i+2)
+    {
+        tmp2 =  (unsigned char )bufin[i];
+        tmp2 =  tmp2 <= '9'?(unsigned char)(unsigned int)(tmp2-0x30):(unsigned char)(unsigned int)(tmp2-0x37);
+        cc = bufin[i+1];
+        tmp =  (unsigned int)(unsigned char)cc;
+        tmp =  tmp <= '9'?(unsigned int)(tmp-0x30):(unsigned int)(tmp-0x37);
+        bufout[i/2] =(tmp2<<4)|(tmp&0x0F);
+    }
+    return 0;
+}
+
+*/
+
+int hexstr2byte(const char *buf, int len, char *bufout)
+{
+    int ret = -1;
+    int i = 0;
+    uint8_t low;
+    uint8_t high;
+
+    if (NULL == buf || len <= 0 || NULL == bufout)
+    {
+        return ret;
+    }
+
+    ret = 0;
+    for(i = 0; i < len; i = i+2)
+    {
+        if(((buf[i]) >= '0') && (buf[i] <= '9'))
+        {
+            high = (uint8_t)( buf[i] - '0');
+        }
+        else if((buf[i] >= 'A') && (buf[i] <= 'F'))
+        {
+            high = (uint8_t)( buf[i] - 'A') + 10;
+        }
+        else if((buf[i] >= 'a') && (buf[i] <= 'f'))
+        {
+            high = (uint8_t)( buf[i] - 'a') + 10;
+        }
+        else
+        {
+            ret = -1;
+            break;
+        }
+
+        if(((buf[i+1]) >= '0') && (buf[i+1] <= '9'))
+        {
+            low = (uint8_t)( buf[i+1] - '0');
+        }
+        else if((buf[i+1] >= 'A') && (buf[i+1] <= 'F'))
+        {
+            low = (uint8_t)( buf[i+1] - 'A') + 10;
+        }
+        else if((buf[i+1] >= 'a') && (buf[i+1] <= 'f'))
+        {
+            low = (uint8_t)( buf[i+1] - 'a') + 10;
+        }
+        else
+        {
+            ret = -1;
+            break;
+        }
+
+        bufout[i/2] = (char)((high<<4)|(low&0x0F));
+    }
+    return ret;
+}
+
+
+
+//make a byte to 2 ascii hex
+int byte2hexstr(uint8_t *bufin, int len, char *bufout)
+{
+    int i = 0;
+    uint8_t tmp_l = 0x0;
+    uint8_t tmp_h = 0;
+    if ((NULL == bufin )|| (len <= 0 )||( NULL == bufout))
+    {
+        return -1;
+    }
+    for(i = 0; i < len; i++)
+    {
+        tmp_h = (bufin[i]>>4)&0X0F;
+        tmp_l = bufin[i] &0x0F;
+        bufout[2*i] = (tmp_h > 9)? (tmp_h - 10 + 'a'):(tmp_h +'0');
+        bufout[2*i + 1] = (tmp_l > 9)? (tmp_l - 10 + 'a'):(tmp_l +'0');
+    }
+    bufout[2*len] = '\0';
+
+    return 0;
+}
+
+
+
+
+
+

+ 46 - 0
iot_link/link_misc/link_time.h

@@ -0,0 +1,46 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-05-10 14:37  zhangqianfu  The first version  
+ *
+ */
+#ifndef LITEOS_LAB_IOT_LINK_LINK_MISC_LINK_TIME_H_
+#define LITEOS_LAB_IOT_LINK_LINK_MISC_LINK_TIME_H_
+
+
+
+
+
+#endif /* LITEOS_LAB_IOT_LINK_LINK_MISC_LINK_TIME_H_ */

+ 49 - 0
iot_link/network/dtls/BUILD.gn

@@ -0,0 +1,49 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# 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.
+
+dtls_inc = [
+    "mbedtls/mbedtls_port",
+    "../../inc",
+    "../../link_misc",
+    "//kernel/liteos_m/components/cmsis/2.0",
+    "//third_party/mbedtls/include/",
+]
+
+
+dtls_src = [
+    "dtls_al/dtls_al.c",
+    "mbedtls/mbedtls_port/dtls_interface.c",
+    "mbedtls/mbedtls_port/mbed_port.c",
+    "mbedtls/mbedtls_port/timing_alt.c",
+]
+dtls_def = [
+    "WITH_DTLS",
+    "MBEDTLS_AES_ROM_TABLES",
+    "MBEDTLS_CONFIG_FILE=\"los_mbedtls_config_dtls.h\"",
+    "CONFIG_DTLS_MBEDTLS_CERT",
+    "CONFIG_DTLS_MBEDTLS_PSK",
+    "CFG_MBEDTLS_MODE=PSK_CERT",
+
+]
+
+dtls_cflags = [
+    "-Wno-sign-compare",
+    "-Wno-unused-parameter",
+]
+
+static_library("dtls") {
+        cflags = dtls_cflags
+        defines = dtls_def
+        sources = dtls_src
+        include_dirs = dtls_inc
+}

+ 143 - 0
iot_link/network/dtls/dtls_al/dtls_al.c

@@ -0,0 +1,143 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2019-10-17 19:50  zhangqianfu  The first version
+ *
+ */
+
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <dtls_al.h>
+#include <link_log.h>
+
+
+static const dtls_al_t  *s_dtls_al;
+
+en_dtls_al_err_t dtls_al_new(dtls_al_para_t *para,void **handle)
+{
+    en_dtls_al_err_t ret = EN_DTLS_AL_ERR_NOCONFIG;
+    if( (NULL != s_dtls_al) && (NULL != s_dtls_al->io.io_new) )
+    {
+        ret = s_dtls_al->io.io_new(para, handle);
+    }
+    return ret;
+}
+
+
+int   dtls_al_connect(void *handle,const char *server_ip, const char *server_port, int timeout)
+{
+    int ret = -1;
+    if( (NULL != s_dtls_al) && (NULL != s_dtls_al->io.io_connect))
+    {
+        ret = s_dtls_al->io.io_connect(handle, server_ip,server_port, timeout);
+    }
+    return ret;
+}
+
+int   dtls_al_write(void *handle, uint8_t *msg, size_t len, int timeout)
+{
+    int ret = 0;
+    if( (NULL != s_dtls_al) && (NULL != s_dtls_al->io.io_write))
+    {
+        ret = s_dtls_al->io.io_write(handle, msg, len, timeout );
+    }
+    return ret;
+}
+
+int  dtls_al_read(void *handle, uint8_t *buf, size_t len, int timeout)
+{
+    int ret = 0;
+    if( (NULL != s_dtls_al) && (NULL != s_dtls_al->io.io_read))
+    {
+        ret = s_dtls_al->io.io_read(handle, buf, len, timeout );
+    }
+    return ret;
+}
+
+en_dtls_al_err_t   dtls_al_destroy(void *handle)
+{
+    en_dtls_al_err_t ret = EN_DTLS_AL_ERR_NOCONFIG;
+    if( (NULL != s_dtls_al) && (NULL != s_dtls_al->io.io_destroy))
+    {
+        ret = s_dtls_al->io.io_destroy( handle );
+    }
+    return ret;
+}
+
+
+int dtls_al_install(const dtls_al_t *dtls)
+{
+    int ret = -1;
+    if (NULL == s_dtls_al )
+    {
+        s_dtls_al = dtls;
+        ret = 0;
+    }
+
+    return ret;
+}
+
+int dtls_al_uninstall(const char*name)
+{
+    int ret = -1;
+
+    if((NULL != s_dtls_al) && (0 == strcmp(name,s_dtls_al->name)))
+    {
+        s_dtls_al = NULL;
+    }
+
+    return ret;
+}
+
+__attribute__((weak))  int dtls_imp_init(void)
+{
+    LINK_LOG_DEBUG("%s:###please implement dtls by yourself####",__FUNCTION__);
+    return -1;
+}
+
+int dtls_al_init(void)
+{
+    int ret;
+
+    ret = dtls_imp_init();
+    LINK_LOG_DEBUG("IOT_LINK:DO DTLS LOAD-IMPLEMENT RET:%d",ret);
+
+    return ret;
+}
+
+

+ 552 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/dtls_interface.c

@@ -0,0 +1,552 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Simple DTLS client demonstration program
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#include "dtls_interface.h"
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/ssl_internal.h"
+#include "cmsis_os2.h"
+#include "string.h"
+
+#define MBEDTLS_LOG LINK_LOG_DEBUG
+
+mbedtls_ssl_context *dtls_ssl_new(dtls_establish_info_s *info, char plat_type)
+{
+    int ret = -1;
+    mbedtls_ssl_context *ssl = NULL;
+    mbedtls_ssl_config *conf = NULL;
+    mbedtls_entropy_context *entropy = NULL;
+    mbedtls_ctr_drbg_context *ctr_drbg = NULL;
+    mbedtls_timing_delay_context *timer = NULL;
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    mbedtls_x509_crt *cacert;
+    mbedtls_x509_crt *client_ca = NULL;
+    mbedtls_pk_context *client_pk = NULL;
+#endif
+
+    const char *pers = "ssl_client";
+    int transport;
+    ssl       = mbedtls_calloc(1, sizeof(mbedtls_ssl_context));
+    conf      = mbedtls_calloc(1, sizeof(mbedtls_ssl_config));
+    entropy   = mbedtls_calloc(1, sizeof(mbedtls_entropy_context));
+    ctr_drbg  = mbedtls_calloc(1, sizeof(mbedtls_ctr_drbg_context));
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    cacert    = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+#endif
+
+    if (NULL == info || NULL == ssl
+        || NULL == conf || NULL == entropy
+        || NULL == ctr_drbg
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+        || NULL == cacert
+#endif
+        )
+    {
+        goto exit_fail;
+    }
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if(NULL != info->v.c.client_ca) /// we'd better to make the client ca and key
+    {
+        client_ca    = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+        client_pk    = mbedtls_calloc(1, sizeof(mbedtls_pk_context));
+        if((NULL == client_ca) || (NULL == client_pk))
+        {
+            goto exit_fail;
+        }
+        mbedtls_x509_crt_init(client_ca);
+        mbedtls_pk_init(client_pk);
+    }
+#endif
+
+    if (info->udp_or_tcp == MBEDTLS_NET_PROTO_UDP)
+    {
+        transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
+        timer = mbedtls_calloc(1, sizeof(mbedtls_timing_delay_context));
+        if (NULL == timer)
+            goto exit_fail;
+    }
+    else
+    {
+        transport = MBEDTLS_SSL_TRANSPORT_STREAM;
+    }
+
+    mbedtls_ssl_init(ssl);
+    mbedtls_ssl_config_init(conf);
+    mbedtls_ctr_drbg_init(ctr_drbg);
+    mbedtls_entropy_init(entropy);
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if (info->psk_or_cert == VERIFY_WITH_CERT)
+    {
+        mbedtls_x509_crt_init(cacert);
+    }
+#endif
+
+    if ((ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy,
+                                     (const unsigned char *) pers,
+                                     strlen(pers))) != 0)
+    {
+        MBEDTLS_LOG("mbedtls_ctr_drbg_seed failed: -0x%x", -ret);
+        goto exit_fail;
+    }
+
+    MBEDTLS_LOG("setting up the SSL structure");
+
+    (void) mbedtls_ssl_config_defaults(conf,plat_type,transport,MBEDTLS_SSL_PRESET_DEFAULT);
+
+    mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+    mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, ctr_drbg);
+
+    if (info->udp_or_tcp == MBEDTLS_NET_PROTO_TCP)
+    {
+        mbedtls_ssl_conf_read_timeout(conf, TLS_SHAKEHAND_TIMEOUT);
+    }
+
+#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
+    if (info->psk_or_cert == VERIFY_WITH_PSK)
+    {
+        if ((ret = mbedtls_ssl_conf_psk(conf,
+                                        info->v.p.psk,
+                                        info->v.p.psk_len,
+                                        info->v.p.psk_identity,
+                                        strlen((const char *)info->v.p.psk_identity))) != 0)
+        {
+            MBEDTLS_LOG("mbedtls_ssl_conf_psk failed: -0x%x", -ret);
+            goto exit_fail;
+        }
+    }
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if (info->psk_or_cert == VERIFY_WITH_CERT)
+    {
+        ret = mbedtls_x509_crt_parse(cacert, info->v.c.ca_cert, info->v.c.cert_len);
+        if(ret < 0)
+        {
+            MBEDTLS_LOG("mbedtls_x509_crt_parse failed -0x%x", -ret);
+            goto exit_fail;
+        }
+        mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+        mbedtls_ssl_conf_ca_chain(conf, cacert, NULL);
+
+        if(NULL != info->v.c.client_ca) ///< setup the client key and ca
+        {
+            ret = mbedtls_x509_crt_parse(client_ca,info->v.c.client_ca,info->v.c.client_ca_len);
+            if(ret <0)
+            {
+                goto exit_fail;
+            }
+
+            ret = mbedtls_pk_parse_key(client_pk,info->v.c.client_pk,info->v.c.client_pk_len,\
+                                       info->v.c.client_pk_pwd,info->v.c.client_pk_pwd_len);
+            if(ret < 0)
+            {
+                goto exit_fail;
+            }
+
+            ret = mbedtls_ssl_conf_own_cert( conf, client_ca, client_pk );
+            if(ret != 0)
+            {
+                goto exit_fail;
+            }
+        }
+    }
+#endif
+
+    mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);  //TODO--test for no check the ca_rt--only for the debug
+
+    if ((ret = mbedtls_ssl_setup(ssl, conf)) != 0)
+    {
+        MBEDTLS_LOG("mbedtls_ssl_setup failed: -0x%x", -ret);
+        goto exit_fail;
+    }
+
+    if (info->udp_or_tcp == MBEDTLS_NET_PROTO_UDP)
+    {
+        mbedtls_ssl_set_timer_cb(ssl, timer, mbedtls_timing_set_delay,
+                                 mbedtls_timing_get_delay);
+    }
+
+    MBEDTLS_LOG("set SSL structure succeed");
+
+    return ssl;
+
+exit_fail:
+
+    if (conf)
+    {
+        mbedtls_ssl_config_free(conf);
+        mbedtls_free(conf);
+    }
+
+    if (ctr_drbg)
+    {
+        mbedtls_ctr_drbg_free(ctr_drbg);
+        mbedtls_free(ctr_drbg);
+    }
+
+    if (entropy)
+    {
+        mbedtls_entropy_free(entropy);
+        mbedtls_free(entropy);
+    }
+
+    if (timer)
+    {
+        mbedtls_free(timer);
+    }
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if (cacert)
+    {
+        mbedtls_x509_crt_free(cacert);
+        mbedtls_free(cacert);
+    }
+
+    if(client_ca)
+    {
+        mbedtls_x509_crt_free(client_ca);
+        mbedtls_free(client_ca);
+    }
+
+    if(client_pk)
+    {
+        mbedtls_pk_free(client_pk);
+        mbedtls_free(client_pk);
+    }
+#endif
+
+    if (ssl)
+    {
+        mbedtls_ssl_free(ssl);
+        mbedtls_free(ssl);
+    }
+    return NULL;
+}
+
+static inline uint32_t dtls_gettime(void)
+{
+    return ((uint32_t)osKernelGetTickCount() * (1000 / 100) );
+}
+
+int dtls_shakehand(mbedtls_ssl_context *ssl, const dtls_shakehand_info_s *info)
+{
+    int ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
+    uint32_t change_value = 0;
+    mbedtls_net_context *server_fd = NULL;
+    uint32_t max_value;
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    unsigned int flags;
+#endif
+
+    MBEDTLS_LOG("connecting to server");
+
+    server_fd = (mbedtls_net_context *)malloc(sizeof(mbedtls_net_context));
+    if (server_fd == NULL)
+    {
+        MBEDTLS_LOG("connect failed! mode %d", info->client_or_server);
+        ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
+        goto exit_fail;
+    }
+
+    if (MBEDTLS_SSL_IS_CLIENT == info->client_or_server)
+    {
+        ret = mbedtls_net_connect(server_fd, info->u.c.host, info->u.c.port, info->udp_or_tcp);
+        if( 0 != ret)
+        {
+            ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
+            goto exit_fail;
+        }
+    }
+    else
+    {
+        //server_fd = (mbedtls_net_context*)atiny_net_bind(NULL, info->u.s.local_port, MBEDTLS_NET_PROTO_UDP);
+        ///< --TODO ,not implement yet
+    }
+
+    mbedtls_ssl_set_bio(ssl, server_fd,
+                        mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
+
+    MBEDTLS_LOG("performing the SSL/TLS handshake");
+
+    max_value = ((MBEDTLS_SSL_IS_SERVER == info->client_or_server || info->udp_or_tcp == MBEDTLS_NET_PROTO_UDP) ?
+                (dtls_gettime() + info->timeout) :  50);
+
+    do
+    {
+        ret = mbedtls_ssl_handshake(ssl);
+
+        if (MBEDTLS_SSL_IS_CLIENT == info->client_or_server && info->udp_or_tcp == MBEDTLS_NET_PROTO_TCP)
+        {
+            change_value++;
+        }
+        else
+        {
+            change_value = dtls_gettime();
+        }
+
+        if (info->step_notify)
+        {
+            info->step_notify(info->param);
+        }
+    }
+    while ((ret == MBEDTLS_ERR_SSL_WANT_READ ||
+            ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
+            (ret == MBEDTLS_ERR_SSL_TIMEOUT &&
+            info->udp_or_tcp == MBEDTLS_NET_PROTO_TCP)) &&
+            (change_value < max_value));
+
+    if (info->finish_notify)
+    {
+        info->finish_notify(info->param);
+    }
+
+    if (ret != 0)
+    {
+        MBEDTLS_LOG("mbedtls_ssl_handshake failed: -0x%x", -ret);
+        goto exit_fail;
+    }
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if (info->psk_or_cert == VERIFY_WITH_CERT)
+    {
+        if((flags = mbedtls_ssl_get_verify_result(ssl)) != 0)
+        {
+            char vrfy_buf[512];
+            (void) mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
+            MBEDTLS_LOG("cert verify failed: %s", vrfy_buf);
+            goto exit_fail;
+        }
+        else
+            MBEDTLS_LOG("cert verify succeed");
+    }
+#endif
+
+    MBEDTLS_LOG("handshake succeed");
+
+    return 0;
+
+exit_fail:
+
+    if (server_fd)
+    {
+        mbedtls_net_free(server_fd);
+        ssl->p_bio = NULL;
+    }
+
+    return ret;
+
+}
+void dtls_ssl_destroy(mbedtls_ssl_context *ssl)
+{
+    int ret;
+    mbedtls_ssl_config           *conf = NULL;
+    mbedtls_ctr_drbg_context     *ctr_drbg = NULL;
+    mbedtls_entropy_context      *entropy = NULL;
+    mbedtls_net_context          *server_fd = NULL;
+    mbedtls_timing_delay_context *timer = NULL;
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    mbedtls_x509_crt             *cacert = NULL;
+    mbedtls_x509_crt             *client_ca = NULL;
+    mbedtls_pk_context           *client_pk = NULL;
+    mbedtls_ssl_key_cert         *key_cert = NULL;
+#endif
+
+    if (ssl == NULL)
+    {
+        return;
+    }
+
+    conf       = (mbedtls_ssl_config *)ssl->conf;
+    server_fd  = (mbedtls_net_context *)ssl->p_bio;
+    timer      = (mbedtls_timing_delay_context *)ssl->p_timer;
+
+
+    do ret = mbedtls_ssl_close_notify( ssl );
+    while( ret == MBEDTLS_ERR_SSL_WANT_WRITE );
+
+
+    if (NULL != conf)
+    {
+        ctr_drbg   = conf->p_rng;
+
+        if (NULL !=ctr_drbg)
+        {
+            entropy =  ctr_drbg->p_entropy;
+        }
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+        cacert     = (mbedtls_x509_crt *)conf->ca_chain;
+
+        key_cert   = conf->key_cert;
+        if(NULL != key_cert)
+        {
+            client_ca = (mbedtls_x509_crt *) key_cert->cert;
+            client_pk = key_cert->key;
+        }
+
+#endif
+    }
+
+    if (NULL != server_fd)
+    {
+        mbedtls_net_free(server_fd);
+    }
+
+    if (NULL != conf)
+    {
+        mbedtls_ssl_config_free(conf);
+        mbedtls_free(conf);
+        ssl->conf = NULL; //  need by mbedtls_debug_print_msg(), see mbedtls_ssl_free(ssl)
+    }
+
+    if (ctr_drbg)
+    {
+        mbedtls_ctr_drbg_free(ctr_drbg);
+        mbedtls_free(ctr_drbg);
+    }
+
+    if (entropy)
+    {
+        mbedtls_entropy_free(entropy);
+        mbedtls_free(entropy);
+    }
+
+    if (timer)
+    {
+        mbedtls_free(timer);
+    }
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if (cacert)
+    {
+        mbedtls_x509_crt_free(cacert);
+        mbedtls_free(cacert);
+    }
+    if( client_ca )
+    {
+        mbedtls_x509_crt_free(client_ca);
+        mbedtls_free(client_ca);
+    }
+
+    if( client_pk )
+    {
+        mbedtls_pk_free(client_pk);
+        mbedtls_free(client_pk);
+    }
+
+#endif
+
+    mbedtls_ssl_free(ssl);
+    mbedtls_free(ssl);
+}
+
+int dtls_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len)
+{
+
+    int ret;
+
+    ret = mbedtls_ssl_write(ssl, (unsigned char *) buf, len);
+
+    if ((ret == MBEDTLS_ERR_SSL_WANT_WRITE) ||(ret == MBEDTLS_ERR_SSL_TIMEOUT))
+    {
+        ret =  -1;
+    }
+    else if (ret <= 0)
+    {
+        ret = 0;
+    }
+
+    return ret;
+}
+
+
+///< make it return as normal socket return
+int dtls_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len, uint32_t timeout)
+{
+    int ret;
+
+
+    mbedtls_ssl_conf_read_timeout((mbedtls_ssl_config *)ssl->conf, timeout);
+
+    ret = mbedtls_ssl_read(ssl, buf, len);
+
+    if ((ret == MBEDTLS_ERR_SSL_WANT_READ) ||(ret == MBEDTLS_ERR_SSL_TIMEOUT))
+    {
+        ret = -1;
+    }
+    else if (ret <= 0)
+    {
+        ret = 0;
+    }
+
+    return ret;
+}
+
+
+
+int dtls_accept( mbedtls_net_context *bind_ctx,
+                mbedtls_net_context *client_ctx,
+                void *client_ip, size_t buf_size, size_t *ip_len )
+{
+    return mbedtls_net_accept(bind_ctx, client_ctx, client_ip, buf_size, ip_len);
+}
+
+void dtls_init(void)
+{
+    (void)mbedtls_platform_set_calloc_free(calloc, free);
+    (void)mbedtls_platform_set_snprintf(snprintf);
+    (void)mbedtls_platform_set_printf(printf);
+}

+ 169 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/dtls_interface.h

@@ -0,0 +1,169 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Simple DTLS client demonstration program
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef DTLS_INTERFACE_H
+#define DTLS_INTERFACE_H
+
+
+#include <link_log.h>
+
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "los_mbedtls_config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf   LINK_LOG_DEBUG
+#endif
+
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/error.h"
+#include "mbedtls/timing.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef TLS_SHAKEHAND_TIMEOUT
+#define TLS_SHAKEHAND_TIMEOUT 1000
+#endif
+
+typedef enum
+{
+    VERIFY_WITH_PSK = 0,
+    VERIFY_WITH_CERT,
+}verify_type_e;
+
+typedef struct
+{
+    union
+    {
+        struct
+        {
+            const char *host;
+            const char *port;
+        }c;
+        struct
+        {
+            const char *local_port;
+        }s;
+    }u;
+    uint32_t timeout;
+    int client_or_server;
+    int udp_or_tcp;
+    verify_type_e psk_or_cert;
+    void (*step_notify)(void *param);
+    void (*finish_notify)(void *param);
+    void *param;
+}dtls_shakehand_info_s;
+
+typedef struct
+{
+    union
+    {
+        struct
+        {
+            const unsigned char *psk;
+            uint32_t psk_len;
+            const unsigned char *psk_identity;
+        }p;
+        struct
+        {
+            const unsigned char *ca_cert;
+            uint32_t cert_len;
+
+            const unsigned char *client_ca;
+            uint32_t             client_ca_len;
+
+            const unsigned char *client_pk;
+            uint32_t             client_pk_len;
+
+            const unsigned char *client_pk_pwd;
+            uint32_t             client_pk_pwd_len;
+
+        }c;
+    }v;
+    verify_type_e psk_or_cert;
+    int udp_or_tcp;
+}dtls_establish_info_s;
+
+void dtls_init(void);
+
+mbedtls_ssl_context *dtls_ssl_new(dtls_establish_info_s *info, char plat_type);
+
+int dtls_shakehand(mbedtls_ssl_context *ssl, const dtls_shakehand_info_s *info);
+
+void dtls_ssl_destroy(mbedtls_ssl_context* ssl);
+
+int dtls_write(mbedtls_ssl_context* ssl, const unsigned char* buf, size_t len);
+
+int dtls_read(mbedtls_ssl_context* ssl, unsigned char* buf, size_t len, uint32_t timeout);
+
+int dtls_accept( mbedtls_net_context *bind_ctx,
+                            mbedtls_net_context *client_ctx,
+                            void *client_ip, size_t buf_size, size_t *ip_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 159 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config.h

@@ -0,0 +1,159 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ * Distinguishing features:
+ * - no bignum, no PK, no X509
+ * - fully modern and secure (provided the pre-shared keys have high entropy)
+ * - very low record overhead with CCM-8
+ * - optimized for low RAM usage
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/* System support */
+//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
+/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+//#define MBEDTLS_NET_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_DEBUG_C
+#endif
+
+#ifdef USE_MRVL_SDIO_WIFI
+#define MBEDTLS_ARC4_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_SHA1_C
+#endif
+
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PLATFORM_PRINTF_ALT
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PLATFORM_MEMORY
+//#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 */
+
+/* Save RAM at the expense of ROM */
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_AES_ROM_TABLES
+#endif
+
+/* Save some RAM by adjusting to your exact needs */
+#define MBEDTLS_PSK_MAX_LEN    32 /* 128-bits keys are generally enough */
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
+ */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 1
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
+ * The optimal size here depends on the typical size of records.
+ */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             5000
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+#define MBEDTLS_SSL_RENEGOTIATION
+#define MBEDTLS_SSL_CACHE_C
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#if 0 // We should support two encryption algorithm
+#define MBEDTLS_CCM_C
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
+#define MBEDTLS_WITH_ONLY_AEAD_CHIPERS
+#define MBEDTLS_ONLY_CCM_8_CHIPERS
+#else
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+#endif
+
+#if defined(CONFIG_FEATURE_FOTA) ||  defined(WITH_SOTA)
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V21
+#define MBEDTLS_ASN1_PARSE_C
+#endif
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */

+ 250 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_cert.h

@@ -0,0 +1,250 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ * Distinguishing features:
+ * - no bignum, no PK, no X509
+ * - fully modern and secure (provided the pre-shared keys have high entropy)
+ * - very low record overhead with CCM-8
+ * - optimized for low RAM usage
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/* System support */
+//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
+/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_SSL_PROTO_TLS1_2
+//#define MBEDTLS_SSL_PROTO_DTLS
+//#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+//#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+//#define MBEDTLS_NET_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_CLI_C
+//#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_DEBUG_C
+#endif
+
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PLATFORM_PRINTF_ALT
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PLATFORM_MEMORY
+//#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 */
+
+/* Save RAM at the expense of ROM */
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_AES_ROM_TABLES
+#endif
+
+/* Save some RAM by adjusting to your exact needs */
+#define MBEDTLS_PSK_MAX_LEN    32 /* 128-bits keys are generally enough */
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
+ */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 1
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
+ * The optimal size here depends on the typical size of records.
+ */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             16000
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+#define MBEDTLS_SSL_RENEGOTIATION
+#define MBEDTLS_SSL_CACHE_C
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#if 0 // We should support two encryption algorithm
+#define MBEDTLS_CCM_C
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
+#define MBEDTLS_WITH_ONLY_AEAD_CHIPERS
+#define MBEDTLS_ONLY_CCM_8_CHIPERS
+#else
+
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+#endif
+
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+// #define MBEDTLS_HAVE_ASM
+// #define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+//#define MBEDTLS_CIPHER_MODE_CFB
+//#define MBEDTLS_CIPHER_MODE_CTR
+//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+//#define MBEDTLS_ECDSA_DETERMINISTIC
+//#define MBEDTLS_ECP_NIST_OPTIM
+#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
+//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+//#define MBEDTLS_GENPRIME
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_PKCS1_V21
+//#define MBEDTLS_SELF_TEST
+//#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#define MBEDTLS_SSL_FALLBACK_SCSV
+//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+//#define MBEDTLS_SSL_PROTO_TLS1
+//#define MBEDTLS_SSL_PROTO_TLS1_1
+//#define MBEDTLS_SSL_ALPN
+//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+#define MBEDTLS_SSL_SESSION_TICKETS
+#define MBEDTLS_SSL_EXPORT_KEYS
+// #define MBEDTLS_SSL_SERVER_NAME_INDICATION
+//#define MBEDTLS_SSL_TRUNCATED_HMAC
+#define MBEDTLS_VERSION_FEATURES
+#define MBEDTLS_VERSION_C
+// #define MBEDTLS_AESNI_C
+//#define MBEDTLS_ARC4_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+//#define MBEDTLS_BLOWFISH_C
+//#define MBEDTLS_CAMELLIA_C
+#define MBEDTLS_CERTS_C
+//#define MBEDTLS_DES_C
+//#define MBEDTLS_DHM_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_GCM_C
+//#define MBEDTLS_HMAC_DRBG_C
+//#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+// #define MBEDTLS_PADLOCK_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PKCS12_C
+//#define MBEDTLS_RIPEMD160_C
+#define MBEDTLS_RSA_C
+//#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_COOKIE_C
+//#define MBEDTLS_SSL_TICKET_C
+ #define MBEDTLS_X509_CHECK_KEY_USAGE
+ #define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+ #define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+ #define MBEDTLS_X509_USE_C
+ #define MBEDTLS_X509_CRT_PARSE_C
+ #define MBEDTLS_X509_CRL_PARSE_C
+ #define MBEDTLS_X509_CSR_PARSE_C
+ #define MBEDTLS_X509_CREATE_C
+ #define MBEDTLS_X509_CRT_WRITE_C
+ #define MBEDTLS_X509_CSR_WRITE_C
+//#define MBEDTLS_XTEA_C
+//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+#define MBEDTLS_SHA1_C
+
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */

+ 250 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_cert.h.bak

@@ -0,0 +1,250 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ * Distinguishing features:
+ * - no bignum, no PK, no X509
+ * - fully modern and secure (provided the pre-shared keys have high entropy)
+ * - very low record overhead with CCM-8
+ * - optimized for low RAM usage
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/* System support */
+//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
+/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_SSL_PROTO_TLS1_2
+//#define MBEDTLS_SSL_PROTO_DTLS
+//#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+//#define MBEDTLS_NET_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_CLI_C
+//#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_DEBUG_C
+#endif
+
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PLATFORM_PRINTF_ALT
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PLATFORM_MEMORY
+//#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 */
+
+/* Save RAM at the expense of ROM */
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_AES_ROM_TABLES
+#endif
+
+/* Save some RAM by adjusting to your exact needs */
+#define MBEDTLS_PSK_MAX_LEN    32 /* 128-bits keys are generally enough */
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
+ */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 1
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
+ * The optimal size here depends on the typical size of records.
+ */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             5000
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+#define MBEDTLS_SSL_RENEGOTIATION
+#define MBEDTLS_SSL_CACHE_C
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#if 0 // We should support two encryption algorithm
+#define MBEDTLS_CCM_C
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
+#define MBEDTLS_WITH_ONLY_AEAD_CHIPERS
+#define MBEDTLS_ONLY_CCM_8_CHIPERS
+#else
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+#endif
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+// #define MBEDTLS_HAVE_ASM
+ #define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+
+
+
+#define MBEDTLS_CIPHER_MODE_CFB
+#define MBEDTLS_CIPHER_MODE_CTR
+#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECP_NIST_OPTIM
+#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
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+#define MBEDTLS_GENPRIME
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_PKCS1_V21
+#define MBEDTLS_SELF_TEST
+#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#define MBEDTLS_SSL_FALLBACK_SCSV
+#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+#define MBEDTLS_SSL_PROTO_TLS1
+#define MBEDTLS_SSL_PROTO_TLS1_1
+#define MBEDTLS_SSL_ALPN
+//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+#define MBEDTLS_SSL_SESSION_TICKETS
+#define MBEDTLS_SSL_EXPORT_KEYS
+// #define MBEDTLS_SSL_SERVER_NAME_INDICATION
+#define MBEDTLS_SSL_TRUNCATED_HMAC
+#define MBEDTLS_VERSION_FEATURES
+#define MBEDTLS_VERSION_C
+// #define MBEDTLS_AESNI_C
+#define MBEDTLS_ARC4_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_BLOWFISH_C
+#define MBEDTLS_CAMELLIA_C
+#define MBEDTLS_CERTS_C
+#define MBEDTLS_DES_C
+#define MBEDTLS_DHM_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_GCM_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+// #define MBEDTLS_PADLOCK_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PKCS12_C
+#define MBEDTLS_RIPEMD160_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_TICKET_C
+ #define MBEDTLS_X509_CHECK_KEY_USAGE
+ #define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+ #define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+ #define MBEDTLS_X509_USE_C
+ #define MBEDTLS_X509_CRT_PARSE_C
+ #define MBEDTLS_X509_CRL_PARSE_C
+ #define MBEDTLS_X509_CSR_PARSE_C
+ #define MBEDTLS_X509_CREATE_C
+ #define MBEDTLS_X509_CRT_WRITE_C
+ #define MBEDTLS_X509_CSR_WRITE_C
+#define MBEDTLS_XTEA_C
+#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+#define MBEDTLS_SHA1_C
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */

+ 293 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_dtls.h

@@ -0,0 +1,293 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ * Distinguishing features:
+ * - no bignum, no PK, no X509
+ * - fully modern and secure (provided the pre-shared keys have high entropy)
+ * - very low record overhead with CCM-8
+ * - optimized for low RAM usage
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/* System support */
+//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
+/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_SSL_PROTO_TLS1_2
+
+#ifdef CONFIG_DTLS_MBEDTLS_PSK
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#endif
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+//#define MBEDTLS_NET_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_CLI_C
+
+#ifdef CONFIG_DTLS_MBEDTLS_PSK
+#define MBEDTLS_SSL_SRV_C
+#endif
+
+#define MBEDTLS_SSL_TLS_C
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_DEBUG_C
+#endif
+
+#ifdef CONFIG_DTLS_MBEDTLS_PSK
+#ifdef USE_MRVL_SDIO_WIFI
+#define MBEDTLS_ARC4_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_SHA1_C
+#endif
+#endif
+
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PLATFORM_PRINTF_ALT
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PLATFORM_MEMORY
+//#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 */
+
+/* Save RAM at the expense of ROM */
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_AES_ROM_TABLES
+#endif
+
+/* Save some RAM by adjusting to your exact needs */
+#define MBEDTLS_PSK_MAX_LEN    32 /* 128-bits keys are generally enough */
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
+ */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 1
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
+ * The optimal size here depends on the typical size of records.
+ */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             5000
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+#ifdef CONFIG_DTLS_MBEDTLS_PSK
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#endif
+
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+#define MBEDTLS_SSL_RENEGOTIATION
+#define MBEDTLS_SSL_CACHE_C
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#if 0 // We should support two encryption algorithm
+#define MBEDTLS_CCM_C
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
+#define MBEDTLS_WITH_ONLY_AEAD_CHIPERS
+#define MBEDTLS_ONLY_CCM_8_CHIPERS
+#else
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+#endif
+
+#ifdef CONFIG_DTLS_MBEDTLS_CERT
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+// #define MBEDTLS_HAVE_ASM
+ #define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+#define MBEDTLS_CIPHER_MODE_CFB
+#define MBEDTLS_CIPHER_MODE_CTR
+#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECP_NIST_OPTIM
+#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
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+#define MBEDTLS_GENPRIME
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_PKCS1_V21
+#define MBEDTLS_SELF_TEST
+#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#define MBEDTLS_SSL_FALLBACK_SCSV
+#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+#define MBEDTLS_SSL_PROTO_TLS1
+#define MBEDTLS_SSL_PROTO_TLS1_1
+#define MBEDTLS_SSL_ALPN
+//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+#define MBEDTLS_SSL_SESSION_TICKETS
+#define MBEDTLS_SSL_EXPORT_KEYS
+// #define MBEDTLS_SSL_SERVER_NAME_INDICATION
+#define MBEDTLS_SSL_TRUNCATED_HMAC
+#define MBEDTLS_VERSION_FEATURES
+#define MBEDTLS_VERSION_C
+// #define MBEDTLS_AESNI_C
+#define MBEDTLS_ARC4_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_BLOWFISH_C
+#define MBEDTLS_CAMELLIA_C
+#define MBEDTLS_CERTS_C
+#define MBEDTLS_DES_C
+#define MBEDTLS_DHM_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_GCM_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+// #define MBEDTLS_PADLOCK_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PKCS12_C
+#define MBEDTLS_RIPEMD160_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_TICKET_C
+ #define MBEDTLS_X509_CHECK_KEY_USAGE
+ #define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+ #define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+ #define MBEDTLS_X509_USE_C
+ #define MBEDTLS_X509_CRT_PARSE_C
+ #define MBEDTLS_X509_CRL_PARSE_C
+ #define MBEDTLS_X509_CSR_PARSE_C
+ #define MBEDTLS_X509_CREATE_C
+ #define MBEDTLS_X509_CRT_WRITE_C
+ #define MBEDTLS_X509_CSR_WRITE_C
+#define MBEDTLS_XTEA_C
+#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+#define MBEDTLS_SHA1_C
+#endif
+
+
+#ifdef CONFIG_DTLS_MBEDTLS_PSK
+#if defined(CONFIG_FEATURE_FOTA) ||  defined(WITH_SOTA)
+#ifndef MBEDTLS_RSA_C
+#define MBEDTLS_RSA_C
+#endif
+
+#ifndef MBEDTLS_BIGNUM_C
+#define MBEDTLS_BIGNUM_C
+#endif
+
+#ifndef MBEDTLS_OID_C
+#define MBEDTLS_OID_C
+#endif
+
+#ifndef MBEDTLS_PKCS1_V21
+#define MBEDTLS_PKCS1_V21
+#endif
+
+#ifndef MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_PARSE_C
+#endif
+#endif
+#endif
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */

+ 246 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/los_mbedtls_config_psk.h

@@ -0,0 +1,246 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+/*
+ *  Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
+ * Distinguishing features:
+ * - no bignum, no PK, no X509
+ * - fully modern and secure (provided the pre-shared keys have high entropy)
+ * - very low record overhead with CCM-8
+ * - optimized for low RAM usage
+ *
+ * See README.txt for usage instructions.
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/* System support */
+//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
+/* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
+
+/* mbed TLS feature support */
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+//#define MBEDTLS_NET_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_CLI_C
+//#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_DEBUG_C
+#endif
+
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PLATFORM_PRINTF_ALT
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PLATFORM_MEMORY
+//#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 */
+
+/* Save RAM at the expense of ROM */
+#if !defined ( __GNUC__ )  /* GCC*/
+#define MBEDTLS_AES_ROM_TABLES
+#endif
+
+/* Save some RAM by adjusting to your exact needs */
+#define MBEDTLS_PSK_MAX_LEN    32 /* 128-bits keys are generally enough */
+
+/*
+ * You should adjust this to the exact number of sources you're using: default
+ * is the "platform_entropy_poll" source, but you may want to add other ones
+ * Minimum is 2 for the entropy test suite.
+ */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 1
+
+/*
+ * Save RAM at the expense of interoperability: do this only if you control
+ * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
+ * The optimal size here depends on the typical size of records.
+ */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             5000
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+#define MBEDTLS_SSL_RENEGOTIATION
+#define MBEDTLS_SSL_CACHE_C
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#if 0 // We should support two encryption algorithm
+#define MBEDTLS_CCM_C
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8
+#define MBEDTLS_WITH_ONLY_AEAD_CHIPERS
+#define MBEDTLS_ONLY_CCM_8_CHIPERS
+#else
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_SSL_CIPHERSUITES                        \
+        MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+#endif
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+// #define MBEDTLS_HAVE_ASM
+// #define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+#define MBEDTLS_CIPHER_MODE_CFB
+#define MBEDTLS_CIPHER_MODE_CTR
+#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECP_NIST_OPTIM
+#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
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+#define MBEDTLS_GENPRIME
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_PKCS1_V21
+#define MBEDTLS_SELF_TEST
+#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#define MBEDTLS_SSL_FALLBACK_SCSV
+#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+#define MBEDTLS_SSL_PROTO_TLS1
+#define MBEDTLS_SSL_PROTO_TLS1_1
+#define MBEDTLS_SSL_ALPN
+#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+#define MBEDTLS_SSL_SESSION_TICKETS
+#define MBEDTLS_SSL_EXPORT_KEYS
+// #define MBEDTLS_SSL_SERVER_NAME_INDICATION
+#define MBEDTLS_SSL_TRUNCATED_HMAC
+#define MBEDTLS_VERSION_FEATURES
+#define MBEDTLS_VERSION_C
+// #define MBEDTLS_AESNI_C
+#define MBEDTLS_ARC4_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_BLOWFISH_C
+#define MBEDTLS_CAMELLIA_C
+#define MBEDTLS_CERTS_C
+#define MBEDTLS_DES_C
+#define MBEDTLS_DHM_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_GCM_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+// #define MBEDTLS_PADLOCK_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PKCS12_C
+#define MBEDTLS_RIPEMD160_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_TICKET_C
+// #define MBEDTLS_X509_CHECK_KEY_USAGE
+// #define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+// #define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+// #define MBEDTLS_X509_USE_C
+// #define MBEDTLS_X509_CRT_PARSE_C
+// #define MBEDTLS_X509_CRL_PARSE_C
+// #define MBEDTLS_X509_CSR_PARSE_C
+// #define MBEDTLS_X509_CREATE_C
+// #define MBEDTLS_X509_CRT_WRITE_C
+// #define MBEDTLS_X509_CSR_WRITE_C
+#define MBEDTLS_XTEA_C
+#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+#define MBEDTLS_SHA1_C
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */

+ 209 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/mbed_port.c

@@ -0,0 +1,209 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+/**
+ *  DATE                AUTHOR      INSTRUCTION
+ *  2020-02-18 09:00  zhangqianfu  The first version
+ *
+ */
+
+#include <string.h>
+#include <dtls_al.h>
+#include <dtls_interface.h>
+#include "mbedtls/platform.h"
+
+#if defined(MBEDTLS_DEBUG_C)
+static void mbed_port_debug( void *ctx, int level,
+                      const char *file, int line,
+                      const char *str )
+{
+    const char *p, *basename;
+
+    /* Extract basename from file */
+    for( p = basename = file; *p != '\0'; p++ )
+        if( *p == '/' || *p == '\\' )
+            basename = p + 1;
+
+    printf("%s:%04d: |%d| %s", basename, line, level, str );
+}
+#endif
+
+en_dtls_al_err_t mbed_new(dtls_al_para_t *para, void **handle)
+{
+
+    en_dtls_al_err_t ret = EN_DTLS_AL_ERR_PARA;
+    mbedtls_ssl_context  *ssl;
+    dtls_establish_info_s einfo;
+    char  plat_type;
+
+    if(para->security.type == EN_DTLS_AL_SECURITY_TYPE_CERT)
+    {
+        einfo.psk_or_cert = VERIFY_WITH_CERT;
+
+        einfo.v.c.ca_cert = para->security.u.cert.server_ca;
+        einfo.v.c.cert_len = para->security.u.cert.server_ca_len;
+        einfo.v.c.client_ca = para->security.u.cert.client_ca;
+        einfo.v.c.client_ca_len = para->security.u.cert.client_ca_len;
+        einfo.v.c.client_pk = para->security.u.cert.client_pk;
+        einfo.v.c.client_pk_len = para->security.u.cert.client_pk_len;
+        einfo.v.c.client_pk_pwd = para->security.u.cert.client_pk_pwd;
+        einfo.v.c.client_pk_pwd_len = para->security.u.cert.client_pk_pwd_len;
+    }
+    else
+    {
+        einfo.psk_or_cert  = VERIFY_WITH_PSK;
+        einfo.v.p.psk = para->security.u.psk.psk_key;
+        einfo.v.p.psk_len = para->security.u.psk.psk_key_len;
+        einfo.v.p.psk_identity = para->security.u.psk.psk_id;
+    }
+
+    if(para->istcp)
+    {
+        einfo.udp_or_tcp = MBEDTLS_NET_PROTO_TCP;
+    }
+    else
+    {
+        einfo.udp_or_tcp = MBEDTLS_NET_PROTO_UDP;
+    }
+
+
+    if(para->isclient)
+    {
+        plat_type = MBEDTLS_SSL_IS_CLIENT;
+    }
+    else
+    {
+        plat_type = MBEDTLS_SSL_IS_SERVER;
+    }
+
+    ssl = dtls_ssl_new(&einfo, plat_type);
+
+    if(NULL != ssl)
+    {
+        *handle = ssl;
+        ret = EN_DTLS_AL_ERR_OK;
+
+        #if defined(MBEDTLS_DEBUG_C)
+            mbedtls_debug_set_threshold(10);
+            mbedtls_ssl_conf_dbg (ssl->conf,mbed_port_debug,NULL);
+        #endif
+    }
+
+    return ret;
+}
+
+
+en_dtls_al_err_t mbed_destroy(void *handle)
+{
+    en_dtls_al_err_t ret = EN_DTLS_AL_ERR_PARA;
+    if(NULL != handle)
+    {
+        dtls_ssl_destroy(handle);
+        ret = EN_DTLS_AL_ERR_OK;
+    }
+    return ret;
+}
+
+
+///< make it return as normal socket return
+
+int mbed_write(void *handle, uint8_t *buf, size_t len,int timeout)
+{
+
+    int ret;
+
+    ret = dtls_write(handle, buf,len);
+
+    return ret;
+}
+
+
+int mbed_read( void *handle, unsigned char *buf, size_t len, int timeout)
+{
+    int ret;
+
+    ret = dtls_read(handle, buf,len,timeout);
+
+    return ret;
+}
+
+int dtls_shakehand(mbedtls_ssl_context *ssl, const dtls_shakehand_info_s *info);
+
+
+int mbed_connect(void *handle,const char *server_ip, const char *server_port,int timeout)
+{
+    int ret = -1;
+    dtls_shakehand_info_s  sinfo;
+
+
+    (void) memset(&sinfo, 0, sizeof(sinfo));
+
+
+    sinfo.u.c.host = server_ip;
+    sinfo.u.c.port = server_port;
+
+    sinfo.client_or_server = MBEDTLS_SSL_IS_CLIENT;
+    sinfo.udp_or_tcp = MBEDTLS_NET_PROTO_TCP;
+    sinfo.timeout = timeout;
+
+    ret = dtls_shakehand( handle,&sinfo);
+
+    return ret;
+}
+
+static const dtls_al_t  s_mbedtls_io =
+{
+    .name = "mbed",
+    .io = {
+            .io_new = mbed_new,
+            .io_connect = mbed_connect,
+            .io_read = mbed_read,
+            .io_write = mbed_write,
+            .io_destroy = mbed_destroy,
+    },
+};
+
+
+
+int dtls_imp_init(void)
+{
+    int ret =-1;
+
+    (void)mbedtls_platform_set_calloc_free(calloc, free);
+    // (void)mbedtls_platform_set_snprintf(snprintf);
+    // (void)mbedtls_platform_set_printf(printf);
+    ret = dtls_al_install(&s_mbedtls_io);
+
+    return ret;
+}
+

+ 101 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/timing_alt.c

@@ -0,0 +1,101 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2016-2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * 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 the copyright holder 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulations.
+ *---------------------------------------------------------------------------*/
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+
+#include "cmsis_os2.h"
+#include <timing_alt.h>
+
+unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)
+{
+    struct mbedtls_timing_hr_time now;
+    now.timer_ms = osKernelGetTickCount() * (1000 / 1000);;
+
+    if (reset)
+    {
+        val->timer_ms = now.timer_ms;
+    }
+
+    return (unsigned long)(now.timer_ms - val->timer_ms);
+}
+
+/*
+ * 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;
+}
+

+ 97 - 0
iot_link/network/dtls/mbedtls/mbedtls_port/timing_alt.h

@@ -0,0 +1,97 @@
+/**
+ * \file timing_alt.h
+ *
+ * \brief Portable interface to the CPU cycle counter
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_TIMING_ALT_H
+#define MBEDTLS_TIMING_ALT_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          timer structure
+ */
+struct mbedtls_timing_hr_time
+{
+    uint64_t timer_ms;
+};
+
+/**
+ * \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;
+
+/**
+ * \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          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
+
+
+#endif /* timing_alt.h */
+

+ 58 - 0
iot_link/network/mqtt/BUILD.gn

@@ -0,0 +1,58 @@
+# Copyright (c) 2020 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
+# 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.
+
+mqtt_paho_inc = [
+    "paho_mqtt/paho/MQTTClient-C/src",
+    "paho_mqtt/paho/MQTTPacket/src",
+    "paho_mqtt/port",
+    "../../inc",
+    "//kernel/liteos_m/components/cmsis/2.0",
+    "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
+]
+
+
+mqtt_paho_src = [
+    "mqtt_al/mqtt_al.c",
+    "paho_mqtt/port/paho_mqtt_port.c",
+    "paho_mqtt/port/paho_osdepends.c",
+    "paho_mqtt/paho/MQTTClient-C/src/MQTTClient.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTConnectClient.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTConnectServer.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTDeserializePublish.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTFormat.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTPacket.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTSerializePublish.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTSubscribeClient.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTSubscribeServer.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTUnsubscribeClient.c",
+    "paho_mqtt/paho/MQTTPacket/src/MQTTUnsubscribeServer.c",
+    
+
+]
+mqtt_paho_defs = [
+    "MQTTCLIENT_PLATFORM_HEADER=paho_osdepends.h",
+
+]
+
+mqtt_cflags = [
+    "-Wno-sign-compare",
+    "-Wno-unused-parameter",
+    "-Wno-unused-function",
+]
+
+static_library("mqtt") {
+        cflags = mqtt_cflags
+        defines = mqtt_paho_defs
+        sources = mqtt_paho_src
+        include_dirs = mqtt_paho_inc
+}

+ 213 - 0
iot_link/network/mqtt/mqtt_al/mqtt_al.c

@@ -0,0 +1,213 @@
+/*----------------------------------------------------------------------------
+ * Copyright (c) <2018>, <Huawei Technologies Co., Ltd>
+ * All rights reserved.
+ * Redistributopsn and use in source and binary forms, with or without modificatopsn,
+ * are permitted provided that the following conditopsns are met:
+ * 1. Redistributopsns of source code must retain the above copyright notice, this list of
+ * conditopsns and the following disclaimer.
+ * 2. Redistributopsns in binary form must reproduce the above copyright notice, this list
+ * of conditopsns and the following disclaimer in the documentatopsn and/or other materials
+ * provided with the distributopsn.
+ * 3. Neither the name of the copyright holder nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific propsr written
+ * permissopsn.
+ * 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 INTERRUPTopsN) 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.
+ *---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+ * Notice of Export Control Law
+ * ===============================================
+ * Huawei LiteOS may be subject to applicable export control laws and regulatopsns, which might
+ * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
+ * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
+ * applicable export control laws and regulatopsns.
+ *---------------------------------------------------------------------------*/
+
+#include <stdint.h>
+#include <stddef.h>
+#include <link_log.h>
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+
+#include <mqtt_al.h>
+
+
+typedef struct
+{
+    mqtt_al_op_t  *ops;
+    mqtt_al_op_t   mem;
+}mqtt_al_op_cb_t;
+
+static mqtt_al_op_cb_t   s_mqtt_al_op_cb;
+
+
+/////////////////CREATE THE API FOR THE MQTT LIB////////////////////////////////
+int mqtt_al_install(mqtt_al_op_t *op)
+{
+    int ret = -1;
+    if((NULL != op)&&(NULL == s_mqtt_al_op_cb.ops))
+    {
+        s_mqtt_al_op_cb.mem  = *op;
+        s_mqtt_al_op_cb.ops = &s_mqtt_al_op_cb.mem;
+
+        ret = 0;
+    }
+
+    return ret;
+}
+
+int mqtt_al_uninstall()
+{
+    int ret = -1;
+    if(NULL != s_mqtt_al_op_cb.ops)
+    {
+        s_mqtt_al_op_cb.ops = NULL;
+
+        ret = 0;
+    }
+
+    return ret;
+}
+
+//////////////////////////CREATE THE API FOR THE MQTT APPLICATopsN///////////////
+
+__attribute__((weak))  int mqtt_imp_init(void)
+{
+    LINK_LOG_DEBUG("%s:###please implement mqtt by yourself####",__FUNCTION__);
+    return -1;
+}
+
+int mqtt_al_init(void)
+{
+    int ret;
+
+    ret = mqtt_imp_init();
+    LINK_LOG_DEBUG("IOT_LINK:DO MQTT LOAD-IMPLEMENT RET:%d",ret);
+
+    return ret;
+}
+
+int  mqtt_al_deinit()
+{
+
+    int ret = 0;
+
+    //maybe need special code here
+
+    return ret;
+}
+
+void * mqtt_al_connect( mqtt_al_conpara_t *conpara)
+{
+
+    void *ret = NULL;
+
+    if((NULL != conpara) && (NULL != s_mqtt_al_op_cb.ops) && (NULL != s_mqtt_al_op_cb.ops->connect))
+    {
+        ret = s_mqtt_al_op_cb.ops->connect(conpara);
+    }
+
+    return ret;
+
+}
+
+
+int mqtt_al_disconnect(void *handle)
+{
+
+    int ret = -1;
+
+    if((NULL != handle) && (NULL != s_mqtt_al_op_cb.ops) && (NULL != s_mqtt_al_op_cb.ops->disconnect))
+    {
+        ret = s_mqtt_al_op_cb.ops->disconnect(handle);
+    }
+
+    return ret;
+
+}
+
+
+int mqtt_al_publish(void *handle, mqtt_al_pubpara_t *pubpara)
+{
+
+    int ret = -1;
+
+    if((NULL != handle) && (NULL != pubpara) &&\
+       (NULL != s_mqtt_al_op_cb.ops) && (NULL != s_mqtt_al_op_cb.ops->publish))
+    {
+        ret = s_mqtt_al_op_cb.ops->publish(handle,pubpara);
+    }
+
+    return ret;
+
+}
+
+
+int mqtt_al_subscribe(void *handle, mqtt_al_subpara_t *subpara)
+{
+
+    int ret = -1;
+
+    if((NULL != handle) && (NULL != subpara) &&\
+       (NULL != s_mqtt_al_op_cb.ops) && (NULL != s_mqtt_al_op_cb.ops->subscribe))
+    {
+        ret = s_mqtt_al_op_cb.ops->subscribe(handle,subpara);
+    }
+
+    return ret;
+
+}
+
+
+int mqtt_al_unsubscribe(void *handle, mqtt_al_unsubpara_t *unsubpara)
+{
+
+    int ret = -1;
+
+    if((NULL != handle) && (NULL != unsubpara) && \
+        (NULL != s_mqtt_al_op_cb.ops) && (NULL != s_mqtt_al_op_cb.ops->unsubscribe))
+    {
+        ret = s_mqtt_al_op_cb.ops->unsubscribe(handle,unsubpara);
+    }
+
+    return ret;
+
+}
+
+en_mqtt_al_connect_state mqtt_al_check_status(void *handle)
+{
+
+    en_mqtt_al_connect_state ret = en_mqtt_al_connect_err;
+
+    if((NULL != handle) && (NULL != s_mqtt_al_op_cb.ops) && (NULL != s_mqtt_al_op_cb.ops->check_status))
+    {
+        ret = s_mqtt_al_op_cb.ops->check_status(handle);
+    }
+
+    return ret;
+}
+
+
+
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cpluscplus */
+#endif /* __cpluscplus */
+
+

+ 22 - 0
iot_link/network/mqtt/paho_mqtt/Readme.md

@@ -0,0 +1,22 @@
+#### PAHO库修改说明
+
+在PAHO v1.1.0版本上修改,修改的主要点如下:
+
+| 修改级别 | 修改内容                                                     |
+| :------- | ------------------------------------------------------------ |
+| 修复     | 原库定义的SUCCESS会引起冲突,C50版本重新命                   |
+| 修复     | MQTTClientInit原库没有返回值,C50版本修改为有返回值,并增加了MQTTClientDeinit函数 |
+| 修复     | MQTTClientInit原库没有检查互斥锁返回值,C50版本修改为检查返回值 |
+| 优化     | C50版本修改了TOPIC匹配函数(用于收到消息时投递消息),应该是引用了某个库的API函数,暂时未查阅到 |
+| 修复     | C50在CYCLE中增加了UNSUBACK的处理                             |
+| 修改     | 原库版本的KEEPALIVE逻辑为上次发送和上次接收为或逻辑,C50版本修改为与逻辑 |
+| 修改     | C50版本修改了超时重传逻辑(QOS2)                              |
+| 修复     | C50版本的MQTTYield函数使用互斥锁进行互斥,避免数据冲突       |
+| 修改     | 原库版本订阅函数的回调函数不支持ARG参数,修改为带参数模式    |
+
+修复:原版本或者库存在显性或者隐性BUG,进行修复
+
+修改:原版本不满足现有需求或者功能,需要修改
+
+优化:对某些实现做了更合适的修改
+

+ 184 - 0
iot_link/network/mqtt/paho_mqtt/paho/.cproject

@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?><?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="cdt.managedbuild.config.gnu.so.debug.1049786922">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.so.debug.1049786922" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+				<externalSettings>
+					<externalSetting>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/embedded-C"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/embedded-C/Debug"/>
+						<entry flags="RESOLVED" kind="libraryFile" name="embedded-C" srcPrefixMapping="" srcRootPath=""/>
+					</externalSetting>
+				</externalSettings>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.so.debug.1049786922" name="Debug" parent="cdt.managedbuild.config.gnu.so.debug">
+					<folderInfo id="cdt.managedbuild.config.gnu.so.debug.1049786922." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.so.debug.1188656409" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.so.debug">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.so.debug.84156419" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.so.debug"/>
+							<builder buildPath="${workspace_loc:/embedded-C}/Debug" id="cdt.managedbuild.target.gnu.builder.so.debug.1027987368" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.so.debug"/>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1945555299" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.so.debug.531983260" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.so.debug">
+								<option id="gnu.cpp.compiler.so.debug.option.optimization.level.2125064804" name="Optimization Level" superClass="gnu.cpp.compiler.so.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.so.debug.option.debugging.level.43422664" name="Debug Level" superClass="gnu.cpp.compiler.so.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.so.debug.908163257" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.so.debug">
+								<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.so.debug.option.optimization.level.1025282191" name="Optimization Level" superClass="gnu.c.compiler.so.debug.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.so.debug.option.debugging.level.1611217070" name="Debug Level" superClass="gnu.c.compiler.so.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+								<option id="gnu.c.compiler.option.include.paths.1830522647" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/embedded-C/MQTTPacket/src}&quot;"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.103641925" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.so.debug.1517956238" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.so.debug">
+								<option defaultValue="true" id="gnu.c.link.so.debug.option.shared.1823245824" name="Shared (-shared)" superClass="gnu.c.link.so.debug.option.shared" valueType="boolean"/>
+								<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.936512212" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.so.debug.1821422645" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.so.debug">
+								<option defaultValue="true" id="gnu.cpp.link.so.debug.option.shared.2029194272" name="Shared (-shared)" superClass="gnu.cpp.link.so.debug.option.shared" valueType="boolean"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.so.debug.65794919" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.so.debug">
+								<option id="gnu.both.asm.option.include.paths.624151837" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"/>
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.544886244" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<folderInfo id="cdt.managedbuild.config.gnu.so.debug.1049786922.2012134380" name="/" resourcePath="MQTTPacket/src">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.so.debug.373936532" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.so.debug" unusedChildren="">
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.826338972" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base.1945555299"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.so.debug.162520987" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.so.debug.531983260"/>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.so.debug.411531358" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.so.debug.908163257">
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1008566315" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.so.debug.1559782853" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.so.debug.1517956238"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.so.debug.550864828" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.so.debug.1821422645"/>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.so.debug.580263878" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.so.debug.65794919">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1150650244" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTClient/src"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTPacket/samples"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTPacket/src"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.config.gnu.so.release.374902706">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.so.release.374902706" moduleId="org.eclipse.cdt.core.settings" name="Release">
+				<externalSettings>
+					<externalSetting>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/embedded-C"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/embedded-C/Release"/>
+						<entry flags="RESOLVED" kind="libraryFile" name="embedded-C" srcPrefixMapping="" srcRootPath=""/>
+					</externalSetting>
+				</externalSettings>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.so.release.374902706" name="Release" parent="cdt.managedbuild.config.gnu.so.release">
+					<folderInfo id="cdt.managedbuild.config.gnu.so.release.374902706." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.so.release.212092660" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.so.release">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.so.release.115420820" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.so.release"/>
+							<builder buildPath="${workspace_loc:/embedded-C}/Release" id="cdt.managedbuild.target.gnu.builder.so.release.1607415402" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.so.release"/>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1822133490" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.so.release.482703733" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.so.release">
+								<option id="gnu.cpp.compiler.so.release.option.optimization.level.1208586309" name="Optimization Level" superClass="gnu.cpp.compiler.so.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.so.release.option.debugging.level.1769747565" name="Debug Level" superClass="gnu.cpp.compiler.so.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.so.release.1838975818" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.so.release">
+								<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.so.release.option.optimization.level.589960637" name="Optimization Level" superClass="gnu.c.compiler.so.release.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.so.release.option.debugging.level.940644097" name="Debug Level" superClass="gnu.c.compiler.so.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+								<option id="gnu.c.compiler.option.include.paths.1739833982" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/embedded-C/src}&quot;"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1074589063" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.so.release.1807144456" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.so.release">
+								<option defaultValue="true" id="gnu.c.link.so.release.option.shared.11876845" name="Shared (-shared)" superClass="gnu.c.link.so.release.option.shared" valueType="boolean"/>
+								<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.289563790" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.so.release.395214940" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.so.release">
+								<option defaultValue="true" id="gnu.cpp.link.so.release.option.shared.594459767" name="Shared (-shared)" superClass="gnu.cpp.link.so.release.option.shared" valueType="boolean"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.so.release.2061779220" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.so.release">
+								<option id="gnu.both.asm.option.include.paths.1657504482" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/embedded-C/src}&quot;"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1949893916" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<folderInfo id="cdt.managedbuild.config.gnu.so.release.374902706.734460083" name="/" resourcePath="MQTTPacket/src">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.so.release.1128610593" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.so.release" unusedChildren="">
+							<tool id="cdt.managedbuild.tool.gnu.archiver.base.1066241773" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base.1822133490"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.so.release.771591369" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.so.release.482703733"/>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.so.release.1125066379" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.so.release.1838975818">
+								<option id="gnu.c.compiler.option.include.paths.271775004" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/embedded-C/MQTTPacket/src}&quot;"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.995178283" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.so.release.1173497209" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.so.release.1807144456"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.so.release.2074144887" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.so.release.395214940"/>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.so.release.239315112" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.so.release.2061779220">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2006922113" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry excluding="src|MQTTClient|MQTTPacket/samples|samples" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+						<entry excluding="src" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTClient"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTClient/src"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTPacket/samples"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="embedded-C.cdt.managedbuild.target.gnu.so.1829285851" name="Shared Library" projectType="cdt.managedbuild.target.gnu.so"/>
+	</storageModule>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.so.release.374902706;cdt.managedbuild.config.gnu.so.release.374902706.;cdt.managedbuild.tool.gnu.c.compiler.so.release.1838975818;cdt.managedbuild.tool.gnu.c.compiler.input.1074589063">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.so.debug.1049786922;cdt.managedbuild.config.gnu.so.debug.1049786922.;cdt.managedbuild.tool.gnu.c.compiler.so.debug.908163257;cdt.managedbuild.tool.gnu.c.compiler.input.103641925">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		</scannerConfigBuildInfo>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="refreshScope" versionNumber="2">
+		<configuration configurationName="Debug">
+			<resource resourceType="PROJECT" workspacePath="/embedded-C"/>
+		</configuration>
+		<configuration configurationName="Release">
+			<resource resourceType="PROJECT" workspacePath="/embedded-C"/>
+		</configuration>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+</cproject>

+ 8 - 0
iot_link/network/mqtt/paho_mqtt/paho/.gitignore

@@ -0,0 +1,8 @@
+/dep/
+/build/
+/build.paho/
+*.swp
+*.pyc
+/doc/MQTTClient/
+/doc/MQTTPacket/
+/doc/MQTTClient-C/

+ 26 - 0
iot_link/network/mqtt/paho_mqtt/paho/.project

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>embedded-C</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>

+ 163 - 0
iot_link/network/mqtt/paho_mqtt/paho/.settings/org.eclipse.cdt.core.prefs

@@ -0,0 +1,163 @@
+eclipse.preferences.version=1
+org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.cdt.core.formatter.alignment_for_assignment=16
+org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
+org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.cdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=34
+org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18
+org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0
+org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
+org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
+org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
+org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.cdt.core.formatter.alignment_for_member_access=0
+org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16
+org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=next_line
+org.eclipse.cdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=next_line
+org.eclipse.cdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line
+org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1
+org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true
+org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true
+org.eclipse.cdt.core.formatter.compact_else_if=true
+org.eclipse.cdt.core.formatter.continuation_indentation=2
+org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
+org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0
+org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
+org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false
+org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false
+org.eclipse.cdt.core.formatter.indent_empty_lines=false
+org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.cdt.core.formatter.indentation.size=4
+org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
+org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.cdt.core.formatter.join_wrapped_lines=true
+org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.cdt.core.formatter.lineSplit=80
+org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.cdt.core.formatter.tabulation.char=tab
+org.eclipse.cdt.core.formatter.tabulation.size=4
+org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false

+ 3 - 0
iot_link/network/mqtt/paho_mqtt/paho/.settings/org.eclipse.cdt.ui.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+formatter_profile=org.eclipse.cdt.ui.default.allman_profile
+formatter_settings_version=1

+ 29 - 0
iot_link/network/mqtt/paho_mqtt/paho/.travis.yml

@@ -0,0 +1,29 @@
+sudo: true
+language: c
+
+compiler:
+  - gcc
+
+os:
+  - linux
+
+sudo: required
+
+before_install:
+  - ./travis-install.sh
+
+script:
+  - if [[ "$COVERITY_SCAN_BRANCH" != 1 ]]; then ./travis-build.sh; fi
+
+addons:
+  apt:
+    sources:
+      - george-edison55-precise-backports # cmake 3.2.3 / doxygen 1.8.3
+      - sourceline: 'ppa:mosquitto-dev/mosquitto-ppa'
+    packages:
+      - cmake
+      - cmake-data
+      - mosquitto
+      - doxygen
+
+

+ 46 - 0
iot_link/network/mqtt/paho_mqtt/paho/CMakeLists.txt

@@ -0,0 +1,46 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+cmake_minimum_required(VERSION 2.8)
+project (embedded-mqtt)
+set(CMAKE_BUILD_TYPE Debug)
+
+message(STATUS "CMake version: " ${CMAKE_VERSION})
+message(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME})
+
+set(CMAKE_SCRIPTS "${CMAKE_SOURCE_DIR}/cmake")
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
+
+## build settings
+set(PAHO_VERSION_MAJOR 1)
+set(PAHO_VERSION_MINOR 0)
+set(PAHO_VERSION_PATCH 0)
+set(CLIENT_VERSION ${PAHO_VERSION_MAJOR}.${PAHO_VERSION_MINOR}.${PAHO_VERSION_PATCH})
+
+string(TIMESTAMP BUILD_TIMESTAMP UTC)
+message(STATUS "Timestamp is ${BUILD_TIMESTAMP}")
+
+set(CPACK_PACKAGE_VERSION_MAJOR ${PAHO_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${PAHO_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${PAHO_VERSION_PATCH})
+include(CPack)
+
+include_directories(MQTTPacket/src)
+
+enable_testing()
+ADD_SUBDIRECTORY(MQTTPacket)
+ADD_SUBDIRECTORY(MQTTClient)
+ADD_SUBDIRECTORY(MQTTClient-C)

+ 66 - 0
iot_link/network/mqtt/paho_mqtt/paho/CONTRIBUTING.md

@@ -0,0 +1,66 @@
+# Contributing to Paho
+
+Thanks for your interest in this project!
+
+You can contribute bugfixes and new features by sending pull requests through GitHub.
+
+## Legal
+
+In order for your contribution to be accepted, it must comply with the Eclipse Foundation IP policy.
+
+Please read the [Eclipse Foundation policy on accepting contributions via Git](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git).
+
+1. Sign the [Eclipse CLA](http://www.eclipse.org/legal/CLA.php)
+  1. Register for an Eclipse Foundation User ID. You can register [here](https://dev.eclipse.org/site_login/createaccount.php).
+  2. Log into the [Projects Portal](https://projects.eclipse.org/), and click on the '[Eclipse CLA](https://projects.eclipse.org/user/sign/cla)' link.
+2. Go to your [account settings](https://dev.eclipse.org/site_login/myaccount.php#open_tab_accountsettings) and add your GitHub username to your account.
+3. Make sure that you _sign-off_ your Git commits in the following format:
+  ``` Signed-off-by: John Smith <johnsmith@nowhere.com> ``` This is usually at the bottom of the commit message. You can automate this by adding the '-s' flag when you make the commits. e.g.   ```git commit -s -m "Adding a cool feature"```
+4. Ensure that the email address that you make your commits with is the same one you used to sign up to the Eclipse Foundation website with.
+
+## Contributing a change
+
+1. [Fork the repository on GitHub](https://github.com/eclipse/paho.mqtt.embedded-c/fork)
+2. Clone the forked repository onto your computer: ``` git clone https://github.com/<your username>/paho.mqtt.embedded-c.git ```
+3. Create a new branch from the latest ```develop``` branch with ```git checkout -b YOUR_BRANCH_NAME origin/develop```
+4. Make your changes
+5. If developing a new feature, make sure to include JUnit tests.
+6. Ensure that all new and existing tests pass.
+7. Commit the changes into the branch: ``` git commit -s ``` Make sure that your commit message is meaningful and describes your changes correctly.
+8. If you have a lot of commits for the change, squash them into a single / few commits.
+9. Push the changes in your branch to your forked repository.
+10. Finally, go to [https://github.com/eclipse/paho.mqtt.embedded-c](https://github.com/eclipse/paho.mqtt.embedded-c) and create a pull request from your "YOUR_BRANCH_NAME" branch to the ```develop``` one to request review and merge of the commits in your pushed branch.
+
+
+What happens next depends on the content of the patch. If it is 100% authored
+by the contributor and is less than 1000 lines (and meets the needs of the
+project), then it can be pulled into the main repository. If not, more steps
+are required. These are detailed in the
+[legal process poster](http://www.eclipse.org/legal/EclipseLegalProcessPoster.pdf).
+
+
+
+## Developer resources:
+
+
+Information regarding source code management, builds, coding standards, and more.
+
+- [https://projects.eclipse.org/projects/iot.paho/developer](https://projects.eclipse.org/projects/iot.paho/developer)
+
+Contact:
+--------
+
+Contact the project developers via the project's development
+[mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev).
+
+Search for bugs:
+----------------
+
+This project uses GitHub Issues here: [github.com/eclipse/paho.mqtt.embedded-c/issues](https://github.com/eclipse/paho.mqtt.embedded-c/issues) to track ongoing development and issues.
+
+Create a new bug:
+-----------------
+
+Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome!
+
+- [Create new Paho bug](https://github.com/eclipse/paho.mqtt.embedded-c/issues)

+ 45 - 0
iot_link/network/mqtt/paho_mqtt/paho/Debug/makefile

@@ -0,0 +1,45 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+-include ../makefile.init
+
+RM := rm -rf
+
+# All of the sources participating in the build are defined here
+-include sources.mk
+-include MQTTPacket/src/subdir.mk
+-include MQTTPacket/samples/subdir.mk
+-include subdir.mk
+-include objects.mk
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(strip $(C_DEPS)),)
+-include $(C_DEPS)
+endif
+endif
+
+-include ../makefile.defs
+
+# Add inputs and outputs from these tool invocations to the build variables 
+
+# All Target
+all: libembedded-C.so
+
+# Tool invocations
+libembedded-C.so: $(OBJS) $(USER_OBJS)
+	@echo 'Building target: $@'
+	@echo 'Invoking: GCC C Linker'
+	gcc -shared -o "libembedded-C.so" $(OBJS) $(USER_OBJS) $(LIBS)
+	@echo 'Finished building target: $@'
+	@echo ' '
+
+# Other Targets
+clean:
+	-$(RM) $(C_DEPS)$(LIBRARIES)$(OBJS) libembedded-C.so
+	-@echo ' '
+
+.PHONY: all clean dependents
+.SECONDARY:
+
+-include ../makefile.targets

+ 8 - 0
iot_link/network/mqtt/paho_mqtt/paho/Debug/objects.mk

@@ -0,0 +1,8 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+USER_OBJS :=
+
+LIBS :=
+

+ 18 - 0
iot_link/network/mqtt/paho_mqtt/paho/Debug/sources.mk

@@ -0,0 +1,18 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+ASM_SRCS := 
+OBJ_SRCS := 
+S_UPPER_SRCS := 
+C_SRCS := 
+O_SRCS := 
+C_DEPS := 
+LIBRARIES := 
+OBJS := 
+
+# Every subdirectory with source files must be described here
+SUBDIRS := \
+MQTTPacket/src \
+MQTTPacket/samples \
+

+ 4 - 0
iot_link/network/mqtt/paho_mqtt/paho/Debug/src/MQTTDeserializeConnect.d

@@ -0,0 +1,4 @@
+src/MQTTDeserializeConnect.d src/MQTTDeserializeConnect.o: \
+ ../src/MQTTDeserializeConnect.c ../src/StackTrace.h
+
+../src/StackTrace.h:

+ 48 - 0
iot_link/network/mqtt/paho_mqtt/paho/Debug/src/subdir.mk

@@ -0,0 +1,48 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+# Add inputs and outputs from these tool invocations to the build variables 
+C_SRCS += \
+../src/MQTTConnectClient.c \
+../src/MQTTConnectServer.c \
+../src/MQTTDeserializePublish.c \
+../src/MQTTPacket.c \
+../src/MQTTSerializePublish.c \
+../src/MQTTSubscribeClient.c \
+../src/MQTTSubscribeServer.c \
+../src/MQTTUnsubscribeClient.c \
+../src/MQTTUnsubscribeServer.c 
+
+C_DEPS += \
+./src/MQTTConnectClient.d \
+./src/MQTTConnectServer.d \
+./src/MQTTDeserializePublish.d \
+./src/MQTTPacket.d \
+./src/MQTTSerializePublish.d \
+./src/MQTTSubscribeClient.d \
+./src/MQTTSubscribeServer.d \
+./src/MQTTUnsubscribeClient.d \
+./src/MQTTUnsubscribeServer.d 
+
+OBJS += \
+./src/MQTTConnectClient.o \
+./src/MQTTConnectServer.o \
+./src/MQTTDeserializePublish.o \
+./src/MQTTPacket.o \
+./src/MQTTSerializePublish.o \
+./src/MQTTSubscribeClient.o \
+./src/MQTTSubscribeServer.o \
+./src/MQTTUnsubscribeClient.o \
+./src/MQTTUnsubscribeServer.o 
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/%.o: ../src/%.c
+	@echo 'Building file: $<'
+	@echo 'Invoking: GCC C Compiler'
+	gcc -I"/home/icraggs/work/paho/org.eclipse.paho.mqtt.embedded-c/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
+	@echo 'Finished building: $<'
+	@echo ' '
+
+

+ 21 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/CMakeLists.txt

@@ -0,0 +1,21 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+project("paho-mqttclient" C)
+
+ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(samples)
+ADD_SUBDIRECTORY(test)

+ 17 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/CMakeLists.txt

@@ -0,0 +1,17 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+add_subdirectory(linux)

+ 95 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/FreeRTOS/MQTTEcho.c

@@ -0,0 +1,95 @@
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+
+#define MQTT_TASK 1
+#include "MQTTClient.h"
+
+
+void messageArrived(MessageData* data)
+{
+	printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
+		data->message->payloadlen, data->message->payload);
+}
+
+static void prvMQTTEchoTask(void *pvParameters)
+{
+	/* connect to m2m.eclipse.org, subscribe to a topic, send and receive messages regularly every 1 sec */
+	MQTTClient client;
+	Network network;
+	unsigned char sendbuf[80], readbuf[80];
+	int rc = 0, 
+		count = 0;
+	MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
+
+	pvParameters = 0;
+	NetworkInit(&network);
+	MQTTClientInit(&client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf));
+
+	char* address = "iot.eclipse.org";
+	if ((rc = NetworkConnect(&network, address, 1883)) != 0)
+		printf("Return code from network connect is %d\n", rc);
+
+#if defined(MQTT_TASK)
+	if ((rc = MQTTStartTask(&client)) != pdPASS)
+		printf("Return code from start tasks is %d\n", rc);
+#endif
+
+	connectData.MQTTVersion = 3;
+	connectData.clientID.cstring = "FreeRTOS_sample";
+
+	if ((rc = MQTTConnect(&client, &connectData)) != 0)
+		printf("Return code from MQTT connect is %d\n", rc);
+	else
+		printf("MQTT Connected\n");
+
+	if ((rc = MQTTSubscribe(&client, "FreeRTOS/sample/#", 2, messageArrived)) != 0)
+		printf("Return code from MQTT subscribe is %d\n", rc);
+
+	while (++count)
+	{
+		MQTTMessage message;
+		char payload[30];
+
+		message.qos = 1;
+		message.retained = 0;
+		message.payload = payload;
+		sprintf(payload, "message number %d", count);
+		message.payloadlen = strlen(payload);
+
+		if ((rc = MQTTPublish(&client, "FreeRTOS/sample/a", &message)) != 0)
+			printf("Return code from MQTT publish is %d\n", rc);
+#if !defined(MQTT_TASK)
+		if ((rc = MQTTYield(&client, 1000)) != 0)
+			printf("Return code from yield is %d\n", rc);
+#endif
+	}
+
+	/* do not return */
+}
+
+
+void vStartMQTTTasks(uint16_t usTaskStackSize, UBaseType_t uxTaskPriority)
+{
+	BaseType_t x = 0L;
+
+	xTaskCreate(prvMQTTEchoTask,	/* The function that implements the task. */
+			"MQTTEcho0",			/* Just a text name for the task to aid debugging. */
+			usTaskStackSize,	/* The stack size is defined in FreeRTOSIPConfig.h. */
+			(void *)x,		/* The task parameter, not used in this case. */
+			uxTaskPriority,		/* The priority assigned to the task is defined in FreeRTOSConfig.h. */
+			NULL);				/* The task handle is not used. */
+}
+/*-----------------------------------------------------------*/
+
+

+ 24 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/linux/CMakeLists.txt

@@ -0,0 +1,24 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+
+add_executable(
+  stdoutsubc
+  stdoutsub.c
+)
+target_link_libraries(stdoutsubc paho-embed-mqtt3cc paho-embed-mqtt3c)
+target_include_directories(stdoutsubc PRIVATE "../../src" "../../src/linux")
+target_compile_definitions(stdoutsubc PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h)

+ 3 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/linux/build.sh

@@ -0,0 +1,3 @@
+cp ../../src/MQTTClient.c .
+sed -e 's/""/"MQTTLinux.h"/g' ../../src/MQTTClient.h > MQTTClient.h
+gcc stdoutsub.c -I ../../src -I ../../src/linux -I ../../../MQTTPacket/src MQTTClient.c ../../src/linux/MQTTLinux.c ../../../MQTTPacket/src/MQTTFormat.c  ../../../MQTTPacket/src/MQTTPacket.c ../../../MQTTPacket/src/MQTTDeserializePublish.c ../../../MQTTPacket/src/MQTTConnectClient.c ../../../MQTTPacket/src/MQTTSubscribeClient.c ../../../MQTTPacket/src/MQTTSerializePublish.c -o stdoutsub ../../../MQTTPacket/src/MQTTConnectServer.c ../../../MQTTPacket/src/MQTTSubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeClient.c -DMQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h

+ 254 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/samples/linux/stdoutsub.c

@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2016 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution. 
+ *
+ * The Eclipse Public License is available at 
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial contribution
+ *    Ian Craggs - change delimiter option from char to string
+ *    Al Stockdill-Mander - Version using the embedded C client
+ *    Ian Craggs - update MQTTClient function names
+ *******************************************************************************/
+
+/*
+ 
+ stdout subscriber
+ 
+ compulsory parameters:
+ 
+  topic to subscribe to
+ 
+ defaulted parameters:
+ 
+	--host localhost
+	--port 1883
+	--qos 2
+	--delimiter \n
+	--clientid stdout_subscriber
+	
+	--userid none
+	--password none
+
+ for example:
+
+    stdoutsub topic/of/interest --host iot.eclipse.org
+
+*/
+#include <stdio.h>
+#include <memory.h>
+#include "MQTTClient.h"
+
+#include <stdio.h>
+#include <signal.h>
+
+#include <sys/time.h>
+
+
+volatile int toStop = 0;
+
+
+void usage()
+{
+	printf("MQTT stdout subscriber\n");
+	printf("Usage: stdoutsub topicname <options>, where options are:\n");
+	printf("  --host <hostname> (default is localhost)\n");
+	printf("  --port <port> (default is 1883)\n");
+	printf("  --qos <qos> (default is 2)\n");
+	printf("  --delimiter <delim> (default is \\n)\n");
+	printf("  --clientid <clientid> (default is hostname+timestamp)\n");
+	printf("  --username none\n");
+	printf("  --password none\n");
+	printf("  --showtopics <on or off> (default is on if the topic has a wildcard, else off)\n");
+	exit(-1);
+}
+
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+
+struct opts_struct
+{
+	char* clientid;
+	int nodelimiter;
+	char* delimiter;
+	enum QoS qos;
+	char* username;
+	char* password;
+	char* host;
+	int port;
+	int showtopics;
+} opts =
+{
+	(char*)"stdout-subscriber", 0, (char*)"\n", QOS2, NULL, NULL, (char*)"localhost", 1883, 0
+};
+
+
+void getopts(int argc, char** argv)
+{
+	int count = 2;
+	
+	while (count < argc)
+	{
+		if (strcmp(argv[count], "--qos") == 0)
+		{
+			if (++count < argc)
+			{
+				if (strcmp(argv[count], "0") == 0)
+					opts.qos = QOS0;
+				else if (strcmp(argv[count], "1") == 0)
+					opts.qos = QOS1;
+				else if (strcmp(argv[count], "2") == 0)
+					opts.qos = QOS2;
+				else
+					usage();
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--host") == 0)
+		{
+			if (++count < argc)
+				opts.host = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--port") == 0)
+		{
+			if (++count < argc)
+				opts.port = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--clientid") == 0)
+		{
+			if (++count < argc)
+				opts.clientid = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--username") == 0)
+		{
+			if (++count < argc)
+				opts.username = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--password") == 0)
+		{
+			if (++count < argc)
+				opts.password = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--delimiter") == 0)
+		{
+			if (++count < argc)
+				opts.delimiter = argv[count];
+			else
+				opts.nodelimiter = 1;
+		}
+		else if (strcmp(argv[count], "--showtopics") == 0)
+		{
+			if (++count < argc)
+			{
+				if (strcmp(argv[count], "on") == 0)
+					opts.showtopics = 1;
+				else if (strcmp(argv[count], "off") == 0)
+					opts.showtopics = 0;
+				else
+					usage();
+			}
+			else
+				usage();
+		}
+		count++;
+	}
+	
+}
+
+
+void messageArrived(MessageData* md)
+{
+	MQTTMessage* message = md->message;
+
+	if (opts.showtopics)
+		printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);
+	if (opts.nodelimiter)
+		printf("%.*s", (int)message->payloadlen, (char*)message->payload);
+	else
+		printf("%.*s%s", (int)message->payloadlen, (char*)message->payload, opts.delimiter);
+	//fflush(stdout);
+}
+
+
+int main(int argc, char** argv)
+{
+	int rc = 0;
+	unsigned char buf[100];
+	unsigned char readbuf[100];
+	
+	if (argc < 2)
+		usage();
+	
+	char* topic = argv[1];
+
+	if (strchr(topic, '#') || strchr(topic, '+'))
+		opts.showtopics = 1;
+	if (opts.showtopics)
+		printf("topic is %s\n", topic);
+
+	getopts(argc, argv);	
+
+	Network n;
+	MQTTClient c;
+
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+
+	NetworkInit(&n);
+	NetworkConnect(&n, opts.host, opts.port);
+	MQTTClientInit(&c, &n, 1000, buf, 100, readbuf, 100);
+ 
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
+	data.willFlag = 0;
+	data.MQTTVersion = 3;
+	data.clientID.cstring = opts.clientid;
+	data.username.cstring = opts.username;
+	data.password.cstring = opts.password;
+
+	data.keepAliveInterval = 10;
+	data.cleansession = 1;
+	printf("Connecting to %s %d\n", opts.host, opts.port);
+	
+	rc = MQTTConnect(&c, &data);
+	printf("Connected %d\n", rc);
+    
+    printf("Subscribing to %s\n", topic);
+	rc = MQTTSubscribe(&c, topic, opts.qos, messageArrived);
+	printf("Subscribed %d\n", rc);
+
+	while (!toStop)
+	{
+		MQTTYield(&c, 1000);	
+	}
+	
+	printf("Stopping\n");
+
+	MQTTDisconnect(&c);
+	NetworkDisconnect(&n);
+
+	return 0;
+}
+
+

+ 30 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/CMakeLists.txt

@@ -0,0 +1,30 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+# MQTTClient Library - C
+
+
+file(GLOB SOURCES "*.c" "linux/*.c")
+
+add_library(
+  paho-embed-mqtt3cc SHARED
+  ${SOURCES}
+)
+install(TARGETS paho-embed-mqtt3cc DESTINATION /usr/lib)
+target_include_directories(paho-embed-mqtt3cc PRIVATE "linux")
+target_link_libraries(paho-embed-mqtt3cc paho-embed-mqtt3c)
+target_compile_definitions(paho-embed-mqtt3cc PRIVATE
+             MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h MQTTCLIENT_QOS2=1)

+ 241 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/FreeRTOS/MQTTFreeRTOS.c

@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
+ *    Ian Craggs - convert to FreeRTOS
+ *******************************************************************************/
+
+#include "MQTTFreeRTOS.h"
+
+
+int ThreadStart(Thread* thread, void (*fn)(void*), void* arg)
+{
+	int rc = 0;
+	uint16_t usTaskStackSize = (configMINIMAL_STACK_SIZE * 5);
+	UBaseType_t uxTaskPriority = uxTaskPriorityGet(NULL); /* set the priority as the same as the calling task*/
+
+	rc = xTaskCreate(fn,	/* The function that implements the task. */
+		"MQTTTask",			/* Just a text name for the task to aid debugging. */
+		usTaskStackSize,	/* The stack size is defined in FreeRTOSIPConfig.h. */
+		arg,				/* The task parameter, not used in this case. */
+		uxTaskPriority,		/* The priority assigned to the task is defined in FreeRTOSConfig.h. */
+		&thread->task);		/* The task handle is not used. */
+
+	return rc;
+}
+
+
+void MqttMutexInit(Mutex* mutex)
+{
+	mutex->sem = xSemaphoreCreateMutex();
+}
+
+int MqttMutexLock(Mutex* mutex)
+{
+	return xSemaphoreTake(mutex->sem, portMAX_DELAY);
+	
+}
+
+int MqttMutexUnlock(Mutex* mutex)
+{
+	return xSemaphoreGive(mutex->sem);
+}
+
+
+void TimerCountdownMS(Timer* timer, unsigned int timeout_ms)
+{
+	timer->xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
+	vTaskSetTimeOutState(&timer->xTimeOut); /* Record the time at which this function was entered. */
+}
+
+
+void TimerCountdown(Timer* timer, unsigned int timeout) 
+{
+	TimerCountdownMS(timer, timeout * 1000);
+}
+
+
+int TimerLeftMS(Timer* timer) 
+{
+	xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait); /* updates xTicksToWait to the number left */
+	return (timer->xTicksToWait < 0) ? 0 : (timer->xTicksToWait * portTICK_PERIOD_MS);
+}
+
+
+char TimerIsExpired(Timer* timer)
+{
+	return xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait) == pdTRUE;
+}
+
+
+void TimerInit(Timer* timer)
+{
+	timer->xTicksToWait = 0;
+	memset(&timer->xTimeOut, '\0', sizeof(timer->xTimeOut));
+}
+
+
+int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
+{
+	TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
+	TimeOut_t xTimeOut;
+	int recvLen = 0;
+
+	vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
+	do
+	{
+		int rc = 0;
+
+		FreeRTOS_setsockopt(n->my_socket, 0, FREERTOS_SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait));
+		rc = FreeRTOS_recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
+		if (rc > 0)
+			recvLen += rc;
+		else if (rc < 0)
+		{
+			recvLen = rc;
+			break;
+		}
+	} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
+
+	return recvLen;
+}
+
+
+int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
+{
+	TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */
+	TimeOut_t xTimeOut;
+	int sentLen = 0;
+
+	vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
+	do
+	{
+		int rc = 0;
+
+		FreeRTOS_setsockopt(n->my_socket, 0, FREERTOS_SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait));
+		rc = FreeRTOS_send(n->my_socket, buffer + sentLen, len - sentLen, 0);
+		if (rc > 0)
+			sentLen += rc;
+		else if (rc < 0)
+		{
+			sentLen = rc;
+			break;
+		}
+	} while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
+
+	return sentLen;
+}
+
+
+void FreeRTOS_disconnect(Network* n)
+{
+	FreeRTOS_closesocket(n->my_socket);
+}
+
+
+void NetworkInit(Network* n)
+{
+	n->my_socket = 0;
+	n->mqttread = FreeRTOS_read;
+	n->mqttwrite = FreeRTOS_write;
+	n->disconnect = FreeRTOS_disconnect;
+}
+
+
+int NetworkConnect(Network* n, char* addr, int port)
+{
+	struct freertos_sockaddr sAddr;
+	int retVal = -1;
+	uint32_t ipAddress;
+
+	if ((ipAddress = FreeRTOS_gethostbyname(addr)) == 0)
+		goto exit;
+
+	sAddr.sin_port = FreeRTOS_htons(port);
+	sAddr.sin_addr = ipAddress;
+
+	if ((n->my_socket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP)) < 0)
+		goto exit;
+
+	if ((retVal = FreeRTOS_connect(n->my_socket, &sAddr, sizeof(sAddr))) < 0)
+	{
+		FreeRTOS_closesocket(n->my_socket);
+	    goto exit;
+	}
+
+exit:
+	return retVal;
+}
+
+
+#if 0
+int NetworkConnectTLS(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify)
+{
+	SlSockAddrIn_t sAddr;
+	int addrSize;
+	int retVal;
+	unsigned long ipAddress;
+
+	retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET);
+	if (retVal < 0) {
+		return -1;
+	}
+
+	sAddr.sin_family = AF_INET;
+	sAddr.sin_port = sl_Htons((unsigned short)port);
+	sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);
+
+	addrSize = sizeof(SlSockAddrIn_t);
+
+	n->my_socket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);
+	if (n->my_socket < 0) {
+		return -1;
+	}
+
+	SlSockSecureMethod method;
+	method.secureMethod = sec_method;
+	retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method));
+	if (retVal < 0) {
+		return retVal;
+	}
+
+	SlSockSecureMask mask;
+	mask.secureMask = cipher;
+	retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask));
+	if (retVal < 0) {
+		return retVal;
+	}
+
+	if (certificates != NULL) {
+		retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t));
+		if (retVal < 0)
+		{
+			return retVal;
+		}
+	}
+
+	retVal = sl_Connect(n->my_socket, (SlSockAddr_t *)&sAddr, addrSize);
+	if (retVal < 0) {
+		if (server_verify || retVal != -453) {
+			sl_Close(n->my_socket);
+			return retVal;
+		}
+	}
+
+	SysTickIntRegister(SysTickIntHandler);
+	SysTickPeriodSet(80000);
+	SysTickEnable();
+
+	return retVal;
+}
+#endif

+ 72 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/FreeRTOS/MQTTFreeRTOS.h

@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTTFreeRTOS_H)
+#define MQTTFreeRTOS_H
+
+#include "FreeRTOS.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP.h"
+#include "semphr.h"
+#include "task.h"
+
+typedef struct Timer 
+{
+	TickType_t xTicksToWait;
+	TimeOut_t xTimeOut;
+} Timer;
+
+typedef struct Network Network;
+
+struct Network
+{
+	xSocket_t my_socket;
+	int (*mqttread) (Network*, unsigned char*, int, int);
+	int (*mqttwrite) (Network*, unsigned char*, int, int);
+	void (*disconnect) (Network*);
+};
+
+void TimerInit(Timer*);
+char TimerIsExpired(Timer*);
+void TimerCountdownMS(Timer*, unsigned int);
+void TimerCountdown(Timer*, unsigned int);
+int TimerLeftMS(Timer*);
+
+typedef struct Mutex
+{
+	SemaphoreHandle_t sem;
+} Mutex;
+
+void MqttMutexInit(Mutex*);
+int MqttMutexLock(Mutex*);
+int MqttMutexUnlock(Mutex*);
+
+typedef struct Thread
+{
+	TaskHandle_t task;
+} Thread;
+
+int ThreadStart(Thread*, void (*fn)(void*), void* arg);
+
+int FreeRTOS_read(Network*, unsigned char*, int, int);
+int FreeRTOS_write(Network*, unsigned char*, int, int);
+void FreeRTOS_disconnect(Network*);
+
+void NetworkInit(Network*);
+int NetworkConnect(Network*, char*, int);
+/*int NetworkConnectTLS(Network*, char*, int, SlSockSecureFiles_t*, unsigned char, unsigned int, char);*/
+
+#endif

+ 952 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/MQTTClient.c

@@ -0,0 +1,952 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *   Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
+ *   Ian Craggs - fix for #96 - check rem_len in readPacket
+ *   Ian Craggs - add ability to set message handler separately #6
+ *******************************************************************************/
+#include "MQTTClient.h"
+
+static void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessage) {
+    md->topicName = aTopicName;
+    md->message = aMessage;
+}
+
+
+static int getNextPacketId(MQTTClient *c) {
+    return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;
+}
+
+
+static int sendPacket(MQTTClient* c, int length, Timer* timer)
+{
+    int rc = FAILURE,
+        sent = 0;
+
+    while (sent < length && !TimerIsExpired(timer))
+    {
+        rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, TimerLeftMS(timer));
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    if (sent == length)
+    {
+        TimerCountdown(&c->last_sent, c->keepAliveInterval); // record the fact that we have successfully sent the packet
+        rc = MQTT_SUCCESS;
+    }
+    else
+        rc = FAILURE;
+    return rc;
+}
+
+
+int MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,
+                    unsigned char *sendbuf, size_t sendbuf_size, unsigned char *readbuf, size_t readbuf_size)
+{
+    int i;
+    c->ipstack = network;
+
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        c->messageHandlers[i].topicFilter = 0;
+    c->command_timeout_ms = command_timeout_ms;
+    c->buf = sendbuf;
+    c->buf_size = sendbuf_size;
+    c->readbuf = readbuf;
+    c->readbuf_size = readbuf_size;
+    c->isconnected = 0;
+    c->cleansession = 0;
+    c->ping_outstanding = 0;
+    c->defaultMessageHandler = NULL;
+	c->next_packetid = 1;
+    TimerInit(&c->last_sent);
+    TimerInit(&c->last_received);
+#if defined(MQTT_TASK)
+    if (MqttMutexInit(&c->mutex) != 0)
+    {
+        return FAILURE;
+    }
+#endif
+    return MQTT_SUCCESS;
+}
+
+void MQTTClientDeInit(MQTTClient *c)
+{
+    if(!c)
+        return;
+#if defined(MQTT_TASK)
+    MqttMutexDestory(&c->mutex);
+#endif
+    return;
+}
+
+static int decodePacket(MQTTClient* c, int* value, int timeout)
+{
+    unsigned char i;
+    int multiplier = 1;
+    int len = 0;
+    const int 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 = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);
+        if (rc != 1)
+            goto exit;
+        *value += (i & 127) * multiplier;
+        multiplier *= 128;
+    } while ((i & 128) != 0);
+exit:
+    return len;
+}
+
+
+static int readPacket(MQTTClient* c, Timer* timer)
+{
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    int rc = c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer));
+    if (rc != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    decodePacket(c, &rem_len, TimerLeftMS(timer));
+    len += MQTTPacket_encode(c->readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+    if (rem_len > (c->readbuf_size - len))
+    {
+        rc = BUFFER_OVERFLOW;
+        goto exit;
+    }
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (rem_len > 0 && (rc = c->ipstack->mqttread(c->ipstack, c->readbuf + len, rem_len, TimerLeftMS(timer)) != rem_len)) {
+        rc = 0;
+        goto exit;
+    }
+
+    header.byte = c->readbuf[0];
+    rc = header.bits.type;
+    if (c->keepAliveInterval > 0)
+        TimerCountdown(&c->last_received, c->keepAliveInterval); // record the fact that we have successfully received a packet
+exit:
+    return rc;
+}
+
+/**
+ * Copyright (c) 2009-2018 Roger Light <roger@atchoo.org>
+ * licensed under the Eclipse Public License 1.0 and the Eclipse Distribution License 1.0
+ */
+static int MQTTTopicMatched(const char *sub, MQTTString *topic_name, char *result)
+{
+    int sublen, topiclen;
+    int spos, tpos;
+    char multilevel_wildcard = 0;
+    char *topic;
+
+    if(!result)
+        return -1;
+    *result = 0;
+
+    if(!sub || !topic_name)
+    {
+        return -1;
+    }
+
+    sublen = strlen(sub);
+
+    if(topic_name->cstring)
+    {
+        topic = topic_name->cstring;
+        topiclen = strlen(topic_name->cstring);
+    }
+    else
+    {
+        topic = topic_name->lenstring.data;
+        topiclen = topic_name->lenstring.len;
+    }
+
+    if(!sublen || !topiclen)
+    {
+        *result = 0;
+        return -1;
+    }
+
+    if(sublen && topiclen)
+    {
+        if((sub[0] == '$' && topic[0] != '$')
+                || (topic[0] == '$' && sub[0] != '$'))
+        {
+            return 0;
+        }
+    }
+
+    spos = 0;
+    tpos = 0;
+
+    while(spos < sublen && tpos <= topiclen)
+    {
+        if(sub[spos] == topic[tpos])
+        {
+            if(tpos == topiclen - 1)
+            {
+                /* Check for e.g. foo matching foo/# */
+                if(spos == sublen - 3 && sub[spos + 1] == '/' && sub[spos + 2] == '#')
+                {
+                    *result = 1;
+                    multilevel_wildcard = 1;
+                    return 0;
+                }
+            }
+            spos++;
+            tpos++;
+            if(spos == sublen && tpos == topiclen)
+            {
+                *result = 1;
+                return 0;
+            }
+            else if(tpos == topiclen && spos == sublen - 1 && sub[spos] == '+')
+            {
+                if(spos > 0 && sub[spos - 1] != '/')
+                {
+                    return -1;
+                }
+                spos++;
+                *result = 1;
+                return 0;
+            }
+        }
+        else
+        {
+            if(sub[spos] == '+')
+            {
+                /* Check for bad "+foo" or "a/+foo" subscription */
+                if(spos > 0 && sub[spos - 1] != '/')
+                {
+                    return -1;
+                }
+                /* Check for bad "foo+" or "foo+/a" subscription */
+                if(spos < sublen - 1 && sub[spos + 1] != '/')
+                {
+                    return -1;
+                }
+                spos++;
+                while(tpos < topiclen && topic[tpos] != '/')
+                {
+                    tpos++;
+                }
+                if(tpos == topiclen && spos == sublen)
+                {
+                    *result = 1;
+                    return 0;
+                }
+            }
+            else if(sub[spos] == '#')
+            {
+                if(spos > 0 && sub[spos - 1] != '/')
+                {
+                    return -1;
+                }
+                multilevel_wildcard = 1;
+                if(spos + 1 != sublen)
+                {
+                    return -1;
+                }
+                else
+                {
+                    *result = 1;
+                    return 0;
+                }
+            }
+            else
+            {
+                /* Check for e.g. foo/bar matching foo/+/# */
+                if(spos > 0 && spos + 2 == sublen && tpos == topiclen
+                        && sub[spos - 1] == '+' && sub[spos] == '/' && sub[spos + 1] == '#')
+                {
+                    *result = 1;
+                    multilevel_wildcard = 1;
+                    return 0;
+                }
+                return 0;
+            }
+        }
+    }
+    if(multilevel_wildcard == 0 && (tpos < topiclen || spos < sublen))
+    {
+        *result = 0;
+    }
+
+    return 0;
+}
+
+
+int deliverMessage(MQTTClient* c, MQTTString* topicName, MQTTMessage* message)
+{
+    int i;
+    int rc = FAILURE;
+    char match_rst = 0;
+
+    // we have to find the right message handler - indexed by topic
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (c->messageHandlers[i].topicFilter != 0)
+        {
+            (void)MQTTTopicMatched((const char *)c->messageHandlers[i].topicFilter, topicName, &match_rst);
+            if (1 == match_rst && c->messageHandlers[i].fp != NULL)
+            {
+                MessageData md;
+                NewMessageData(&md, topicName, message);
+
+                md.arg = c->messageHandlers[i].arg;   ///< --modified,we need a args for the handler
+                c->messageHandlers[i].fp(&md);
+                rc = MQTT_SUCCESS;
+            }
+        }
+    }
+
+    if (rc == FAILURE && c->defaultMessageHandler != NULL)
+    {
+        MessageData md;
+        NewMessageData(&md, topicName, message);
+        c->defaultMessageHandler(&md);
+        rc = MQTT_SUCCESS;
+    }
+
+    return rc;
+}
+
+
+int keepalive(MQTTClient* c)
+{
+    int rc = MQTT_SUCCESS;
+
+    if (c->keepAliveInterval == 0)
+        goto exit;
+
+    ///<ACOCORDING TO THE protocol,we only care about the  send time
+    if (TimerIsExpired(&c->last_sent))
+    {
+        if (c->ping_outstanding)
+            rc = FAILURE; /* PINGRESP not received in keepalive interval */
+        else
+        {
+            Timer timer;
+            TimerInit(&timer);
+            TimerCountdownMS(&timer, 1000);
+            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);
+            if (len > 0 && (rc = sendPacket(c, len, &timer)) == MQTT_SUCCESS) // send the ping packet
+                c->ping_outstanding = 1;
+        }
+    }
+
+exit:
+    return rc;
+}
+
+
+void MQTTCleanSession(MQTTClient* c)
+{
+    int i = 0;
+
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        c->messageHandlers[i].topicFilter = NULL;
+}
+
+
+void MQTTCloseSession(MQTTClient* c)
+{
+    c->ping_outstanding = 0;
+    c->isconnected = 0;
+    if (c->cleansession)
+        MQTTCleanSession(c);
+}
+
+
+int cycle(MQTTClient* c, Timer* timer)
+{
+    int len = 0,
+        rc = MQTT_SUCCESS;
+    Timer send_timer;
+
+    int packet_type = readPacket(c, timer);     /* read the socket, see what work is due */
+
+    switch (packet_type)
+    {
+    default:
+        /* no more data to read, unrecoverable. Or read packet fails due to unexpected network error */
+        rc = packet_type;
+        goto exit;
+    case 0: /* timed out reading packet */
+        break;
+    case CONNACK:
+    case PUBACK:
+    case SUBACK:
+    case UNSUBACK:
+        break;
+    case PUBLISH:
+    {
+        MQTTString topicName;
+        MQTTMessage msg;
+        int intQoS;
+        msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */
+        if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
+                                    (unsigned char **)&msg.payload, (int *)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
+            goto exit;
+        msg.qos = (enum QoS)intQoS;
+        deliverMessage(c, &topicName, &msg);
+        if (msg.qos != QOS0)
+        {
+            if (msg.qos == QOS1)
+                len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
+            else if (msg.qos == QOS2)
+                len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
+            if (len <= 0)
+                rc = FAILURE;
+            else
+            {
+                TimerInit(&send_timer);
+                TimerCountdownMS(&send_timer, 1000);
+                rc = sendPacket(c, len, &send_timer);
+            }
+            if (rc == FAILURE)
+                goto exit; // there was a problem
+        }
+        break;
+    }
+    case PUBREC:
+    case PUBREL:
+    {
+        unsigned short mypacketid;
+        unsigned char dup, type;
+        if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+            rc = FAILURE;
+        else if ((len = MQTTSerialize_ack(c->buf, c->buf_size,
+                                          (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)
+            rc = FAILURE;
+        else
+        {
+            TimerInit(&send_timer);
+            TimerCountdownMS(&send_timer, 1000);
+            rc = sendPacket(c, len, &send_timer);
+            if(rc != MQTT_SUCCESS)
+                rc = FAILURE; // there was a problem
+        }
+        if (rc == FAILURE)
+            goto exit; // there was a problem
+        break;
+    }
+
+    case PUBCOMP:
+        break;
+    case PINGRESP:
+        c->ping_outstanding = 0;
+        break;
+    }
+
+    if (keepalive(c) != MQTT_SUCCESS)
+    {
+        //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT
+        rc = FAILURE;
+    }
+
+exit:
+    if (rc == MQTT_SUCCESS)
+        rc = packet_type;
+    else if (c->isconnected)
+        MQTTCloseSession(c);
+    return rc;
+}
+
+
+int MQTTYield(MQTTClient* c, int timeout_ms)
+{
+    int rc = MQTT_SUCCESS;
+    Timer timer;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, timeout_ms);
+
+    do
+    {
+#if defined(MQTT_TASK)
+        (void)MqttMutexLock(&c->mutex);
+#endif
+        if ( (rc = cycle(c, &timer) ) < 0)
+        {
+            rc = FAILURE;
+#if defined(MQTT_TASK)
+            MqttMutexUnlock(&c->mutex);
+#endif
+            break;
+        }
+#if defined(MQTT_TASK)
+        MqttMutexUnlock(&c->mutex);
+#endif
+    }
+    while (!TimerIsExpired(&timer));
+
+    return rc;
+}
+
+
+void MQTTRun(void* parm)
+{
+	Timer timer;
+	MQTTClient* c = (MQTTClient*)parm;
+
+	TimerInit(&timer);
+
+	while (1)
+	{
+#if defined(MQTT_TASK)
+		MqttMutexLock(&c->mutex);
+#endif
+		TimerCountdownMS(&timer, 500); /* Don't wait too long if no traffic is incoming */
+		cycle(c, &timer);
+#if defined(MQTT_TASK)
+		MqttMutexUnlock(&c->mutex);
+#endif
+	}
+}
+
+
+//#if defined(MQTT_TASK)
+//int MQTTStartTask(MQTTClient* client)
+//{
+//	return ThreadStart(&client->thread, &MQTTRun, client);
+//}
+//#endif
+
+
+int waitfor(MQTTClient* c, int packet_type, Timer* timer)
+{
+    int rc = FAILURE;
+
+    do
+    {
+        if (TimerIsExpired(timer))
+            break; // we timed out
+        rc = cycle(c, timer);
+    }
+    while (rc != packet_type && rc >= 0);
+
+    return rc;
+}
+
+
+int MQTTConnectWithResults(MQTTClient* c, MQTTPacket_connectData* options, MQTTConnackData* data)
+{
+    Timer connect_timer;
+    int rc = FAILURE;
+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	  MqttMutexLock(&c->mutex);
+#endif
+	  if (c->isconnected) /* don't send connect packet again if we are already connected */
+		  goto exit;
+
+    TimerInit(&connect_timer);
+    TimerCountdownMS(&connect_timer, c->command_timeout_ms);
+
+    if (options == 0)
+        options = &default_options; /* set default options if none were supplied */
+
+    c->keepAliveInterval = options->keepAliveInterval;
+    c->cleansession = options->cleansession;
+    TimerCountdown(&c->last_received, c->keepAliveInterval);
+    if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &connect_timer)) != MQTT_SUCCESS)  // send the connect packet
+        goto exit; // there was a problem
+
+    // this will be a blocking call, wait for the connack
+    if (waitfor(c, CONNACK, &connect_timer) == CONNACK)
+    {
+        data->rc = 0;
+        data->sessionPresent = 0;
+        if (MQTTDeserialize_connack(&data->sessionPresent, &data->rc, c->readbuf, c->readbuf_size) == 1)
+            rc = data->rc;
+        else
+            rc = FAILURE;
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == MQTT_SUCCESS)
+    {
+        c->isconnected = 1;
+        c->ping_outstanding = 0;        
+    }
+
+#if defined(MQTT_TASK)
+    
+    MqttMutexUnlock(&c->mutex);    
+#endif
+
+    return rc;
+}
+
+
+int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)
+{
+    MQTTConnackData data;
+    return MQTTConnectWithResults(c, options, &data);
+}
+
+
+int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler)
+{
+    int rc = FAILURE;
+    int i = -1;
+
+    /* first check for an existing matching slot */
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (c->messageHandlers[i].topicFilter != NULL && strcmp(c->messageHandlers[i].topicFilter, topicFilter) == 0)
+        {
+            if (messageHandler == NULL) /* remove existing */
+            {
+                c->messageHandlers[i].topicFilter = NULL;
+                c->messageHandlers[i].fp = NULL;
+            }
+            rc = MQTT_SUCCESS; /* return i when adding new subscription */
+            break;
+        }
+    }
+    /* if no existing, look for empty slot (unless we are removing) */
+    if (messageHandler != NULL)
+    {
+        if (rc == FAILURE)
+        {
+            for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (c->messageHandlers[i].topicFilter == NULL)
+                {
+                    rc = MQTT_SUCCESS;
+                    break;
+                }
+            }
+        }
+        if (i < MAX_MESSAGE_HANDLERS)
+        {
+            c->messageHandlers[i].topicFilter = topicFilter;
+            c->messageHandlers[i].fp = messageHandler;
+        }
+    }
+    return rc;
+}
+
+
+int MQTTSubscribeWithResults(MQTTClient *c, const char *topicFilter, enum QoS qos,
+                             messageHandler messageHandler, MQTTSubackData *data)
+{
+    int rc = FAILURE;
+    Timer timer;
+    int len = 0;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+
+#if defined(MQTT_TASK)
+    MqttMutexLock(&c->mutex);
+#endif
+    if (!c->isconnected)
+        goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int *)&qos);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != MQTT_SUCCESS) // send the subscribe packet
+        goto exit;             // there was a problem
+
+    if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback
+    {
+        int count = 0;
+        unsigned short mypacketid;
+        data->grantedQoS = QOS0;
+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, (int *)&data->grantedQoS, c->readbuf, c->readbuf_size) == 1)
+        {
+            if (data->grantedQoS != 0x80)
+                rc = MQTTSetMessageHandler(c, topicFilter, messageHandler);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == FAILURE)
+        MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MqttMutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+static int MQTTSetMessageHandlerArgs(MQTTClient* c, const char* topicFilter, messageHandler messageHandler,void *arg)
+{
+    int rc = FAILURE;
+    int i = -1;
+
+    /* first check for an existing matching slot */
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (c->messageHandlers[i].topicFilter != NULL && strcmp(c->messageHandlers[i].topicFilter, topicFilter) == 0)
+        {
+            if (messageHandler == NULL) /* remove existing */
+            {
+                c->messageHandlers[i].topicFilter = NULL;
+                c->messageHandlers[i].fp = NULL;
+                c->messageHandlers[i].arg = NULL;
+            }
+            rc = MQTT_SUCCESS; /* return i when adding new subscription */
+            break;
+        }
+    }
+    /* if no existing, look for empty slot (unless we are removing) */
+    if (messageHandler != NULL)
+    {
+        if (rc == FAILURE)
+        {
+            for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (c->messageHandlers[i].topicFilter == NULL)
+                {
+                    rc = MQTT_SUCCESS;
+                    break;
+                }
+            }
+        }
+        if (i < MAX_MESSAGE_HANDLERS)
+        {
+            c->messageHandlers[i].topicFilter = topicFilter;
+            c->messageHandlers[i].fp = messageHandler;
+            c->messageHandlers[i].arg = arg;
+
+        }
+    }
+    return rc;
+}
+
+
+int MQTTSubscribeWithResultsArgs(MQTTClient *c, const char *topicFilter, enum QoS qos,
+                             messageHandler messageHandler, MQTTSubackData *data,void *arg)
+{
+    int rc = FAILURE;
+    Timer timer;
+    int len = 0;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+#if defined(MQTT_TASK)
+    MqttMutexLock(&c->mutex);
+#endif
+    if (!c->isconnected)
+    {
+        goto exit;
+    }
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int *)&qos);
+    if (len <= 0)
+    {
+        goto exit;
+    }
+        
+    if ((rc = sendPacket(c, len, &timer)) != MQTT_SUCCESS) // send the subscribe packet
+    {
+        goto exit;
+    }
+
+    if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback
+    {
+        int count = 0;
+        unsigned short mypacketid;
+        data->grantedQoS = QOS0;
+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, (int *)&data->grantedQoS, c->readbuf, c->readbuf_size) == 1)
+        {
+            if (data->grantedQoS != 0x80)
+                rc = MQTTSetMessageHandlerArgs(c, topicFilter, messageHandler,arg);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == FAILURE)
+    {
+        MQTTCloseSession(c);      
+    }
+        // MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MqttMutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos,
+       messageHandler messageHandler)
+{
+    MQTTSubackData data;
+    return MQTTSubscribeWithResults(c, topicFilter, qos, messageHandler, &data);
+}
+
+
+int MQTTUnsubscribe(MQTTClient* c, const char* topicFilter)
+{
+    int rc = FAILURE;
+    Timer timer;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	  MqttMutexLock(&c->mutex);
+#endif
+	  if (!c->isconnected)
+		  goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != MQTT_SUCCESS) // send the subscribe packet
+        goto exit; // there was a problem
+
+    if (waitfor(c, UNSUBACK, &timer) == UNSUBACK)
+    {
+        unsigned short mypacketid;  // should be the same as the packetid above
+        if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)
+        {
+            /* remove the subscription message handler associated with this topic, if there is one */
+            MQTTSetMessageHandler(c, topicFilter, NULL);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == FAILURE)
+        MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MqttMutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)
+{
+    int rc = FAILURE;
+    Timer timer;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicName;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	  MqttMutexLock(&c->mutex);
+#endif
+	  if (!c->isconnected)
+		    goto exit;
+
+    TimerInit(&timer);
+    if(message->qos == QOS2)
+        TimerCountdownMS(&timer, c->command_timeout_ms * 2);
+    else
+        TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    if (message->qos == QOS1 || message->qos == QOS2)
+        message->id = getNextPacketId(c);
+
+    len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,
+              topic, (unsigned char*)message->payload, message->payloadlen);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != MQTT_SUCCESS) // send the subscribe packet
+        goto exit; // there was a problem
+
+    if (message->qos == QOS1)
+    {
+        if (waitfor(c, PUBACK, &timer) == PUBACK)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+        }
+        else
+            rc = FAILURE;
+    }
+    else if (message->qos == QOS2)
+    {
+        if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+        }
+        else
+            rc = FAILURE;
+    }
+
+exit:
+    if (rc == FAILURE)
+        MQTTCloseSession(c);
+#if defined(MQTT_TASK)
+	  MqttMutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTDisconnect(MQTTClient* c)
+{
+    int rc = FAILURE;
+    Timer timer;     // we might wait for incomplete incoming publishes to complete
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	MqttMutexLock(&c->mutex);
+#endif
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+	  len = MQTTSerialize_disconnect(c->buf, c->buf_size);
+    if (len > 0)
+        rc = sendPacket(c, len, &timer);            // send the disconnect packet
+    MQTTCloseSession(c);
+
+#if defined(MQTT_TASK)
+	  MqttMutexUnlock(&c->mutex);
+#endif
+    return rc;
+}

+ 256 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/MQTTClient.h

@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - documentation and platform specific header
+ *    Ian Craggs - add setMessageHandler function
+ *******************************************************************************/
+
+#if !defined(__MQTT_CLIENT_C_)
+#define __MQTT_CLIENT_C_
+
+#if defined(__cplusplus)
+ 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
+
+#include "MQTTPacket.h"
+#include "stdio.h"
+
+#if defined(MQTTCLIENT_PLATFORM_HEADER)
+/* The following sequence of macros converts the MQTTCLIENT_PLATFORM_HEADER value
+ * into a string constant suitable for use with include.
+ */
+#define xstr(s) str(s)
+#define str(s) #s
+#include xstr(MQTTCLIENT_PLATFORM_HEADER)
+#endif
+
+#define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */
+
+#if !defined(MAX_MESSAGE_HANDLERS)
+#define MAX_MESSAGE_HANDLERS 10/* redefinable - how many subscriptions do you want? */
+#endif
+
+enum QoS { QOS0, QOS1, QOS2, SUBFAIL=0x80 };
+
+/* all failure return codes must be negative */
+enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, MQTT_SUCCESS = 0 };
+
+/* The Platform specific header must define the Network and Timer structures and functions
+ * which operate on them.
+ *
+typedef struct Network
+{
+	int (*mqttread)(Network*, unsigned char* read_buffer, int, int);
+	int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int);
+} Network;*/
+
+/* The Timer structure must be defined in the platform specific header,
+ * and have the following functions to operate on it.  */
+extern void TimerInit(Timer*);
+extern char TimerIsExpired(Timer*);
+extern void TimerCountdownMS(Timer*, unsigned int);
+extern void TimerCountdown(Timer*, unsigned int);
+extern int TimerLeftMS(Timer*);
+
+typedef struct MQTTMessage
+{
+    enum QoS qos;
+    unsigned char retained;
+    unsigned char dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+} MQTTMessage;
+
+typedef struct MessageData
+{
+    MQTTMessage* message;
+    MQTTString* topicName;
+    void        *arg;
+} MessageData;
+
+typedef struct MQTTConnackData
+{
+    unsigned char rc;
+    unsigned char sessionPresent;
+} MQTTConnackData;
+
+typedef struct MQTTSubackData
+{
+    enum QoS grantedQoS;
+} MQTTSubackData;
+
+typedef void (*messageHandler)(MessageData*);
+
+typedef struct MQTTClient
+{
+    unsigned int next_packetid,
+      command_timeout_ms;
+    size_t buf_size,
+      readbuf_size;
+    unsigned char *buf,
+      *readbuf;
+    unsigned int keepAliveInterval;
+    char ping_outstanding;
+    int isconnected;
+    int cleansession;
+
+    struct MessageHandlers
+    {
+        const char* topicFilter;
+        void (*fp) (MessageData*);
+        void  *arg;
+    } messageHandlers[MAX_MESSAGE_HANDLERS];      /* Message handlers are indexed by subscription topic */
+
+    void (*defaultMessageHandler) (MessageData*);
+
+    Network* ipstack;
+    Timer last_sent, last_received;
+#if defined(MQTT_TASK)
+    Mutex mutex;
+    Thread thread;
+#endif
+} MQTTClient;
+
+#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}
+
+
+/**
+ * Create an MQTT client object
+ * @param client
+ * @param network
+ * @param command_timeout_ms
+ * @param
+ */
+DLLExport int MQTTClientInit(MQTTClient* client, Network* network, unsigned int command_timeout_ms,
+		unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size);
+DLLExport void MQTTClientDeInit(MQTTClient* c);
+
+/** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+ *  The nework object must be connected to the network endpoint before calling this
+ *  @param options - connect options
+ *  @return success code
+ */
+DLLExport int MQTTConnectWithResults(MQTTClient* client, MQTTPacket_connectData* options,
+    MQTTConnackData* data);
+
+/** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+ *  The nework object must be connected to the network endpoint before calling this
+ *  @param options - connect options
+ *  @return success code
+ */
+DLLExport int MQTTConnect(MQTTClient* client, MQTTPacket_connectData* options);
+
+/** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+ *  @param client - the client object to use
+ *  @param topic - the topic to publish to
+ *  @param message - the message to send
+ *  @return success code
+ */
+DLLExport int MQTTPublish(MQTTClient* client, const char*, MQTTMessage*);
+
+/** MQTT SetMessageHandler - set or remove a per topic message handler
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter set the message handler for
+ *  @param messageHandler - pointer to the message handler function or NULL to remove
+ *  @return success code
+ */
+DLLExport int MQTTSetMessageHandler(MQTTClient* c, const char* topicFilter, messageHandler messageHandler);
+
+/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter to subscribe to
+ *  @param message - the message to send
+ *  @return success code
+ */
+DLLExport int MQTTSubscribe(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler);
+
+/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter to subscribe to
+ *  @param message - the message to send
+ *  @param data - suback granted QoS returned
+ *  @return success code
+ */
+DLLExport int MQTTSubscribeWithResults(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler, MQTTSubackData* data);
+
+/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter to subscribe to
+ *  @param message - the message to send
+ *  @param data - suback granted QoS returned
+ *  @param arg  - which used for the messageHandler
+ *  @return success code
+ */
+DLLExport int MQTTSubscribeWithResultsArgs(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler, MQTTSubackData* data,void *args);
+
+
+/** MQTT Subscribe - send an MQTT unsubscribe packet and wait for unsuback before returning.
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter to unsubscribe from
+ *  @return success code
+ */
+DLLExport int MQTTUnsubscribe(MQTTClient* client, const char* topicFilter);
+
+/** MQTT Disconnect - send an MQTT disconnect packet and close the connection
+ *  @param client - the client object to use
+ *  @return success code
+ */
+DLLExport int MQTTDisconnect(MQTTClient* client);
+
+/** MQTT Yield - MQTT background
+ *  @param client - the client object to use
+ *  @param time - the time, in milliseconds, to yield for
+ *  @return success code
+ */
+DLLExport int MQTTYield(MQTTClient* client, int time);
+
+/** MQTT isConnected
+ *  @param client - the client object to use
+ *  @return truth value indicating whether the client is connected to the server
+ */
+static inline DLLExport int MQTTIsConnected(MQTTClient* client)
+{
+  return client->isconnected;
+}
+/** MQTT isConnected
+ *  @param client - the client object to use
+ */
+DLLExport void MQTTClientDeInit(MQTTClient *c);
+
+
+#if defined(MQTT_TASK)
+/** MQTT start background thread for a client.  After this, MQTTYield should not be called.
+*  @param client - the client object to use
+*  @return success code
+*/
+DLLExport int MQTTStartTask(MQTTClient* client);
+#endif
+
+#if defined(__cplusplus)
+     }
+#endif
+
+#endif

+ 196 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/cc3200/MQTTCC3200.c

@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTCC3200.h"
+
+unsigned long MilliTimer;
+
+void SysTickIntHandler(void) {
+	MilliTimer++;
+}
+
+char expired(Timer* timer) {
+	long left = timer->end_time - MilliTimer;
+	return (left < 0);
+}
+
+
+void countdown_ms(Timer* timer, unsigned int timeout) {
+	timer->end_time = MilliTimer + timeout;
+}
+
+
+void countdown(Timer* timer, unsigned int timeout) {
+	timer->end_time = MilliTimer + (timeout * 1000);
+}
+
+
+int left_ms(Timer* timer) {
+	long left = timer->end_time - MilliTimer;
+	return (left < 0) ? 0 : left;
+}
+
+
+void InitTimer(Timer* timer) {
+	timer->end_time = 0;
+}
+
+
+int cc3200_read(Network* n, unsigned char* buffer, int len, int timeout_ms) {
+	SlTimeval_t timeVal;
+	SlFdSet_t fdset;
+	int rc = 0;
+	int recvLen = 0;
+
+	SL_FD_ZERO(&fdset);
+	SL_FD_SET(n->my_socket, &fdset);
+
+	timeVal.tv_sec = 0;
+	timeVal.tv_usec = timeout_ms * 1000;
+	if (sl_Select(n->my_socket + 1, &fdset, NULL, NULL, &timeVal) == 1) {
+		do {
+			rc = sl_Recv(n->my_socket, buffer + recvLen, len - recvLen, 0);
+			recvLen += rc;
+		} while(recvLen < len);
+	}
+	return recvLen;
+}
+
+
+int cc3200_write(Network* n, unsigned char* buffer, int len, int timeout_ms) {
+	SlTimeval_t timeVal;
+	SlFdSet_t fdset;
+	int rc = 0;
+	int readySock;
+
+	SL_FD_ZERO(&fdset);
+	SL_FD_SET(n->my_socket, &fdset);
+
+	timeVal.tv_sec = 0;
+	timeVal.tv_usec = timeout_ms * 1000;
+	do {
+		readySock = sl_Select(n->my_socket + 1, NULL, &fdset, NULL, &timeVal);
+	} while(readySock != 1);
+	rc = sl_Send(n->my_socket, buffer, len, 0);
+	return rc;
+}
+
+
+void cc3200_disconnect(Network* n) {
+	sl_Close(n->my_socket);
+}
+
+
+void NewNetwork(Network* n) {
+	n->my_socket = 0;
+	n->mqttread = cc3200_read;
+	n->mqttwrite = cc3200_write;
+	n->disconnect = cc3200_disconnect;
+}
+
+int TLSConnectNetwork(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify) {
+	SlSockAddrIn_t sAddr;
+	int addrSize;
+	int retVal;
+	unsigned long ipAddress;
+
+	retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET);
+	if (retVal < 0) {
+		return -1;
+	}
+
+	sAddr.sin_family = AF_INET;
+	sAddr.sin_port = sl_Htons((unsigned short)port);
+	sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);
+
+	addrSize = sizeof(SlSockAddrIn_t);
+
+	n->my_socket = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET);
+	if (n->my_socket < 0) {
+		return -1;
+	}
+
+	SlSockSecureMethod method;
+	method.secureMethod = sec_method;
+	retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method));
+	if (retVal < 0) {
+		return retVal;
+	}
+
+	SlSockSecureMask mask;
+	mask.secureMask = cipher;
+	retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask));
+	if (retVal < 0) {
+		return retVal;
+	}
+
+	if (certificates != NULL) {
+		retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t));
+		if(retVal < 0)
+		{
+			return retVal;
+		}
+	}
+
+	retVal = sl_Connect(n->my_socket, ( SlSockAddr_t *)&sAddr, addrSize);
+	if( retVal < 0 ) {
+		if (server_verify || retVal != -453) {
+			sl_Close(n->my_socket);
+			return retVal;
+		}
+	}
+
+	SysTickIntRegister(SysTickIntHandler);
+	SysTickPeriodSet(80000);
+	SysTickEnable();
+
+	return retVal;
+}
+
+int ConnectNetwork(Network* n, char* addr, int port)
+{
+	SlSockAddrIn_t sAddr;
+	int addrSize;
+	int retVal;
+	unsigned long ipAddress;
+
+	sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET);
+
+	sAddr.sin_family = AF_INET;
+	sAddr.sin_port = sl_Htons((unsigned short)port);
+	sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);
+
+	addrSize = sizeof(SlSockAddrIn_t);
+
+	n->my_socket = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
+	if( n->my_socket < 0 ) {
+		// error
+		return -1;
+	}
+
+	retVal = sl_Connect(n->my_socket, ( SlSockAddr_t *)&sAddr, addrSize);
+	if( retVal < 0 ) {
+		// error
+		sl_Close(n->my_socket);
+	    return retVal;
+	}
+
+	SysTickIntRegister(SysTickIntHandler);
+	SysTickPeriodSet(80000);
+	SysTickEnable();
+
+	return retVal;
+}

+ 58 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/cc3200/MQTTCC3200.h

@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef __MQTT_CC3200_
+#define __MQTT_CC3200_
+
+#include "simplelink.h"
+#include "netapp.h"
+#include "socket.h"
+#include "hw_types.h"
+#include "systick.h"
+
+typedef struct Timer Timer;
+
+struct Timer {
+	unsigned long systick_period;
+	unsigned long end_time;
+};
+
+typedef struct Network Network;
+
+struct Network
+{
+	int my_socket;
+	int (*mqttread) (Network*, unsigned char*, int, int);
+	int (*mqttwrite) (Network*, unsigned char*, int, int);
+	void (*disconnect) (Network*);
+};
+
+char expired(Timer*);
+void countdown_ms(Timer*, unsigned int);
+void countdown(Timer*, unsigned int);
+int left_ms(Timer*);
+
+void InitTimer(Timer*);
+
+int cc3200_read(Network*, unsigned char*, int, int);
+int cc3200_write(Network*, unsigned char*, int, int);
+void cc3200_disconnect(Network*);
+void NewNetwork(Network*);
+
+int ConnectNetwork(Network*, char*, int);
+int TLSConnectNetwork(Network*, char*, int, SlSockSecureFiles_t*, unsigned char, unsigned int, char);
+
+#endif

+ 166 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/linux/MQTTLinux.c

@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
+ *    Ian Craggs - return codes from linux_read
+ *******************************************************************************/
+
+#include "MQTTLinux.h"
+
+void TimerInit(Timer* timer)
+{
+	timer->end_time = (struct timeval){0, 0};
+}
+
+char TimerIsExpired(Timer* timer)
+{
+	struct timeval now, res;
+	gettimeofday(&now, NULL);
+	timersub(&timer->end_time, &now, &res);
+	return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);
+}
+
+
+void TimerCountdownMS(Timer* timer, unsigned int timeout)
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000};
+	timeradd(&now, &interval, &timer->end_time);
+}
+
+
+void TimerCountdown(Timer* timer, unsigned int timeout)
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	struct timeval interval = {timeout, 0};
+	timeradd(&now, &interval, &timer->end_time);
+}
+
+
+int TimerLeftMS(Timer* timer)
+{
+	struct timeval now, res;
+	gettimeofday(&now, NULL);
+	timersub(&timer->end_time, &now, &res);
+	//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);
+	return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
+}
+
+
+int linux_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
+{
+	struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
+	if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))
+	{
+		interval.tv_sec = 0;
+		interval.tv_usec = 100;
+	}
+
+	setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
+
+	int bytes = 0;
+	while (bytes < len)
+	{
+		int rc = recv(n->my_socket, &buffer[bytes], (size_t)(len - bytes), 0);
+		if (rc == -1)
+		{
+			if (errno != EAGAIN && errno != EWOULDBLOCK)
+			  bytes = -1;
+			break;
+		}
+		else if (rc == 0)
+		{
+			bytes = 0;
+			break;
+		}
+		else
+			bytes += rc;
+	}
+	return bytes;
+}
+
+
+int linux_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
+{
+	struct timeval tv;
+
+	tv.tv_sec = 0;  /* 30 Secs Timeout */
+	tv.tv_usec = timeout_ms * 1000;  // Not init'ing this can cause strange errors
+
+	setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));
+	int	rc = write(n->my_socket, buffer, len);
+	return rc;
+}
+
+
+void NetworkInit(Network* n)
+{
+	n->my_socket = 0;
+	n->mqttread = linux_read;
+	n->mqttwrite = linux_write;
+}
+
+
+int NetworkConnect(Network* n, char* addr, int port)
+{
+	int type = SOCK_STREAM;
+	struct sockaddr_in address;
+	int rc = -1;
+	sa_family_t family = AF_INET;
+	struct addrinfo *result = NULL;
+	struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};
+
+	if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0)
+	{
+		struct addrinfo* res = result;
+
+		/* prefer ip4 addresses */
+		while (res)
+		{
+			if (res->ai_family == AF_INET)
+			{
+				result = res;
+				break;
+			}
+			res = res->ai_next;
+		}
+
+		if (result->ai_family == AF_INET)
+		{
+			address.sin_port = htons(port);
+			address.sin_family = family = AF_INET;
+			address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
+		}
+		else
+			rc = -1;
+
+		freeaddrinfo(result);
+	}
+
+	if (rc == 0)
+	{
+		n->my_socket = socket(family, type, 0);
+		if (n->my_socket != -1)
+			rc = connect(n->my_socket, (struct sockaddr*)&address, sizeof(address));
+	}
+
+	return rc;
+}
+
+
+void NetworkDisconnect(Network* n)
+{
+	close(n->my_socket);
+}

+ 74 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/src/linux/MQTTLinux.h

@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(__MQTT_LINUX_)
+#define __MQTT_LINUX_
+
+#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
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+typedef struct Timer
+{
+	struct timeval end_time;
+} Timer;
+
+void TimerInit(Timer*);
+char TimerIsExpired(Timer*);
+void TimerCountdownMS(Timer*, unsigned int);
+void TimerCountdown(Timer*, unsigned int);
+int TimerLeftMS(Timer*);
+
+typedef struct Network
+{
+	int my_socket;
+	int (*mqttread) (struct Network*, unsigned char*, int, int);
+	int (*mqttwrite) (struct Network*, unsigned char*, int, int);
+} Network;
+
+int linux_read(Network*, unsigned char*, int, int);
+int linux_write(Network*, unsigned char*, int, int);
+
+DLLExport void NetworkInit(Network*);
+DLLExport int NetworkConnect(Network*, char*, int);
+DLLExport void NetworkDisconnect(Network*);
+
+#endif

+ 20 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/test/CMakeLists.txt

@@ -0,0 +1,20 @@
+PROJECT(mqtt-tests)
+
+SET(MQTT_TEST_BROKER_HOST "localhost" CACHE STRING "Hostname of a test MQTT broker to use")
+SET(MQTT_TEST_PROXY_PORT "1884" CACHE STRING "Port of the test proxy to use")
+SET(MQTT_SSL_HOSTNAME "localhost" CACHE STRING "Hostname of a test SSL MQTT broker to use")
+SET(CERTDIR $ENV{TRAVIS_BUILD_DIR}/test/ssl)
+
+ADD_EXECUTABLE(
+	testc1
+	test1.c
+)
+
+target_link_libraries(testc1 paho-embed-mqtt3cc paho-embed-mqtt3c)
+target_include_directories(testc1 PRIVATE "../src" "../src/linux")
+target_compile_definitions(testc1 PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h)
+
+ADD_TEST(
+	NAME testc1
+	COMMAND "testc1" "--host" ${MQTT_TEST_BROKER_HOST}
+)

+ 1050 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient-C/test/test1.c

@@ -0,0 +1,1050 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial implementation for embedded C client
+ *******************************************************************************/
+
+
+/**
+ * @file
+ * Tests for the Paho embedded C "high" level client
+ */
+
+
+#include "MQTTClient.h"
+#include <string.h>
+#include <stdlib.h>
+
+#if !defined(_WINDOWS)
+  #include <sys/time.h>
+  #include <sys/socket.h>
+  #include <unistd.h>
+  #include <errno.h>
+#else
+  #include <windows.h>
+  #define setenv(a, b, c) _putenv_s(a, b)
+#endif
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+void usage(void)
+{
+	printf("help!!\n");
+	exit(EXIT_FAILURE);
+}
+
+struct Options
+{
+	char* host;         /**< connection to system under test. */
+  int port;
+	char* proxy_host;
+  int proxy_port;
+	int verbose;
+	int test_no;
+	int MQTTVersion;
+	int iterations;
+} options =
+{
+	"localhost",
+  1883,
+	"localhost",
+	1885,
+	0, //verbose
+	0, //test_no
+	4,
+	1,
+};
+
+void getopts(int argc, char** argv)
+{
+	int count = 1;
+
+	while (count < argc)
+	{
+		if (strcmp(argv[count], "--test_no") == 0)
+		{
+			if (++count < argc)
+				options.test_no = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--host") == 0)
+		{
+			if (++count < argc)
+			{
+				options.host = argv[count];
+				printf("\nSetting host to %s\n", options.host);
+			}
+			else
+				usage();
+		}
+    else if (strcmp(argv[count], "--port") == 0)
+    {
+      if (++count < argc)
+      {
+        options.port = atoi(argv[count]);
+        printf("\nSetting port to %d\n", options.port);
+      }
+      else
+        usage();
+    }
+		else if (strcmp(argv[count], "--proxy_host") == 0)
+		{
+			if (++count < argc)
+      {
+				options.proxy_host = argv[count];
+        printf("\nSetting proxy_host to %s\n", options.proxy_host);
+      }
+			else
+				usage();
+		}
+    else if (strcmp(argv[count], "--proxy_port") == 0)
+    {
+      if (++count < argc)
+      {
+        options.proxy_port = atoi(argv[count]);
+        printf("\nSetting proxy_port to %d\n", options.proxy_port);
+      }
+      else
+        usage();
+    }
+		else if (strcmp(argv[count], "--MQTTversion") == 0)
+		{
+			if (++count < argc)
+			{
+				options.MQTTVersion = atoi(argv[count]);
+				printf("setting MQTT version to %d\n", options.MQTTVersion);
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--iterations") == 0)
+		{
+			if (++count < argc)
+				options.iterations = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--verbose") == 0)
+		{
+			options.verbose = 1;
+			printf("\nSetting verbose on\n");
+		}
+		count++;
+	}
+}
+
+
+#define LOGA_DEBUG 0
+#define LOGA_INFO 1
+#include <stdarg.h>
+#include <time.h>
+#include <sys/timeb.h>
+void MyLog(int LOGA_level, char* format, ...)
+{
+	static char msg_buf[256];
+	va_list args;
+	struct timeb ts;
+
+	struct tm *timeinfo;
+
+	if (LOGA_level == LOGA_DEBUG && options.verbose == 0)
+	  return;
+
+	ftime(&ts);
+	timeinfo = localtime(&ts.time);
+	strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo);
+
+	sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm);
+
+	va_start(args, format);
+	vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), format, args);
+	va_end(args);
+
+	printf("%s\n", msg_buf);
+	fflush(stdout);
+}
+
+
+#if defined(WIN32) || defined(_WINDOWS)
+#define mqsleep(A) Sleep(1000*A)
+#define START_TIME_TYPE DWORD
+static DWORD start_time = 0;
+START_TIME_TYPE start_clock(void)
+{
+	return GetTickCount();
+}
+#elif defined(AIX)
+#define mqsleep sleep
+#define START_TIME_TYPE struct timespec
+START_TIME_TYPE start_clock(void)
+{
+	static struct timespec start;
+	clock_gettime(CLOCK_REALTIME, &start);
+	return start;
+}
+#else
+#define mqsleep sleep
+#define START_TIME_TYPE struct timeval
+/* TODO - unused - remove? static struct timeval start_time; */
+START_TIME_TYPE start_clock(void)
+{
+	struct timeval start_time;
+	gettimeofday(&start_time, NULL);
+	return start_time;
+}
+#endif
+
+
+#if defined(WIN32)
+long elapsed(START_TIME_TYPE start_time)
+{
+	return GetTickCount() - start_time;
+}
+#elif defined(AIX)
+#define assert(a)
+long elapsed(struct timespec start)
+{
+	struct timespec now, res;
+
+	clock_gettime(CLOCK_REALTIME, &now);
+	ntimersub(now, start, res);
+	return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
+}
+#else
+long elapsed(START_TIME_TYPE start_time)
+{
+	struct timeval now, res;
+
+	gettimeofday(&now, NULL);
+	timersub(&now, &start_time, &res);
+	return (res.tv_sec)*1000 + (res.tv_usec)/1000;
+}
+#endif
+
+
+#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
+#define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
+
+int tests = 0;
+int failures = 0;
+FILE* xml;
+START_TIME_TYPE global_start_time;
+char output[3000];
+char* cur_output = output;
+
+
+void write_test_result(void)
+{
+	long duration = elapsed(global_start_time);
+
+	fprintf(xml, " time=\"%ld.%.3ld\" >\n", duration / 1000, duration % 1000);
+	if (cur_output != output)
+	{
+		fprintf(xml, "%s", output);
+		cur_output = output;
+	}
+	fprintf(xml, "</testcase>\n");
+}
+
+
+void myassert(char* filename, int lineno, char* description, int value, char* format, ...)
+{
+	++tests;
+	if (!value)
+	{
+		va_list args;
+
+		++failures;
+		MyLog(LOGA_INFO, "Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
+
+		va_start(args, format);
+		vprintf(format, args);
+		va_end(args);
+
+		cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
+                        description, filename, lineno);
+	}
+	else
+		MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", filename, lineno, description);
+}
+
+
+static volatile MessageData* test1_message_data = NULL;
+static MQTTMessage pubmsg;
+
+void messageArrived(MessageData* md)
+{
+  test1_message_data = md;
+  MQTTMessage* m = md->message;
+
+	assert("Good message lengths", pubmsg.payloadlen == m->payloadlen,
+         "payloadlen was %d", m->payloadlen);
+
+  if (pubmsg.payloadlen == m->payloadlen)
+      assert("Good message contents", memcmp(m->payload, pubmsg.payload, m->payloadlen) == 0,
+          "payload was %s", m->payload);
+}
+
+
+/*********************************************************************
+
+Test1: single-threaded client
+
+*********************************************************************/
+void test1_sendAndReceive(MQTTClient* c, int qos, char* test_topic)
+{
+	char* topicName = NULL;
+	int topicLen;
+	int i = 0;
+	int iterations = 50;
+	int rc;
+  int wait_seconds;
+
+	MyLog(LOGA_DEBUG, "%d messages at QoS %d", iterations, qos);
+  memset(&pubmsg, '\0', sizeof(pubmsg));
+	pubmsg.payload = "a much longer message that we can shorten to the extent that we need to payload up to 11";
+	pubmsg.payloadlen = 11;
+	pubmsg.qos = qos;
+	pubmsg.retained = 0;
+  pubmsg.dup = 0;
+
+	for (i = 0; i < iterations; ++i)
+	{
+    test1_message_data = NULL;
+		rc = MQTTPublish(c, test_topic, &pubmsg);
+		assert("Good rc from publish", rc == SUCCESS, "rc was %d", rc);
+
+    /* wait for the message to be received */
+    wait_seconds = 10;
+		while ((test1_message_data == NULL) && (wait_seconds-- > 0))
+		{
+      MQTTYield(c, 100);
+		}
+		assert("Message Arrived", wait_seconds > 0, "Time out waiting for message %d\n", i);
+
+		if (!test1_message_data)
+			printf("No message received within timeout period\n");
+	}
+
+	/* wait to receive any outstanding messages */
+  wait_seconds = 2;
+  while (wait_seconds-- > 0)
+  {
+      MQTTYield(c, 1000);
+  }
+}
+
+
+int test1(struct Options options)
+{
+	int subsqos = 2;
+  Network n;
+	MQTTClient c;
+	int rc = 0;
+	char* test_topic = "C client test1";
+  MQTTPacket_willOptions wopts;
+  unsigned char buf[100];
+  unsigned char readbuf[100];
+
+  printf("test1\n");
+	fprintf(xml, "<testcase classname=\"test1\" name=\"single threaded client using receive\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 1 - single threaded client using receive");
+
+  NetworkInit(&n);
+  NetworkConnect(&n, options.host, options.port);
+  MQTTClientInit(&c, &n, 1000, buf, 100, readbuf, 100);
+
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+  data.willFlag = 1;
+  data.MQTTVersion = options.MQTTVersion;
+  data.clientID.cstring = "single-threaded-test";
+  data.username.cstring = "testuser";
+  data.password.cstring = "testpassword";
+
+  data.keepAliveInterval = 20;
+  data.cleansession = 1;
+
+	data.will.message.cstring = "will message";
+	data.will.qos = 1;
+	data.will.retained = 0;
+	data.will.topicName.cstring = "will topic";
+
+	MyLog(LOGA_DEBUG, "Connecting");
+  rc = MQTTConnect(&c, &data);
+	assert("Good rc from connect", rc == SUCCESS, "rc was %d", rc);
+	if (rc != SUCCESS)
+		goto exit;
+
+	rc = MQTTSubscribe(&c, test_topic, subsqos, messageArrived);
+	assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+
+	test1_sendAndReceive(&c, 0, test_topic);
+	test1_sendAndReceive(&c, 1, test_topic);
+	test1_sendAndReceive(&c, 2, test_topic);
+
+	MyLog(LOGA_DEBUG, "Stopping\n");
+
+	rc = MQTTUnsubscribe(&c, test_topic);
+	assert("Unsubscribe successful", rc == SUCCESS, "rc was %d", rc);
+	rc = MQTTDisconnect(&c);
+	assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+
+	/* Just to make sure we can connect again */
+  NetworkConnect(&n, options.host, options.port);
+  rc = MQTTConnect(&c, &data);
+	assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+	rc = MQTTDisconnect(&c);
+	assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+
+exit:
+	MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+/*********************************************************************
+
+Test 2: connack return data
+
+sessionPresent
+
+*********************************************************************/
+int test2(struct Options options)
+{
+	int subsqos = 2;
+  Network n;
+	MQTTClient c;
+	int rc = 0;
+	char* test_topic = "C client test2";
+  MQTTPacket_willOptions wopts;
+  unsigned char buf[100];
+  unsigned char readbuf[100];
+  MQTTConnackData connack;
+  MQTTSubackData suback;
+
+	fprintf(xml, "<testcase classname=\"test2\" name=\"connack return data\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - connack return data");
+
+  NetworkInit(&n);
+  NetworkConnect(&n, options.host, options.port);
+  MQTTClientInit(&c, &n, 1000, buf, 100, readbuf, 100);
+
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+  data.willFlag = 1;
+  data.MQTTVersion = options.MQTTVersion;
+  data.clientID.cstring = "connack-return-data";
+  data.username.cstring = "testuser";
+  data.password.cstring = "testpassword";
+
+  data.keepAliveInterval = 20;
+  data.cleansession = 1;
+
+	data.will.message.cstring = "will message";
+	data.will.qos = 1;
+	data.will.retained = 0;
+	data.will.topicName.cstring = "will topic";
+
+	MyLog(LOGA_DEBUG, "Connecting");
+  rc = MQTTConnect(&c, &data);
+	assert("Good rc from connect", rc == SUCCESS, "rc was %d", rc);
+	if (rc != SUCCESS)
+		goto exit;
+
+	rc = MQTTDisconnect(&c);
+	assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+  /* now connect cleansession false */
+  NetworkConnect(&n, options.host, options.port);
+  data.cleansession = 0;
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Good rc from connect", rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+         "sessionPresent was %d", connack.sessionPresent);
+
+  /* set up some state */
+  rc = MQTTSubscribeWithResults(&c, test_topic, subsqos, messageArrived, &suback);
+  assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+  assert("Good granted QoS", suback.grantedQoS == subsqos,
+         "granted QoS was %d", suback.grantedQoS);
+
+  rc = MQTTDisconnect(&c);
+  assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+	/* Connect and check sessionPresent */
+  NetworkConnect(&n, options.host, options.port);
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+	assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 1", connack.sessionPresent == 1,
+           "sessionPresent was %d", connack.sessionPresent);
+
+	rc = MQTTDisconnect(&c);
+	assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+  /* Connect and check sessionPresent is cleared */
+  data.cleansession = 1;
+  NetworkConnect(&n, options.host, options.port);
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  rc = MQTTDisconnect(&c);
+  assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+exit:
+	MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+/*********************************************************************
+
+Test 3: client session state
+
+*********************************************************************/
+static volatile MessageData* test2_message_data = NULL;
+
+void messageArrived2(MessageData* md)
+{
+    test2_message_data = md;
+	  MQTTMessage *m = md->message;
+
+    assert("Good message lengths", pubmsg.payloadlen == m->payloadlen,
+         "payloadlen was %d", m->payloadlen);
+
+    if (pubmsg.payloadlen == m->payloadlen)
+        assert("Good message contents", memcmp(m->payload, pubmsg.payload, m->payloadlen) == 0,
+          "payload was %s", m->payload);
+}
+
+
+int check_subs_exist(MQTTClient* c, const char* test_topic, int which)
+{
+    int rc = FAILURE;
+    int wait_seconds = 0;
+
+    memset(&pubmsg, '\0', sizeof(pubmsg));
+    pubmsg.payload = (void*)"a much longer message that we can shorten to the extent that we need to payload up to 11";
+    pubmsg.payloadlen = 11;
+    pubmsg.qos = QOS2;
+    pubmsg.retained = 0;
+    pubmsg.dup = 0;
+
+    test1_message_data = test2_message_data = NULL;
+    rc = MQTTPublish(c, test_topic, &pubmsg);
+    assert("Good rc from publish", rc == SUCCESS, "rc was %d", rc);
+
+    /* wait for the message to be received */
+    wait_seconds = 10;
+    while (wait_seconds-- > 0)
+    {
+        MQTTYield(c, 100);
+    }
+
+    rc = (((which == 1 || which == 3) && test1_message_data) ||
+         (which == 2 && test1_message_data == NULL)) ? SUCCESS : FAILURE;
+    assert("test1 subscription", rc == SUCCESS, "test1_message_data %p\n",
+            test1_message_data);
+    rc = (((which == 2 || which == 3) && test2_message_data) ||
+         (which == 1 && test2_message_data == NULL)) ? SUCCESS : FAILURE;
+    assert("test2 subscription", rc == SUCCESS, "test2_message_data %p\n",
+             test2_message_data);
+    return rc;
+}
+
+
+int test3(struct Options options)
+{
+  enum QoS subsqos = QOS2;
+  Network n;
+  MQTTClient c;
+	int rc;
+  const char* test_topic = "C client test3";
+  int wait_seconds = 0;
+  unsigned char buf[100];
+  unsigned char readbuf[100];
+  MQTTConnackData connack;
+  MQTTSubackData suback;
+
+  fprintf(xml, "<testcase classname=\"test3\" name=\"session state\"");
+  global_start_time = start_clock();
+  failures = 0;
+  MyLog(LOGA_INFO, "Starting test 3 - session state");
+
+  NetworkInit(&n);
+  MQTTClientInit(&c, &n, 1000, buf, 100, readbuf, 100);
+
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+  data.willFlag = 1;
+  data.MQTTVersion = options.MQTTVersion;
+  data.clientID.cstring = (char*)"connack-session-state";
+  data.username.cstring = (char*)"testuser";
+  data.password.cstring = (char*)"testpassword";
+
+  data.keepAliveInterval = 10;
+  data.cleansession = 1;
+
+  data.will.message.cstring = (char*)"will message";
+  data.will.qos = 1;
+  data.will.retained = 0;
+  data.will.topicName.cstring = (char*)"will topic";
+
+  assert("Not connected", MQTTIsConnected(&c) == 0,
+         "isconnected was %d", MQTTIsConnected(&c));
+
+  MyLog(LOGA_DEBUG, "Connecting");
+  rc = NetworkConnect(&n, options.host, options.port);
+  assert("Good rc from TCP connect", rc == SUCCESS, "rc was %d", rc);
+  if (rc != SUCCESS)
+    goto exit;
+
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Good rc from connect", rc == SUCCESS, "rc was %d", rc);
+  if (rc != SUCCESS)
+    goto exit;
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+         "sessionPresent was %d", connack.sessionPresent);
+
+  assert("Good rc in connack", MQTTIsConnected(&c) == 1,
+                "isconnected was %d", MQTTIsConnected(&c));
+
+  rc = MQTTDisconnect(&c);
+  assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = NetworkConnect(&n, options.proxy_host, options.proxy_port);
+  assert("TCP connect successful",  rc == SUCCESS, "rc was %d", rc);
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  rc = MQTTSubscribeWithResults(&c, test_topic, subsqos, messageArrived, &suback);
+  assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == QOS2,
+         "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(&c, test_topic, 1);
+
+  rc = MQTTSubscribeWithResults(&c, test_topic, subsqos, messageArrived2, &suback);
+  assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == QOS2,
+                  "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(&c, test_topic, 2);
+
+  rc = MQTTDisconnect(&c);
+  assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = NetworkConnect(&n, options.proxy_host, options.proxy_port);
+  assert("TCP connect successful",  rc == SUCCESS, "rc was %d", rc);
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 1", connack.sessionPresent == 1,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  check_subs_exist(&c, test_topic, 2);
+
+  rc = MQTTSubscribeWithResults(&c, test_topic, subsqos, messageArrived, &suback);
+  assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == QOS2,
+            "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(&c, test_topic, 1);
+
+  // cause a connection FAILURE
+  memset(&pubmsg, '\0', sizeof(pubmsg));
+  pubmsg.payload = (void*)"TERMINATE";
+  pubmsg.payloadlen = strlen((char*)pubmsg.payload);
+  pubmsg.qos = QOS0;
+  pubmsg.retained = 0;
+  pubmsg.dup = 0;
+  rc = MQTTPublish(&c, "MQTTSAS topic", &pubmsg);
+  assert("Good rc from publish", rc == SUCCESS, "rc was %d", rc);
+
+  // wait for failure to be noticed by keepalive
+  wait_seconds = 20;
+  while (MQTTIsConnected(&c) && (wait_seconds-- > 0))
+  {
+      MQTTYield(&c, 1000);
+  }
+  assert("Disconnected", !MQTTIsConnected(&c), "isConnected was %d",
+         MQTTIsConnected(&c));
+  NetworkDisconnect(&n);
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = NetworkConnect(&n, options.host, options.port);
+  assert("TCP connect successful",  rc == SUCCESS, "rc was %d", rc);
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 1", connack.sessionPresent == 1,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  check_subs_exist(&c, test_topic, 1);
+
+  rc = MQTTSubscribeWithResults(&c, test_topic, subsqos, messageArrived2, &suback);
+  assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == QOS2,
+                  "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(&c, test_topic, 2);
+
+  rc = MQTTDisconnect(&c);
+  assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+  /* reconnect with cleansession true to clean up both server and client state */
+  data.cleansession = 1;
+  rc = NetworkConnect(&n, options.host, options.port);
+  assert("TCP connect successful",  rc == SUCCESS, "rc was %d", rc);
+  rc = MQTTConnectWithResults(&c, &data, &connack);
+  assert("Connect successful",  rc == SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  rc = MQTTSubscribeWithResults(&c, test_topic, subsqos, messageArrived2, &suback);
+  assert("Good rc from subscribe", rc == SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == QOS2,
+                  "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(&c, test_topic, 2);
+
+  rc = MQTTDisconnect(&c);
+  assert("Disconnect successful", rc == SUCCESS, "rc was %d", rc);
+  NetworkDisconnect(&n);
+
+exit:
+  MyLog(LOGA_INFO, "TEST2: test %s. %d tests run, %d failures.",
+      (failures == 0) ? "passed" : "failed", tests, failures);
+  write_test_result();
+  return failures;
+}
+
+#if 0
+/*********************************************************************
+
+Test 4: connectionLost and will message
+
+*********************************************************************/
+MQTTClient test6_c1, test6_c2;
+volatile int test6_will_message_arrived = 0;
+volatile int test6_connection_lost_called = 0;
+
+void test6_connectionLost(void* context, char* cause)
+{
+	MQTTClient c = (MQTTClient)context;
+	printf("%s -> Callback: connection lost\n", (c == test6_c1) ? "Client-1" : "Client-2");
+	test6_connection_lost_called = 1;
+}
+
+void test6_deliveryComplete(void* context, MQTTClient_deliveryToken token)
+{
+	printf("Client-2 -> Callback: publish complete for token %d\n", token);
+}
+
+char* test6_will_topic = "C Test 2: will topic";
+char* test6_will_message = "will message from Client-1";
+
+int test6_messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* m)
+{
+	MQTTClient c = (MQTTClient)context;
+	printf("%s -> Callback: message received on topic '%s' is '%.*s'.\n",
+			 (c == test6_c1) ? "Client-1" : "Client-2", topicName, m->payloadlen, (char*)(m->payload));
+	if (c == test6_c2 && strcmp(topicName, test6_will_topic) == 0 && memcmp(m->payload, test6_will_message, m->payloadlen) == 0)
+		test6_will_message_arrived = 1;
+	MQTTClient_free(topicName);
+	MQTTClient_freeMessage(&m);
+	return 1;
+}
+
+
+int test6(struct Options options)
+{
+	char* testname = "test6";
+	MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
+	MQTTClient_willOptions wopts =  MQTTClient_willOptions_initializer;
+	MQTTClient_connectOptions opts2 = MQTTClient_connectOptions_initializer;
+	int rc, count;
+	char* mqttsas_topic = "MQTTSAS topic";
+
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 6 - connectionLost and will messages");
+	fprintf(xml, "<testcase classname=\"test1\" name=\"connectionLost and will messages\"");
+	global_start_time = start_clock();
+
+	opts.keepAliveInterval = 2;
+	opts.cleansession = 1;
+	opts.MQTTVersion = MQTTVERSION_3_1_1;
+	opts.will = &wopts;
+	opts.will->message = test6_will_message;
+	opts.will->qos = 1;
+	opts.will->retained = 0;
+	opts.will->topicName = test6_will_topic;
+	if (options.haconnections != NULL)
+	{
+		opts.serverURIs = options.haconnections;
+		opts.serverURIcount = options.hacount;
+	}
+
+	/* Client-1 with Will options */
+	rc = MQTTClient_create(&test6_c1, options.proxy_connection, "Client_1", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
+	assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	rc = MQTTClient_setCallbacks(test6_c1, (void*)test6_c1, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
+	assert("good rc from setCallbacks",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	/* Connect to the broker */
+	rc = MQTTClient_connect(test6_c1, &opts);
+	assert("good rc from connect",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	/* Client - 2 (multi-threaded) */
+	rc = MQTTClient_create(&test6_c2, options.connection, "Client_2", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
+	assert("good rc from create",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* Set the callback functions for the client */
+	rc = MQTTClient_setCallbacks(test6_c2, (void*)test6_c2, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
+	assert("good rc from setCallbacks",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* Connect to the broker */
+	opts2.keepAliveInterval = 20;
+	opts2.cleansession = 1;
+	MyLog(LOGA_INFO, "Connecting Client_2 ...");
+	rc = MQTTClient_connect(test6_c2, &opts2);
+	assert("Good rc from connect", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	rc = MQTTClient_subscribe(test6_c2, test6_will_topic, 2);
+	assert("Good rc from subscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* now send the command which will break the connection and cause the will message to be sent */
+	rc = MQTTClient_publish(test6_c1, mqttsas_topic, (int)strlen("TERMINATE"), "TERMINATE", 0, 0, NULL);
+	assert("Good rc from publish", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	MyLog(LOGA_INFO, "Waiting to receive the will message");
+	count = 0;
+	while (++count < 40)
+	{
+		#if defined(WIN32)
+			Sleep(1000L);
+		#else
+			sleep(1);
+		#endif
+		if (test6_will_message_arrived == 1 && test6_connection_lost_called == 1)
+			break;
+	}
+	assert("will message arrived", test6_will_message_arrived == 1,
+							"will_message_arrived was %d\n", test6_will_message_arrived);
+	assert("connection lost called", test6_connection_lost_called == 1,
+			         "connection_lost_called %d\n", test6_connection_lost_called);
+
+	rc = MQTTClient_unsubscribe(test6_c2, test6_will_topic);
+	assert("Good rc from unsubscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
+
+	rc = MQTTClient_isConnected(test6_c2);
+	assert("Client-2 still connected", rc == 1, "isconnected is %d", rc);
+
+	rc = MQTTClient_isConnected(test6_c1);
+	assert("Client-1 not connected", rc == 0, "isconnected is %d", rc);
+
+	rc = MQTTClient_disconnect(test6_c2, 100L);
+	assert("Good rc from disconnect", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
+
+	MQTTClient_destroy(&test6_c1);
+	MQTTClient_destroy(&test6_c2);
+
+exit:
+	MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.\n",
+			(failures == 0) ? "passed" : "failed", testname, tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test6a(struct Options options)
+{
+	char* testname = "test6a";
+	MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
+	MQTTClient_willOptions wopts =  MQTTClient_willOptions_initializer;
+	MQTTClient_connectOptions opts2 = MQTTClient_connectOptions_initializer;
+	int rc, count;
+	char* mqttsas_topic = "MQTTSAS topic";
+
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 6 - connectionLost and binary will messages");
+	fprintf(xml, "<testcase classname=\"test1\" name=\"connectionLost and binary will messages\"");
+	global_start_time = start_clock();
+
+	opts.keepAliveInterval = 2;
+	opts.cleansession = 1;
+	opts.MQTTVersion = MQTTVERSION_3_1_1;
+	opts.will = &wopts;
+	opts.will->payload.data = test6_will_message;
+	opts.will->payload.len = strlen(test6_will_message) + 1;
+	opts.will->qos = 1;
+	opts.will->retained = 0;
+	opts.will->topicName = test6_will_topic;
+	if (options.haconnections != NULL)
+	{
+		opts.serverURIs = options.haconnections;
+		opts.serverURIcount = options.hacount;
+	}
+
+	/* Client-1 with Will options */
+	rc = MQTTClient_create(&test6_c1, options.proxy_connection, "Client_1", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
+	assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	rc = MQTTClient_setCallbacks(test6_c1, (void*)test6_c1, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
+	assert("good rc from setCallbacks",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	/* Connect to the broker */
+	rc = MQTTClient_connect(test6_c1, &opts);
+	assert("good rc from connect",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	/* Client - 2 (multi-threaded) */
+	rc = MQTTClient_create(&test6_c2, options.connection, "Client_2", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
+	assert("good rc from create",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* Set the callback functions for the client */
+	rc = MQTTClient_setCallbacks(test6_c2, (void*)test6_c2, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
+	assert("good rc from setCallbacks",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* Connect to the broker */
+	opts2.keepAliveInterval = 20;
+	opts2.cleansession = 1;
+	MyLog(LOGA_INFO, "Connecting Client_2 ...");
+	rc = MQTTClient_connect(test6_c2, &opts2);
+	assert("Good rc from connect", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	rc = MQTTClient_subscribe(test6_c2, test6_will_topic, 2);
+	assert("Good rc from subscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* now send the command which will break the connection and cause the will message to be sent */
+	rc = MQTTClient_publish(test6_c1, mqttsas_topic, (int)strlen("TERMINATE"), "TERMINATE", 0, 0, NULL);
+	assert("Good rc from publish", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	MyLog(LOGA_INFO, "Waiting to receive the will message");
+	count = 0;
+	while (++count < 40)
+	{
+		#if defined(WIN32)
+			Sleep(1000L);
+		#else
+			sleep(1);
+		#endif
+		if (test6_will_message_arrived == 1 && test6_connection_lost_called == 1)
+			break;
+	}
+	assert("will message arrived", test6_will_message_arrived == 1,
+							"will_message_arrived was %d\n", test6_will_message_arrived);
+	assert("connection lost called", test6_connection_lost_called == 1,
+			         "connection_lost_called %d\n", test6_connection_lost_called);
+
+	rc = MQTTClient_unsubscribe(test6_c2, test6_will_topic);
+	assert("Good rc from unsubscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
+
+	rc = MQTTClient_isConnected(test6_c2);
+	assert("Client-2 still connected", rc == 1, "isconnected is %d", rc);
+
+	rc = MQTTClient_isConnected(test6_c1);
+	assert("Client-1 not connected", rc == 0, "isconnected is %d", rc);
+
+	rc = MQTTClient_disconnect(test6_c2, 100L);
+	assert("Good rc from disconnect", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
+
+	MQTTClient_destroy(&test6_c1);
+	MQTTClient_destroy(&test6_c2);
+
+exit:
+	MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.\n",
+			(failures == 0) ? "passed" : "failed", testname, tests, failures);
+	write_test_result();
+	return failures;
+}
+#endif
+
+int main(int argc, char** argv)
+{
+	int rc = 0;
+ 	int (*tests[])() = {NULL, test1, test2, test3};
+	int i;
+
+	xml = fopen("TEST-test1.xml", "w");
+	fprintf(xml, "<testsuite name=\"test1\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
+
+	getopts(argc, argv);
+
+	for (i = 0; i < options.iterations; ++i)
+	{
+	 	if (options.test_no == 0)
+		{ /* run all the tests */
+ 		   	for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no)
+				rc += tests[options.test_no](options); /* return number of failures.  0 = test succeeded */
+		}
+		else
+ 		   	rc = tests[options.test_no](options); /* run just the selected test */
+	}
+
+ 	if (rc == 0)
+		MyLog(LOGA_INFO, "verdict pass");
+	else
+		MyLog(LOGA_INFO, "verdict fail");
+
+	fprintf(xml, "</testsuite>\n");
+	fclose(xml);
+	return rc;
+}

+ 21 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/CMakeLists.txt

@@ -0,0 +1,21 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+project("paho-mqttclient" C)
+
+#ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(samples)
+ADD_SUBDIRECTORY(test)

+ 17 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/CMakeLists.txt

@@ -0,0 +1,17 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+ADD_SUBDIRECTORY(linux)

+ 131 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/arduino/Hello/Hello.ino

@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp. and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution. 
+ *
+ * The Eclipse Public License is available at 
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial contribution
+ *    Benjamin Cabe - adapt to IPStack, and add Yun instructions
+ *******************************************************************************/
+
+#define MQTTCLIENT_QOS2 1
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <IPStack.h>
+#include <Countdown.h>
+#include <MQTTClient.h>
+
+char printbuf[100];
+
+int arrivedcount = 0;
+
+void messageArrived(MQTT::MessageData& md)
+{
+  MQTT::Message &message = md.message;
+  
+  sprintf(printbuf, "Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n", 
+		++arrivedcount, message.qos, message.retained, message.dup, message.id);
+  Serial.print(printbuf);
+  sprintf(printbuf, "Payload %s\n", (char*)message.payload);
+  Serial.print(printbuf);
+}
+
+EthernetClient c; // replace by a YunClient if running on a Yun
+IPStack ipstack(c);
+MQTT::Client<IPStack, Countdown> client = MQTT::Client<IPStack, Countdown>(ipstack);
+
+byte mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };  // replace with your device's MAC
+const char* topic = "arduino-sample";
+
+void connect()
+{
+  char hostname[] = "iot.eclipse.org";
+  int port = 1883;
+  sprintf(printbuf, "Connecting to %s:%d\n", hostname, port);
+  Serial.print(printbuf);
+  int rc = ipstack.connect(hostname, port);
+  if (rc != 1)
+  {
+    sprintf(printbuf, "rc from TCP connect is %d\n", rc);
+    Serial.print(printbuf);
+  }
+ 
+  Serial.println("MQTT connecting");
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
+  data.MQTTVersion = 3;
+  data.clientID.cstring = (char*)"arduino-sample";
+  rc = client.connect(data);
+  if (rc != 0)
+  {
+    sprintf(printbuf, "rc from MQTT connect is %d\n", rc);
+    Serial.print(printbuf);
+  }
+  Serial.println("MQTT connected");
+  
+  rc = client.subscribe(topic, MQTT::QOS2, messageArrived);   
+  if (rc != 0)
+  {
+    sprintf(printbuf, "rc from MQTT subscribe is %d\n", rc);
+    Serial.print(printbuf);
+  }
+  Serial.println("MQTT subscribed");
+}
+
+void setup()
+{
+  Serial.begin(9600);
+  Ethernet.begin(mac); // replace by Bridge.begin() if running on a Yun
+  Serial.println("MQTT Hello example");
+  connect();
+}
+
+void loop()
+{
+  if (!client.isConnected())
+    connect();
+  
+  MQTT::Message message;
+  
+  arrivedcount = 0;
+
+  // Send and receive QoS 0 message
+  char buf[100];
+  sprintf(buf, "Hello World! QoS 0 message");
+  Serial.println(buf);
+  message.qos = MQTT::QOS0;
+  message.retained = false;
+  message.dup = false;
+  message.payload = (void*)buf;
+  message.payloadlen = strlen(buf)+1;
+  int rc = client.publish(topic, message);
+  while (arrivedcount == 0)
+    client.yield(1000);
+        
+  // Send and receive QoS 1 message
+  sprintf(buf, "Hello World!  QoS 1 message");
+  Serial.println(buf);
+  message.qos = MQTT::QOS1;
+  message.payloadlen = strlen(buf)+1;
+  rc = client.publish(topic, message);
+  while (arrivedcount == 1)
+    client.yield(1000);
+        
+  // Send and receive QoS 2 message
+  sprintf(buf, "Hello World!  QoS 2 message");
+  Serial.println(buf);
+  message.qos = MQTT::QOS2;
+  message.payloadlen = strlen(buf)+1;
+  rc = client.publish(topic, message);
+  while (arrivedcount == 2)
+    client.yield(1000);
+    
+  delay(2000);
+}

+ 31 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/CMakeLists.txt

@@ -0,0 +1,31 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+# Samples
+
+add_executable(
+  hello
+  hello.cpp
+)
+target_include_directories(hello PRIVATE "../../src" "../../src/linux")
+target_link_libraries(hello MQTTPacketClient)
+
+add_executable(
+  stdoutsub
+  stdoutsub.cpp
+)
+target_include_directories(stdoutsub PRIVATE "../../src" "../../src/linux")
+target_link_libraries(stdoutsub paho-embed-mqtt3c)

+ 3 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/build.sh

@@ -0,0 +1,3 @@
+g++ hello.cpp -I ../../src/ -I ../../src/linux -I ../../../MQTTPacket/src ../../../MQTTPacket/src/MQTTPacket.c ../../../MQTTPacket/src/MQTTDeserializePublish.c ../../../MQTTPacket/src/MQTTConnectClient.c ../../../MQTTPacket/src/MQTTSubscribeClient.c ../../../MQTTPacket/src/MQTTSerializePublish.c ../../../MQTTPacket/src/MQTTUnsubscribeClient.c -o hello
+
+g++ -g stdoutsub.cpp -I ../../src -I ../../src/linux -I ../../../MQTTPacket/src ../../../MQTTPacket/src/MQTTFormat.c  ../../../MQTTPacket/src/MQTTPacket.c ../../../MQTTPacket/src/MQTTDeserializePublish.c ../../../MQTTPacket/src/MQTTConnectClient.c ../../../MQTTPacket/src/MQTTSubscribeClient.c ../../../MQTTPacket/src/MQTTSerializePublish.c -o stdoutsub ../../../MQTTPacket/src/MQTTConnectServer.c ../../../MQTTPacket/src/MQTTSubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeClient.c  

+ 104 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/hello.cpp

@@ -0,0 +1,104 @@
+#define MQTTCLIENT_QOS2 1
+
+#include <memory.h>
+
+#include "MQTTClient.h"
+
+#define DEFAULT_STACK_SIZE -1
+
+#include "linux.cpp"
+
+int arrivedcount = 0;
+
+void messageArrived(MQTT::MessageData& md)
+{
+    MQTT::Message &message = md.message;
+
+    printf("Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n", 
+		++arrivedcount, message.qos, message.retained, message.dup, message.id);
+    printf("Payload %.*s\n", (int)message.payloadlen, (char*)message.payload);
+}
+
+
+int main(int argc, char* argv[])
+{   
+    IPStack ipstack = IPStack();
+    float version = 0.3;
+    const char* topic = "mbed-sample";
+    
+    printf("Version is %f\n", version);
+              
+    MQTT::Client<IPStack, Countdown> client = MQTT::Client<IPStack, Countdown>(ipstack);
+    
+    const char* hostname = "iot.eclipse.org";
+    int port = 1883;
+    printf("Connecting to %s:%d\n", hostname, port);
+    int rc = ipstack.connect(hostname, port);
+	if (rc != 0)
+	    printf("rc from TCP connect is %d\n", rc);
+ 
+	printf("MQTT connecting\n");
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
+    data.MQTTVersion = 3;
+    data.clientID.cstring = (char*)"mbed-icraggs";
+    rc = client.connect(data);
+	if (rc != 0)
+	    printf("rc from MQTT connect is %d\n", rc);
+	printf("MQTT connected\n");
+    
+    rc = client.subscribe(topic, MQTT::QOS2, messageArrived);   
+    if (rc != 0)
+        printf("rc from MQTT subscribe is %d\n", rc);
+
+    MQTT::Message message;
+
+    // QoS 0
+    char buf[100];
+    sprintf(buf, "Hello World!  QoS 0 message from app version %f", version);
+    message.qos = MQTT::QOS0;
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf;
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message);
+	if (rc != 0)
+		printf("Error %d from sending QoS 0 message\n", rc);
+    else while (arrivedcount == 0)
+        client.yield(100);
+        
+    // QoS 1
+	printf("Now QoS 1\n");
+    sprintf(buf, "Hello World!  QoS 1 message from app version %f", version);
+    message.qos = MQTT::QOS1;
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message);
+	if (rc != 0)
+		printf("Error %d from sending QoS 1 message\n", rc);
+    else while (arrivedcount == 1)
+        client.yield(100);
+        
+    // QoS 2
+    sprintf(buf, "Hello World!  QoS 2 message from app version %f", version);
+    message.qos = MQTT::QOS2;
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message);
+	if (rc != 0)
+		printf("Error %d from sending QoS 2 message\n", rc);
+    while (arrivedcount == 2)
+        client.yield(100);
+    
+    rc = client.unsubscribe(topic);
+    if (rc != 0)
+        printf("rc from unsubscribe was %d\n", rc);
+    
+    rc = client.disconnect();
+    if (rc != 0)
+        printf("rc from disconnect was %d\n", rc);
+    
+    ipstack.disconnect();
+    
+    printf("Finishing with %d messages received\n", arrivedcount);
+    
+    return 0;
+}
+

+ 291 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/main.cpp

@@ -0,0 +1,291 @@
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include "MQTTClient.h"
+//#include "FP.cpp"
+
+#define DEFAULT_STACK_SIZE -1
+
+
+class IPStack 
+{
+public:    
+    IPStack()
+    {
+
+    }
+    
+	int Socket_error(const char* aString)
+	{
+
+		if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK)
+		{
+			if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET))
+				printf("Socket error %s in %s for socket %d\n", strerror(errno), aString, mysock);
+		}
+		return errno;
+	}
+
+    int connect(const char* hostname, int port)
+    {
+		int type = SOCK_STREAM;
+		struct sockaddr_in address;
+		int rc = -1;
+		sa_family_t family = AF_INET;
+		struct addrinfo *result = NULL;
+		struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};
+
+		if ((rc = getaddrinfo(hostname, NULL, &hints, &result)) == 0)
+		{
+			struct addrinfo* res = result;
+
+			/* prefer ip4 addresses */
+			while (res)
+			{
+				if (res->ai_family == AF_INET)
+				{
+					result = res;
+					break;
+				}
+				res = res->ai_next;
+			}
+
+			if (result->ai_family == AF_INET)
+			{
+				address.sin_port = htons(port);
+				address.sin_family = family = AF_INET;
+				address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
+			}
+			else
+				rc = -1;
+
+			freeaddrinfo(result);
+		}
+
+		if (rc == 0)
+		{
+			mysock = socket(family, type, 0);
+			if (mysock != -1)
+			{
+				int opt = 1;
+
+				//if (setsockopt(mysock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0)
+				//	printf("Could not set SO_NOSIGPIPE for socket %d", mysock);
+				
+				rc = ::connect(mysock, (struct sockaddr*)&address, sizeof(address));
+			}
+		}
+
+        return rc;
+    }
+
+    int read(unsigned char* buffer, int len, int timeout_ms)
+    {
+		struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
+		if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))
+		{
+			interval.tv_sec = 0;
+			interval.tv_usec = 100;
+		}
+
+		setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
+
+		//printf("reading %d bytes\n", len);
+		int rc = ::recv(mysock, buffer, (size_t)len, 0);
+		if (rc == -1)
+			Socket_error("read");
+		//printf("read %d bytes\n", rc);
+		return rc;
+    }
+    
+    int write(unsigned char* buffer, int len, int timeout)
+    {
+		struct timeval tv;
+
+		tv.tv_sec = 0;  /* 30 Secs Timeout */
+		tv.tv_usec = timeout * 1000;  // Not init'ing this can cause strange errors
+
+		setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
+		int	rc = ::write(mysock, buffer, len);
+		//printf("write rc %d\n", rc);
+		return rc;
+    }
+
+	int disconnect()
+	{
+		return ::close(mysock);
+	}
+    
+private:
+
+    int mysock; 
+    
+};
+
+
+class Countdown
+{
+public:
+    Countdown()
+    { 
+	
+    }
+
+    Countdown(int ms)
+    { 
+		countdown_ms(ms);
+    }
+    
+
+    bool expired()
+    {
+		struct timeval now, res;
+		gettimeofday(&now, NULL);
+		timersub(&end_time, &now, &res);		
+		//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);
+		//if (res.tv_sec > 0 || res.tv_usec > 0)
+		//	printf("expired %d %d\n", res.tv_sec, res.tv_usec);
+        return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);
+    }
+    
+
+    void countdown_ms(int ms)  
+    {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		struct timeval interval = {ms / 1000, (ms % 1000) * 1000};
+		//printf("interval %d %d\n", interval.tv_sec, interval.tv_usec);
+		timeradd(&now, &interval, &end_time);
+    }
+
+    
+    void countdown(int seconds)
+    {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		struct timeval interval = {seconds, 0};
+		timeradd(&now, &interval, &end_time);
+    }
+
+    
+    int left_ms()
+    {
+		struct timeval now, res;
+		gettimeofday(&now, NULL);
+		timersub(&end_time, &now, &res);
+		//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);
+        return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
+    }
+    
+private:
+
+	struct timeval end_time;
+};
+
+
+int arrivedcount = 0;
+
+void messageArrived(MQTT::MessageData& md)
+{
+    MQTT::Message &message = md.message;
+
+	printf("Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n", 
+		++arrivedcount, message.qos, message.retained, message.dup, message.id);
+    printf("Payload %.*s\n", message.payloadlen, (char*)message.payload);
+}
+
+
+int main(int argc, char* argv[])
+{   
+    IPStack ipstack = IPStack();
+    float version = 0.3;
+    const char* topic = "mbed-sample";
+    
+    printf("Version is %f\n", version);
+              
+    MQTT::Client<IPStack, Countdown> client = MQTT::Client<IPStack, Countdown>(ipstack);
+    
+    const char* hostname = "localhost"; //"m2m.eclipse.org";
+    int port = 1883;
+    printf("Connecting to %s:%d\n", hostname, port);
+    int rc = ipstack.connect(hostname, port);
+	if (rc != 0)
+	    printf("rc from TCP connect is %d\n", rc);
+ 
+	printf("MQTT connecting\n");
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
+    data.MQTTVersion = 3;
+    data.clientID.cstring = (char*)"mbed-icraggs";
+    rc = client.connect(&data);
+	if (rc != 0)
+	    printf("rc from MQTT connect is %d\n", rc);
+	printf("MQTT connected\n");
+    
+    rc = client.subscribe("+", MQTT::QOS2, messageArrived);   
+    if (rc != 0)
+        printf("rc from MQTT subscribe is %d\n", rc);
+
+    MQTT::Message message;
+
+    // QoS 0
+    char buf[100];
+    sprintf(buf, "Hello World!  QoS 0 message from app version %f", version);
+    message.qos = MQTT::QOS0;
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf;
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, &message);
+    while (arrivedcount == 0)
+        client.yield(100);
+        
+    // QoS 1
+	printf("Now QoS 1\n");
+    sprintf(buf, "Hello World!  QoS 1 message from app version %f", version);
+    message.qos = MQTT::QOS1;
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, &message);
+    while (arrivedcount == 1)
+        client.yield(100);
+        
+    // QoS 2
+    sprintf(buf, "Hello World!  QoS 2 message from app version %f", version);
+    message.qos = MQTT::QOS2;
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, &message);
+    while (arrivedcount == 2)
+        client.yield(100);
+    
+    rc = client.unsubscribe(topic);
+    if (rc != 0)
+        printf("rc from unsubscribe was %d\n", rc);
+    
+    rc = client.disconnect();
+    if (rc != 0)
+        printf("rc from disconnect was %d\n", rc);
+    
+    ipstack.disconnect();
+    
+    printf("Finishing with %d messages received\n", arrivedcount);
+    
+    return 0;
+}
+
+

+ 265 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/samples/linux/stdoutsub.cpp

@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution. 
+ *
+ * The Eclipse Public License is available at 
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial contribution
+ *    Ian Craggs - change delimiter option from char to string
+ *******************************************************************************/
+
+/*
+ 
+ stdout subscriber
+ 
+ compulsory parameters:
+ 
+  topic to subscribe to
+ 
+ defaulted parameters:
+ 
+	--host localhost
+	--port 1883
+	--qos 2
+	--delimiter \n
+	--clientid stdout_subscriber
+	
+	--userid none
+	--password none
+ 
+*/
+#include <stdio.h>
+#include <memory.h>
+#define MQTT_DEBUG 1
+#include "MQTTClient.h"
+
+#define DEFAULT_STACK_SIZE -1
+
+#include "linux.cpp"
+
+#include <signal.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+
+volatile int toStop = 0;
+
+
+void usage()
+{
+	printf("MQTT stdout subscriber\n");
+	printf("Usage: stdoutsub topicname <options>, where options are:\n");
+	printf("  --host <hostname> (default is localhost)\n");
+	printf("  --port <port> (default is 1883)\n");
+	printf("  --qos <qos> (default is 2)\n");
+	printf("  --delimiter <delim> (default is \\n)\n");
+	printf("  --clientid <clientid> (default is hostname+timestamp)\n");
+	printf("  --username none\n");
+	printf("  --password none\n");
+	printf("  --showtopics <on or off> (default is on if the topic has a wildcard, else off)\n");
+	exit(-1);
+}
+
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+
+struct opts_struct
+{
+	char* clientid;
+	int nodelimiter;
+	char* delimiter;
+	MQTT::QoS qos;
+	char* username;
+	char* password;
+	char* host;
+	int port;
+	int showtopics;
+} opts =
+{
+	(char*)"stdout-subscriber", 0, (char*)"\n", MQTT::QOS2, NULL, NULL, (char*)"localhost", 1883, 0
+};
+
+
+void getopts(int argc, char** argv)
+{
+	int count = 2;
+	
+	while (count < argc)
+	{
+		if (strcmp(argv[count], "--qos") == 0)
+		{
+			if (++count < argc)
+			{
+				if (strcmp(argv[count], "0") == 0)
+					opts.qos = MQTT::QOS0;
+				else if (strcmp(argv[count], "1") == 0)
+					opts.qos = MQTT::QOS1;
+				else if (strcmp(argv[count], "2") == 0)
+					opts.qos = MQTT::QOS2;
+				else
+					usage();
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--host") == 0)
+		{
+			if (++count < argc)
+				opts.host = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--port") == 0)
+		{
+			if (++count < argc)
+				opts.port = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--clientid") == 0)
+		{
+			if (++count < argc)
+				opts.clientid = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--username") == 0)
+		{
+			if (++count < argc)
+				opts.username = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--password") == 0)
+		{
+			if (++count < argc)
+				opts.password = argv[count];
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--delimiter") == 0)
+		{
+			if (++count < argc)
+				opts.delimiter = argv[count];
+			else
+				opts.nodelimiter = 1;
+		}
+		else if (strcmp(argv[count], "--showtopics") == 0)
+		{
+			if (++count < argc)
+			{
+				if (strcmp(argv[count], "on") == 0)
+					opts.showtopics = 1;
+				else if (strcmp(argv[count], "off") == 0)
+					opts.showtopics = 0;
+				else
+					usage();
+			}
+			else
+				usage();
+		}
+		count++;
+	}
+	
+}
+
+
+void myconnect(IPStack& ipstack, MQTT::Client<IPStack, Countdown, 1000>& client, MQTTPacket_connectData& data)
+{
+	printf("Connecting to %s:%d\n", opts.host, opts.port);
+	int rc = ipstack.connect(opts.host, opts.port);
+	if (rc != 0)
+	    printf("rc from TCP connect is %d\n", rc);
+
+	rc = client.connect(data);
+	if (rc != 0)
+	{
+		printf("Failed to connect, return code %d\n", rc);
+		exit(-1);	
+	}
+	printf("Connected\n");
+}
+
+
+void messageArrived(MQTT::MessageData& md)
+{
+	MQTT::Message &message = md.message;
+
+	if (opts.showtopics)
+		printf("%.*s\t", md.topicName.lenstring.len, md.topicName.lenstring.data);
+	if (opts.nodelimiter)
+		printf("%.*s", (int)message.payloadlen, (char*)message.payload);
+	else
+		printf("%.*s%s", (int)message.payloadlen, (char*)message.payload, opts.delimiter);
+	fflush(stdout);
+}
+
+
+int main(int argc, char** argv)
+{
+	int rc = 0;
+	
+	if (argc < 2)
+		usage();
+	
+	char* topic = argv[1];
+
+	if (strchr(topic, '#') || strchr(topic, '+'))
+		opts.showtopics = 1;
+	if (opts.showtopics)
+		printf("topic is %s\n", topic);
+
+	getopts(argc, argv);	
+
+	IPStack ipstack = IPStack();
+	MQTT::Client<IPStack, Countdown, 1000> client = MQTT::Client<IPStack, Countdown, 1000>(ipstack);
+
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+ 
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
+	data.willFlag = 0;
+	data.MQTTVersion = 3;
+	data.clientID.cstring = opts.clientid;
+	data.username.cstring = opts.username;
+	data.password.cstring = opts.password;
+
+	data.keepAliveInterval = 10;
+	data.cleansession = 1;
+	printf("will flag %d\n", data.willFlag);
+	
+	myconnect(ipstack, client, data);
+    
+	rc = client.subscribe(topic, opts.qos, messageArrived);
+	printf("Subscribed %d\n", rc);
+
+	while (!toStop)
+	{
+		client.yield(1000);	
+
+		//if (!client.isconnected)
+		//	myconnect(ipstack, client, data);
+	}
+	
+	printf("Stopping\n");
+
+	rc = client.disconnect();
+
+	ipstack.disconnect();
+
+	return 0;
+}
+
+

+ 208 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/FP.h

@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2014 
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Sam Grove - initial API and implementation and/or initial documentation
+ *    Ian Craggs - added attached and detached member functions
+ *    Sam Grove - removed need for FP.cpp
+ *******************************************************************************/
+
+#ifndef FP_H
+#define FP_H
+
+/** Example using the FP Class with global functions
+ * @code
+ *  #include "mbed.h"
+ *  #include "FP.h"
+ *
+ *  FP<void,bool>fp;
+ *  DigitalOut myled(LED1);
+ *
+ *  void handler(bool value)
+ *  {
+ *      myled = value;
+ *      return;
+ *  }
+ *
+ *  int main()
+ *  {
+ *      fp.attach(&handler);
+ *
+ *      while(1)
+ *      {
+ *          fp(1);
+ *          wait(0.2);
+ *          fp(0);
+ *          wait(0.2);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/** Example using the FP Class with different class member functions
+ * @code
+ *  #include "mbed.h"
+ *  #include "FP.h"
+ *
+ *  FP<void,bool>fp;
+ *  DigitalOut myled(LED4);
+ *
+ *  class Wrapper
+ *  {
+ *  public:
+ *      Wrapper(){}
+ *
+ *      void handler(bool value)
+ *      {
+ *          myled = value;
+ *          return;
+ *      }
+ *  };
+ *
+ *  int main()
+ *  {
+ *      Wrapper wrapped;
+ *      fp.attach(&wrapped, &Wrapper::handler);
+ *
+ *      while(1)
+ *      {
+ *          fp(1);
+ *          wait(0.2);
+ *          fp(0);
+ *          wait(0.2);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/** Example using the FP Class with member FP and member function
+* @code
+*  #include "mbed.h"
+*  #include "FP.h"
+*
+*  DigitalOut myled(LED2);
+*
+*  class Wrapper
+*  {
+*  public:
+*      Wrapper()
+*      {
+*          fp.attach(this, &Wrapper::handler);
+*      }
+*
+*      void handler(bool value)
+*      {
+*          myled = value;
+*          return;
+*      }
+*
+*      FP<void,bool>fp;
+*  };
+*
+*  int main()
+*  {
+*      Wrapper wrapped;
+*
+*      while(1)
+*      {
+*          wrapped.fp(1);
+*          wait(0.2);
+*          wrapped.fp(0);
+*          wait(0.2);
+*      }
+*  }
+* @endcode
+*/
+
+/**
+ *  @class FP
+ *  @brief API for managing Function Pointers
+ */
+template<class retT, class argT>
+class FP
+{
+public:
+    /** Create the FP object - only one callback can be attached to the object, that is
+     *  a member function or a global function, not both at the same time
+     */
+    FP()
+    {
+        obj_callback = 0;
+        c_callback = 0;
+    }
+
+    /** Add a callback function to the object
+     *  @param item - Address of the initialized object
+     *  @param member - Address of the member function (dont forget the scope that the function is defined in)
+     */
+    template<class T>
+    void attach(T *item, retT (T::*method)(argT))
+    {
+        obj_callback = (FPtrDummy *)(item);
+        method_callback = (retT (FPtrDummy::*)(argT))(method);
+        return;
+    }
+
+    /** Add a callback function to the object
+     *  @param function - The address of a globally defined function
+     */
+    void attach(retT (*function)(argT))
+    {
+        c_callback = function;
+    }
+
+    /** Invoke the function attached to the class
+     *  @param arg - An argument that is passed into the function handler that is called
+     *  @return The return from the function hanlder called by this class
+     */
+    retT operator()(argT arg) const
+    {
+        if( 0 != c_callback ) {
+            return obj_callback ? (obj_callback->*method_callback)(arg) : (*c_callback)(arg);
+        }
+        return (retT)0;
+    }
+
+    /** Determine if an callback is currently hooked
+     *  @return 1 if a method is hooked, 0 otherwise
+     */
+    bool attached()
+    {
+        return obj_callback || c_callback;
+    }
+
+    /** Release a function from the callback hook
+     */
+    void detach()
+    {
+        obj_callback = 0;
+        c_callback = 0;
+    }
+
+private:
+
+    // empty type used for casting
+    class FPtrDummy;
+
+    FPtrDummy *obj_callback;
+
+    /**
+     *  @union Funciton
+     *  @brief Member or global callback function
+     */
+    union {
+        retT (*c_callback)(argT);                   /*!< Footprint for a global function */
+        retT (FPtrDummy::*method_callback)(argT);   /*!< Footprint for a member function */
+    };
+};
+
+#endif

+ 1046 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/MQTTClient.h

@@ -0,0 +1,1046 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for bug 458512 - QoS 2 messages
+ *    Ian Craggs - fix for bug 460389 - send loop uses wrong length
+ *    Ian Craggs - fix for bug 464169 - clearing subscriptions
+ *    Ian Craggs - fix for bug 464551 - enums and ints can be different size
+ *    Mark Sonnentag - fix for bug 475204 - inefficient instantiation of Timer
+ *    Ian Craggs - fix for bug 475749 - packetid modified twice
+ *    Ian Craggs - add ability to set message handler separately #6
+ *******************************************************************************/
+
+#if !defined(MQTTCLIENT_H)
+#define MQTTCLIENT_H
+
+#include "FP.h"
+#include "MQTTPacket.h"
+#include <stdio.h>
+#include "MQTTLogging.h"
+
+#if !defined(MQTTCLIENT_QOS1)
+    #define MQTTCLIENT_QOS1 1
+#endif
+#if !defined(MQTTCLIENT_QOS2)
+    #define MQTTCLIENT_QOS2 0
+#endif
+
+namespace MQTT
+{
+
+
+enum QoS { QOS0, QOS1, QOS2 };
+
+// all failure return codes must be negative
+enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };
+
+
+struct Message
+{
+    enum QoS qos;
+    bool retained;
+    bool dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+};
+
+
+struct MessageData
+{
+    MessageData(MQTTString &aTopicName, struct Message &aMessage)  : message(aMessage), topicName(aTopicName)
+    { }
+
+    struct Message &message;
+    MQTTString &topicName;
+};
+
+
+struct connackData
+{
+    int rc;
+    bool sessionPresent;
+};
+
+
+struct subackData
+{
+    int grantedQoS;
+};
+
+
+class PacketId
+{
+public:
+    PacketId()
+    {
+        next = 0;
+    }
+
+    int getNext()
+    {
+        return next = (next == MAX_PACKET_ID) ? 1 : next + 1;
+    }
+
+private:
+    static const int MAX_PACKET_ID = 65535;
+    int next;
+};
+
+
+/**
+ * @class Client
+ * @brief blocking, non-threaded MQTT client API
+ *
+ * This version of the API blocks on all method calls, until they are complete.  This means that only one
+ * MQTT request can be in process at any one time.
+ * @param Network a network class which supports send, receive
+ * @param Timer a timer class with the methods:
+ */
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE = 100, int MAX_MESSAGE_HANDLERS = 5>
+class Client
+{
+
+public:
+
+    typedef void (*messageHandler)(MessageData&);
+
+    /** Construct the client
+     *  @param network - pointer to an instance of the Network class - must be connected to the endpoint
+     *      before calling MQTT connect
+     *  @param limits an instance of the Limit class - to alter limits as required
+     */
+    Client(Network& network, unsigned int command_timeout_ms = 30000);
+
+    /** Set the default message handling callback - used for any message which does not match a subscription message handler
+     *  @param mh - pointer to the callback function.  Set to 0 to remove.
+     */
+    void setDefaultMessageHandler(messageHandler mh)
+    {
+        if (mh != 0)
+            defaultMessageHandler.attach(mh);
+        else
+            defaultMessageHandler.detach();
+    }
+
+    /** Set a message handling callback.  This can be used outside of the the subscribe method.
+     *  @param topicFilter - a topic pattern which can include wildcards
+     *  @param mh - pointer to the callback function. If 0, removes the callback if any
+     */
+    int setMessageHandler(const char* topicFilter, messageHandler mh);
+
+    /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+     *  The nework object must be connected to the network endpoint before calling this
+     *  Default connect options are used
+     *  @return success code -
+     */
+    int connect();
+
+    /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+     *  The nework object must be connected to the network endpoint before calling this
+     *  @param options - connect options
+     *  @return success code -
+     */
+    int connect(MQTTPacket_connectData& options);
+
+    /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+     *  The nework object must be connected to the network endpoint before calling this
+     *  @param options - connect options
+     *  @param connackData - connack data to be returned
+     *  @return success code -
+     */
+    int connect(MQTTPacket_connectData& options, connackData& data);
+
+    /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+     *  @param topic - the topic to publish to
+     *  @param message - the message to send
+     *  @return success code -
+     */
+    int publish(const char* topicName, Message& message);
+
+    /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+     *  @param topic - the topic to publish to
+     *  @param payload - the data to send
+     *  @param payloadlen - the length of the data
+     *  @param qos - the QoS to send the publish at
+     *  @param retained - whether the message should be retained
+     *  @return success code -
+     */
+    int publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos = QOS0, bool retained = false);
+
+    /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+     *  @param topic - the topic to publish to
+     *  @param payload - the data to send
+     *  @param payloadlen - the length of the data
+     *  @param id - the packet id used - returned
+     *  @param qos - the QoS to send the publish at
+     *  @param retained - whether the message should be retained
+     *  @return success code -
+     */
+    int publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos = QOS1, bool retained = false);
+
+    /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
+     *  @param topicFilter - a topic pattern which can include wildcards
+     *  @param qos - the MQTT QoS to subscribe at
+     *  @param mh - the callback function to be invoked when a message is received for this subscription
+     *  @return success code -
+     */
+    int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh);
+
+    /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
+     *  @param topicFilter - a topic pattern which can include wildcards
+     *  @param qos - the MQTT QoS to subscribe at©
+     *  @param mh - the callback function to be invoked when a message is received for this subscription
+     *  @param
+     *  @return success code -
+     */
+    int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh, subackData &data);
+
+    /** MQTT Unsubscribe - send an MQTT unsubscribe packet and wait for the unsuback
+     *  @param topicFilter - a topic pattern which can include wildcards
+     *  @return success code -
+     */
+    int unsubscribe(const char* topicFilter);
+
+    /** MQTT Disconnect - send an MQTT disconnect packet, and clean up any state
+     *  @return success code -
+     */
+    int disconnect();
+
+    /** A call to this API must be made within the keepAlive interval to keep the MQTT connection alive
+     *  yield can be called if no other MQTT operation is needed.  This will also allow messages to be
+     *  received.
+     *  @param timeout_ms the time to wait, in milliseconds
+     *  @return success code - on failure, this means the client has disconnected
+     */
+    int yield(unsigned long timeout_ms = 1000L);
+
+    /** Is the client connected?
+     *  @return flag - is the client connected or not?
+     */
+    bool isConnected()
+    {
+        return isconnected;
+    }
+
+private:
+
+    void closeSession();
+    void cleanSession();
+    int cycle(Timer& timer);
+    int waitfor(int packet_type, Timer& timer);
+    int keepalive();
+    int publish(int len, Timer& timer, enum QoS qos);
+
+    int decodePacket(int* value, int timeout);
+    int readPacket(Timer& timer);
+    int sendPacket(int length, Timer& timer);
+    int deliverMessage(MQTTString& topicName, Message& message);
+    bool isTopicMatched(char* topicFilter, MQTTString& topicName);
+
+    Network& ipstack;
+    unsigned long command_timeout_ms;
+
+    unsigned char sendbuf[MAX_MQTT_PACKET_SIZE];
+    unsigned char readbuf[MAX_MQTT_PACKET_SIZE];
+
+    Timer last_sent, last_received;
+    unsigned int keepAliveInterval;
+    bool ping_outstanding;
+    bool cleansession;
+
+    PacketId packetid;
+
+    struct MessageHandlers
+    {
+        const char* topicFilter;
+        FP<void, MessageData&> fp;
+    } messageHandlers[MAX_MESSAGE_HANDLERS];      // Message handlers are indexed by subscription topic
+
+    FP<void, MessageData&> defaultMessageHandler;
+
+    bool isconnected;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    unsigned char pubbuf[MAX_MQTT_PACKET_SIZE];  // store the last publish for sending on reconnect
+    int inflightLen;
+    unsigned short inflightMsgid;
+    enum QoS inflightQoS;
+#endif
+
+#if MQTTCLIENT_QOS2
+    bool pubrel;
+    #if !defined(MAX_INCOMING_QOS2_MESSAGES)
+        #define MAX_INCOMING_QOS2_MESSAGES 10
+    #endif
+    unsigned short incomingQoS2messages[MAX_INCOMING_QOS2_MESSAGES];
+    bool isQoS2msgidFree(unsigned short id);
+    bool useQoS2msgid(unsigned short id);
+	void freeQoS2msgid(unsigned short id);
+#endif
+
+};
+
+}
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::cleanSession()
+{
+    for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        messageHandlers[i].topicFilter = 0;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    inflightMsgid = 0;
+    inflightQoS = QOS0;
+#endif
+
+#if MQTTCLIENT_QOS2
+    pubrel = false;
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+        incomingQoS2messages[i] = 0;
+#endif
+}
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::closeSession()
+{
+    ping_outstanding = false;
+    isconnected = false;
+    if (cleansession)
+        cleanSession();
+}
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::Client(Network& network, unsigned int command_timeout_ms)  : ipstack(network), packetid()
+{
+    this->command_timeout_ms = command_timeout_ms;
+    cleansession = true;
+	  closeSession();
+}
+
+
+#if MQTTCLIENT_QOS2
+template<class Network, class Timer, int a, int b>
+bool MQTT::Client<Network, Timer, a, b>::isQoS2msgidFree(unsigned short id)
+{
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+    {
+        if (incomingQoS2messages[i] == id)
+            return false;
+    }
+    return true;
+}
+
+
+template<class Network, class Timer, int a, int b>
+bool MQTT::Client<Network, Timer, a, b>::useQoS2msgid(unsigned short id)
+{
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+    {
+        if (incomingQoS2messages[i] == 0)
+        {
+            incomingQoS2messages[i] = id;
+            return true;
+        }
+    }
+    return false;
+}
+
+
+template<class Network, class Timer, int a, int b>
+void MQTT::Client<Network, Timer, a, b>::freeQoS2msgid(unsigned short id)
+{
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+    {
+        if (incomingQoS2messages[i] == id)
+        {
+            incomingQoS2messages[i] = 0;
+            return;
+        }
+    }
+}
+#endif
+
+
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::sendPacket(int length, Timer& timer)
+{
+    int rc = FAILURE,
+        sent = 0;
+
+    while (sent < length && !timer.expired())
+    {
+        rc = ipstack.write(&sendbuf[sent], length - sent, timer.left_ms());
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    if (sent == length)
+    {
+        if (this->keepAliveInterval > 0)
+            last_sent.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet
+        rc = SUCCESS;
+    }
+    else
+        rc = FAILURE;
+
+#if defined(MQTT_DEBUG)
+    char printbuf[150];
+    DEBUG("Rc %d from sending packet %s\n", rc, MQTTFormat_toServerString(printbuf, sizeof(printbuf), sendbuf, length));
+#endif
+    return rc;
+}
+
+
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::decodePacket(int* value, int timeout)
+{
+    unsigned char c;
+    int multiplier = 1;
+    int len = 0;
+    const int 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 = ipstack.read(&c, 1, timeout);
+        if (rc != 1)
+            goto exit;
+        *value += (c & 127) * multiplier;
+        multiplier *= 128;
+    } while ((c & 128) != 0);
+exit:
+    return len;
+}
+
+
+/**
+ * If any read fails in this method, then we should disconnect from the network, as on reconnect
+ * the packets can be retried.
+ * @param timeout the max time to wait for the packet read to complete, in milliseconds
+ * @return the MQTT packet type, 0 if none, -1 if error
+ */
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::readPacket(Timer& timer)
+{
+    int rc = FAILURE;
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    rc = ipstack.read(readbuf, 1, timer.left_ms());
+    if (rc != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    decodePacket(&rem_len, timer.left_ms());
+    len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length into the buffer */
+
+    if (rem_len > (MAX_MQTT_PACKET_SIZE - len))
+    {
+        rc = BUFFER_OVERFLOW;
+        goto exit;
+    }
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (rem_len > 0 && (ipstack.read(readbuf + len, rem_len, timer.left_ms()) != rem_len))
+        goto exit;
+
+    header.byte = readbuf[0];
+    rc = header.bits.type;
+    if (this->keepAliveInterval > 0)
+        last_received.countdown(this->keepAliveInterval); // record the fact that we have successfully received a packet
+exit:
+
+#if defined(MQTT_DEBUG)
+    if (rc >= 0)
+    {
+        char printbuf[50];
+        DEBUG("Rc %d from receiving packet %s\n", rc,
+            MQTTFormat_toClientString(printbuf, sizeof(printbuf), readbuf, len));
+    }
+#endif
+    return rc;
+}
+
+
+// assume topic filter and name is in correct format
+// # can only be at end
+// + and # can only be next to separator
+template<class Network, class Timer, int a, int b>
+bool MQTT::Client<Network, Timer, a, b>::isTopicMatched(char* topicFilter, MQTTString& topicName)
+{
+    char* curf = topicFilter;
+    char* curn = topicName.lenstring.data;
+    char* curn_end = curn + topicName.lenstring.len;
+
+    while (*curf && curn < curn_end)
+    {
+        if (*curn == '/' && *curf != '/')
+            break;
+        if (*curf != '+' && *curf != '#' && *curf != *curn)
+            break;
+        if (*curf == '+')
+        {   // skip until we meet the next separator, or end of string
+            char* nextpos = curn + 1;
+            while (nextpos < curn_end && *nextpos != '/')
+                nextpos = ++curn + 1;
+        }
+        else if (*curf == '#')
+            curn = curn_end - 1;    // skip until end of string
+        curf++;
+        curn++;
+    };
+
+    return (curn == curn_end) && (*curf == '\0');
+}
+
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::deliverMessage(MQTTString& topicName, Message& message)
+{
+    int rc = FAILURE;
+
+    // we have to find the right message handler - indexed by topic
+    for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(&topicName, (char*)messageHandlers[i].topicFilter) ||
+                isTopicMatched((char*)messageHandlers[i].topicFilter, topicName)))
+        {
+            if (messageHandlers[i].fp.attached())
+            {
+                MessageData md(topicName, message);
+                messageHandlers[i].fp(md);
+                rc = SUCCESS;
+            }
+        }
+    }
+
+    if (rc == FAILURE && defaultMessageHandler.attached())
+    {
+        MessageData md(topicName, message);
+        defaultMessageHandler(md);
+        rc = SUCCESS;
+    }
+
+    return rc;
+}
+
+
+
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::yield(unsigned long timeout_ms)
+{
+    int rc = SUCCESS;
+    Timer timer;
+
+    timer.countdown_ms(timeout_ms);
+    while (!timer.expired())
+    {
+        if (cycle(timer) < 0)
+        {
+            rc = FAILURE;
+            break;
+        }
+    }
+
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::cycle(Timer& timer)
+{
+    // get one piece of work off the wire and one pass through
+    int len = 0,
+        rc = SUCCESS;
+
+    int packet_type = readPacket(timer);    // read the socket, see what work is due
+
+    switch (packet_type)
+    {
+        default:
+            // no more data to read, unrecoverable. Or read packet fails due to unexpected network error
+            rc = packet_type;
+            goto exit;
+        case 0: // timed out reading packet
+            break;
+        case CONNACK:
+        case PUBACK:
+        case SUBACK:
+            break;
+        case PUBLISH:
+        {
+            MQTTString topicName = MQTTString_initializer;
+            Message msg;
+            int intQoS;
+            msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */
+            if (MQTTDeserialize_publish((unsigned char*)&msg.dup, &intQoS, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
+                                 (unsigned char**)&msg.payload, (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                goto exit;
+            msg.qos = (enum QoS)intQoS;
+#if MQTTCLIENT_QOS2
+            if (msg.qos != QOS2)
+#endif
+                deliverMessage(topicName, msg);
+#if MQTTCLIENT_QOS2
+            else if (isQoS2msgidFree(msg.id))
+            {
+                if (useQoS2msgid(msg.id))
+                    deliverMessage(topicName, msg);
+                else
+                    WARN("Maximum number of incoming QoS2 messages exceeded");
+            }
+#endif
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+            if (msg.qos != QOS0)
+            {
+                if (msg.qos == QOS1)
+                    len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBACK, 0, msg.id);
+                else if (msg.qos == QOS2)
+                    len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREC, 0, msg.id);
+                if (len <= 0)
+                    rc = FAILURE;
+                else
+                    rc = sendPacket(len, timer);
+                if (rc == FAILURE)
+                    goto exit; // there was a problem
+            }
+            break;
+#endif
+        }
+#if MQTTCLIENT_QOS2
+        case PUBREC:
+        case PUBREL:
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                rc = FAILURE;
+            else if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE,
+						         (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)
+                rc = FAILURE;
+            else if ((rc = sendPacket(len, timer)) != SUCCESS) // send the PUBREL packet
+                rc = FAILURE; // there was a problem
+            if (rc == FAILURE)
+                goto exit; // there was a problem
+            if (packet_type == PUBREL)
+                freeQoS2msgid(mypacketid);
+            break;
+
+        case PUBCOMP:
+            break;
+#endif
+        case PINGRESP:
+            ping_outstanding = false;
+            break;
+    }
+
+    if (keepalive() != SUCCESS)
+        //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT
+        rc = FAILURE;
+
+exit:
+    if (rc == SUCCESS)
+        rc = packet_type;
+    else if (isconnected)
+        closeSession();
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::keepalive()
+{
+    int rc = SUCCESS;
+
+    if (keepAliveInterval == 0)
+        goto exit;
+
+    if (last_sent.expired() || last_received.expired())
+    {
+        if (ping_outstanding)
+        {
+            rc = FAILURE; // session failure
+            #if defined(MQTT_DEBUG)
+                char printbuf[150];
+                DEBUG("PINGRESP not received in keepalive interval\n");
+            #endif
+        }
+        else
+        {
+            Timer timer(1000);
+            int len = MQTTSerialize_pingreq(sendbuf, MAX_MQTT_PACKET_SIZE);
+            if (len > 0 && (rc = sendPacket(len, timer)) == SUCCESS) // send the ping packet
+                ping_outstanding = true;
+        }
+    }
+
+exit:
+    return rc;
+}
+
+
+// only used in single-threaded mode where one command at a time is in process
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::waitfor(int packet_type, Timer& timer)
+{
+    int rc = FAILURE;
+
+    do
+    {
+        if (timer.expired())
+            break; // we timed out
+        rc = cycle(timer);
+    }
+    while (rc != packet_type && rc >= 0);
+
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options, connackData& data)
+{
+    Timer connect_timer(command_timeout_ms);
+    int rc = FAILURE;
+    int len = 0;
+
+    if (isconnected) // don't send connect packet again if we are already connected
+        goto exit;
+
+    this->keepAliveInterval = options.keepAliveInterval;
+    this->cleansession = options.cleansession;
+    if ((len = MQTTSerialize_connect(sendbuf, MAX_MQTT_PACKET_SIZE, &options)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(len, connect_timer)) != SUCCESS)  // send the connect packet
+        goto exit; // there was a problem
+
+    if (this->keepAliveInterval > 0)
+        last_received.countdown(this->keepAliveInterval);
+    // this will be a blocking call, wait for the connack
+    if (waitfor(CONNACK, connect_timer) == CONNACK)
+    {
+        data.rc = 0;
+        data.sessionPresent = false;
+        if (MQTTDeserialize_connack((unsigned char*)&data.sessionPresent,
+                            (unsigned char*)&data.rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+            rc = data.rc;
+        else
+            rc = FAILURE;
+    }
+    else
+        rc = FAILURE;
+
+#if MQTTCLIENT_QOS2
+    // resend any inflight publish
+    if (inflightMsgid > 0 && inflightQoS == QOS2 && pubrel)
+    {
+        if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREL, 0, inflightMsgid)) <= 0)
+            rc = FAILURE;
+        else
+            rc = publish(len, connect_timer, inflightQoS);
+    }
+    else
+#endif
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    if (inflightMsgid > 0)
+    {
+        memcpy(sendbuf, pubbuf, MAX_MQTT_PACKET_SIZE);
+        rc = publish(inflightLen, connect_timer, inflightQoS);
+    }
+#endif
+
+exit:
+    if (rc == SUCCESS)
+    {
+        isconnected = true;
+        ping_outstanding = false;
+    }
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options)
+{
+    connackData data;
+    return connect(options, data);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect()
+{
+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
+    return connect(default_options);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::setMessageHandler(const char* topicFilter, messageHandler messageHandler)
+{
+    int rc = FAILURE;
+    int i = -1;
+
+    // first check for an existing matching slot
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (messageHandlers[i].topicFilter != 0 && strcmp(messageHandlers[i].topicFilter, topicFilter) == 0)
+        {
+            if (messageHandler == 0) // remove existing
+            {
+                messageHandlers[i].topicFilter = 0;
+                messageHandlers[i].fp.detach();
+            }
+            rc = SUCCESS; // return i when adding new subscription
+            break;
+        }
+    }
+    // if no existing, look for empty slot (unless we are removing)
+    if (messageHandler != 0) {
+        if (rc == FAILURE)
+        {
+            for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (messageHandlers[i].topicFilter == 0)
+                {
+                    rc = SUCCESS;
+                    break;
+                }
+            }
+        }
+        if (i < MAX_MESSAGE_HANDLERS)
+        {
+            messageHandlers[i].topicFilter = topicFilter;
+            messageHandlers[i].fp.attach(messageHandler);
+        }
+    }
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter,
+     enum QoS qos, messageHandler messageHandler, subackData& data)
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);
+    int len = 0;
+    MQTTString topic = {(char*)topicFilter, {0, 0}};
+
+    if (!isconnected)
+        goto exit;
+
+    len = MQTTSerialize_subscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet
+        goto exit;             // there was a problem
+
+    if (waitfor(SUBACK, timer) == SUBACK)      // wait for suback
+    {
+        int count = 0;
+        unsigned short mypacketid;
+        data.grantedQoS = 0;
+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, &data.grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+        {
+            if (data.grantedQoS != 0x80)
+                rc = setMessageHandler(topicFilter, messageHandler);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == FAILURE)
+        closeSession();
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter, enum QoS qos, messageHandler messageHandler)
+{
+    subackData data;
+    return subscribe(topicFilter, qos, messageHandler, data);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::unsubscribe(const char* topicFilter)
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);
+    MQTTString topic = {(char*)topicFilter, {0, 0}};
+    int len = 0;
+
+    if (!isconnected)
+        goto exit;
+
+    if ((len = MQTTSerialize_unsubscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(len, timer)) != SUCCESS) // send the unsubscribe packet
+        goto exit; // there was a problem
+
+    if (waitfor(UNSUBACK, timer) == UNSUBACK)
+    {
+        unsigned short mypacketid;  // should be the same as the packetid above
+        if (MQTTDeserialize_unsuback(&mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+        {
+            // remove the subscription message handler associated with this topic, if there is one
+            setMessageHandler(topicFilter, 0);
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc != SUCCESS)
+        closeSession();
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(int len, Timer& timer, enum QoS qos)
+{
+    int rc;
+
+    if ((rc = sendPacket(len, timer)) != SUCCESS) // send the publish packet
+        goto exit; // there was a problem
+
+#if MQTTCLIENT_QOS1
+    if (qos == QOS1)
+    {
+        if (waitfor(PUBACK, timer) == PUBACK)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                rc = FAILURE;
+            else if (inflightMsgid == mypacketid)
+                inflightMsgid = 0;
+        }
+        else
+            rc = FAILURE;
+    }
+#endif
+#if MQTTCLIENT_QOS2
+    else if (qos == QOS2)
+    {
+        if (waitfor(PUBCOMP, timer) == PUBCOMP)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                rc = FAILURE;
+            else if (inflightMsgid == mypacketid)
+                inflightMsgid = 0;
+        }
+        else
+            rc = FAILURE;
+    }
+#endif
+
+exit:
+    if (rc != SUCCESS)
+        closeSession();
+    return rc;
+}
+
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos, bool retained)
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);
+    MQTTString topicString = MQTTString_initializer;
+    int len = 0;
+
+    if (!isconnected)
+        goto exit;
+
+    topicString.cstring = (char*)topicName;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    if (qos == QOS1 || qos == QOS2)
+        id = packetid.getNext();
+#endif
+
+    len = MQTTSerialize_publish(sendbuf, MAX_MQTT_PACKET_SIZE, 0, qos, retained, id,
+              topicString, (unsigned char*)payload, payloadlen);
+    if (len <= 0)
+        goto exit;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    if (!cleansession)
+    {
+        memcpy(pubbuf, sendbuf, len);
+        inflightMsgid = id;
+        inflightLen = len;
+        inflightQoS = qos;
+#if MQTTCLIENT_QOS2
+        pubrel = false;
+#endif
+    }
+#endif
+
+    rc = publish(len, timer, qos);
+exit:
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos, bool retained)
+{
+    unsigned short id = 0;  // dummy - not used for anything
+    return publish(topicName, payload, payloadlen, id, qos, retained);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, Message& message)
+{
+    return publish(topicName, message.payload, message.payloadlen, message.qos, message.retained);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::disconnect()
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);     // we might wait for incomplete incoming publishes to complete
+    int len = MQTTSerialize_disconnect(sendbuf, MAX_MQTT_PACKET_SIZE);
+    if (len > 0)
+        rc = sendPacket(len, timer);            // send the disconnect packet
+    closeSession();
+    return rc;
+}
+
+#endif

+ 55 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/MQTTLogging.h

@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTT_LOGGING_H)
+#define MQTT_LOGGING_H
+
+#define STREAM      stdout
+#if !defined(DEBUG)
+#define DEBUG(...)    \
+    {\
+    fprintf(STREAM, "DEBUG:   %s L#%d ", __PRETTY_FUNCTION__, __LINE__);  \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    }
+#endif
+#if !defined(LOG)
+#define LOG(...)    \
+    {\
+    fprintf(STREAM, "LOG:   %s L#%d ", __PRETTY_FUNCTION__, __LINE__);  \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    }
+#endif
+#if !defined(WARN)
+#define WARN(...)   \
+    { \
+    fprintf(STREAM, "WARN:  %s L#%d ", __PRETTY_FUNCTION__, __LINE__);  \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    }
+#endif 
+#if !defined(ERROR)
+#define ERROR(...)  \
+    { \
+    fprintf(STREAM, "ERROR: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    exit(1); \
+    }
+#endif
+
+#endif

+ 57 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/arduino/Countdown.h

@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(COUNTDOWN_H)
+#define COUNTDOWN_H
+
+class Countdown
+{
+public:
+    Countdown()
+    {  
+		interval_end_ms = 0L;
+    }
+    
+    Countdown(int ms)
+    {
+        countdown_ms(ms);   
+    }
+    
+    bool expired()
+    {
+        return (interval_end_ms > 0L) && (millis() >= interval_end_ms);
+    }
+    
+    void countdown_ms(unsigned long ms)  
+    {
+        interval_end_ms = millis() + ms;
+    }
+    
+    void countdown(int seconds)
+    {
+        countdown_ms((unsigned long)seconds * 1000L);
+    }
+    
+    int left_ms()
+    {
+        return interval_end_ms - millis();
+    }
+    
+private:
+    unsigned long interval_end_ms; 
+};
+
+#endif

+ 79 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/arduino/IPStack.h

@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Benjamin Cabe - generic IPStack
+ *******************************************************************************/
+
+#if !defined(IPSTACK_H)
+#define IPSTACK_H
+
+#ifndef WiFi_h
+  #include <SPI.h>
+#endif
+
+#include <Client.h>
+
+class IPStack
+{
+public:
+    IPStack(Client& client) : client(&client)
+    {
+
+    }
+
+    int connect(char* hostname, int port)
+    {
+        return client->connect(hostname, port);
+    }
+
+    int connect(uint32_t hostname, int port)
+    {
+        return client->connect(hostname, port);
+    }
+
+    int read(unsigned char* buffer, int len, int timeout)
+    {
+        int interval = 10;  // all times are in milliseconds
+		int total = 0, rc = -1;
+
+		if (timeout < 30)
+			interval = 2;
+		while (client->available() < len && total < timeout)
+		{
+			delay(interval);
+			total += interval;
+		}
+		if (client->available() >= len)
+			rc = client->readBytes((char*)buffer, len);
+		return rc;
+    }
+
+    int write(unsigned char* buffer, int len, int timeout)
+    {
+        client->setTimeout(timeout);
+		return client->write((uint8_t*)buffer, len);
+    }
+
+    int disconnect()
+    {
+        client->stop();
+        return 0;
+    }
+
+private:
+
+    Client* client;
+};
+
+#endif

+ 69 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/arduino/WifiIPStack.h

@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef ARDUINOWIFIIPSTACK_H
+#define ARDUINOWIFIIPSTACK_H
+
+#include <WiFi.h>
+
+class WifiIPStack 
+{
+public:    
+    WifiIPStack()
+    {
+        //WiFi.begin();              // Use DHCP
+        iface.setTimeout(1000);    // 1 second Timeout 
+    }
+    
+    int connect(char* hostname, int port)
+    {
+        return iface.connect(hostname, port);
+    }
+
+    int connect(uint32_t hostname, int port)
+    {
+        return iface.connect(hostname, port);
+    }
+
+    int read(char* buffer, int len, int timeout)
+    {
+        iface.setTimeout(timeout);
+        while(!iface.available());
+        return iface.readBytes(buffer, len);
+    }
+    
+    int write(char* buffer, int len, int timeout)
+    {
+        iface.setTimeout(timeout);  
+        return iface.write((uint8_t*)buffer, len);
+    }
+    
+    int disconnect()
+    {
+        iface.stop();
+        return 0;
+    }
+    
+private:
+
+    WiFiClient iface;
+    
+};
+
+#endif
+
+
+

+ 213 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/linux/linux.cpp

@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - ensure read returns if no bytes read
+ *******************************************************************************/
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+
+class IPStack
+{
+public:
+  IPStack()
+  {
+
+  }
+
+  int connect(const char* hostname, int port)
+  {
+		int type = SOCK_STREAM;
+		struct sockaddr_in address;
+		int rc = -1;
+		sa_family_t family = AF_INET;
+		struct addrinfo *result = NULL;
+		struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};
+
+		if ((rc = getaddrinfo(hostname, NULL, &hints, &result)) == 0)
+		{
+			struct addrinfo* res = result;
+
+			/* prefer ip4 addresses */
+			while (res)
+			{
+				if (res->ai_family == AF_INET)
+				{
+					result = res;
+					break;
+				}
+				res = res->ai_next;
+			}
+
+			if (result->ai_family == AF_INET)
+			{
+				address.sin_port = htons(port);
+				address.sin_family = family = AF_INET;
+				address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
+			}
+			else
+				rc = -1;
+
+			freeaddrinfo(result);
+		}
+
+		if (rc == 0)
+		{
+			mysock = socket(family, type, 0);
+			if (mysock != -1)
+			{
+				int opt = 1;
+
+				//if (setsockopt(mysock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0)
+				//	printf("Could not set SO_NOSIGPIPE for socket %d", mysock);
+
+				rc = ::connect(mysock, (struct sockaddr*)&address, sizeof(address));
+			}
+		}
+
+        return rc;
+    }
+
+  // return -1 on error, or the number of bytes read
+  // which could be 0 on a read timeout
+  int read(unsigned char* buffer, int len, int timeout_ms)
+  {
+		struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};
+		if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0))
+		{
+			interval.tv_sec = 0;
+			interval.tv_usec = 100;
+		}
+
+		setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval));
+
+		int bytes = 0;
+    int i = 0; const int max_tries = 10;
+		while (bytes < len)
+		{
+			int rc = ::recv(mysock, &buffer[bytes], (size_t)(len - bytes), 0);
+			if (rc == -1)
+			{
+        if (errno != EAGAIN && errno != EWOULDBLOCK)
+          bytes = -1;
+        break;
+			}
+			else
+				bytes += rc;
+      if (++i >= max_tries)
+        break;
+      if (rc == 0)
+        break;
+		}
+		return bytes;
+  }
+
+  int write(unsigned char* buffer, int len, int timeout)
+  {
+		struct timeval tv;
+
+		tv.tv_sec = 0;  /* 30 Secs Timeout */
+		tv.tv_usec = timeout * 1000;  // Not init'ing this can cause strange errors
+
+		setsockopt(mysock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval));
+		int	rc = ::write(mysock, buffer, len);
+		//printf("write rc %d\n", rc);
+		return rc;
+  }
+
+	int disconnect()
+	{
+		return ::close(mysock);
+	}
+
+private:
+
+    int mysock;
+};
+
+
+class Countdown
+{
+public:
+  Countdown()
+  {
+
+  }
+
+  Countdown(int ms)
+  {
+		countdown_ms(ms);
+  }
+
+
+  bool expired()
+  {
+		struct timeval now, res;
+		gettimeofday(&now, NULL);
+		timersub(&end_time, &now, &res);
+		//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);
+		//if (res.tv_sec > 0 || res.tv_usec > 0)
+		//	printf("expired %d %d\n", res.tv_sec, res.tv_usec);
+        return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0);
+  }
+
+
+  void countdown_ms(int ms)
+  {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		struct timeval interval = {ms / 1000, (ms % 1000) * 1000};
+		//printf("interval %d %d\n", interval.tv_sec, interval.tv_usec);
+		timeradd(&now, &interval, &end_time);
+  }
+
+
+  void countdown(int seconds)
+  {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		struct timeval interval = {seconds, 0};
+		timeradd(&now, &interval, &end_time);
+  }
+
+
+  int left_ms()
+  {
+		struct timeval now, res;
+		gettimeofday(&now, NULL);
+		timersub(&end_time, &now, &res);
+		//printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000);
+        return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000;
+  }
+
+private:
+
+	struct timeval end_time;
+};

+ 40 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/mbed/MQTTEthernet.h

@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTTETHERNET_H)
+#define MQTTETHERNET_H
+
+#include "MQTT_mbed.h"
+#include "EthernetInterface.h"
+#include "MQTTSocket.h"
+
+class MQTTEthernet : public MQTTSocket
+{
+public:    
+    MQTTEthernet()
+    {
+        eth.init();                          // Use DHCP
+        eth.connect();
+    }
+    
+private:
+
+    EthernetInterface eth;
+    
+};
+
+
+#endif

+ 57 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/src/mbed/MQTTSocket.h

@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTTSOCKET_H)
+#define MQTTSOCKET_H
+
+#include "MQTT_mbed.h"
+#include "TCPSocketConnection.h"
+
+class MQTTSocket
+{
+public:    
+    int connect(char* hostname, int port, int timeout=1000)
+    {
+        mysock.set_blocking(false, timeout);    // 1 second Timeout 
+        return mysock.connect(hostname, port);
+    }
+
+    int read(unsigned char* buffer, int len, int timeout)
+    {
+        mysock.set_blocking(false, timeout);  
+        return mysock.receive((char*)buffer, len);
+    }
+    
+    int write(unsigned char* buffer, int len, int timeout)
+    {
+        mysock.set_blocking(false, timeout);  
+        return mysock.send((char*)buffer, len);
+    }
+    
+    int disconnect()
+    {
+        return mysock.close();
+    }
+    
+private:
+
+    TCPSocketConnection mysock; 
+    
+};
+
+
+
+#endif

+ 20 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/test/CMakeLists.txt

@@ -0,0 +1,20 @@
+PROJECT(mqttcpp-tests)
+
+SET(MQTT_TEST_BROKER_HOST "localhost" CACHE STRING "Hostname of a test MQTT broker to use")
+SET(MQTT_TEST_PROXY_PORT "1884" CACHE STRING "Port of the test proxy to use")
+SET(MQTT_SSL_HOSTNAME "localhost" CACHE STRING "Hostname of a test SSL MQTT broker to use")
+SET(CERTDIR $ENV{TRAVIS_BUILD_DIR}/test/ssl)
+
+ADD_EXECUTABLE(
+	testcpp1
+	test1.cpp
+)
+
+target_compile_definitions(testcpp1 PRIVATE MQTTCLIENT_QOS1=1 MQTTCLIENT_QOS2=1)
+target_include_directories(testcpp1 PRIVATE "../src" "../src/linux")
+target_link_libraries(testcpp1 MQTTPacketClient  MQTTPacketServer)
+
+ADD_TEST(
+	NAME testcpp1
+	COMMAND "testcpp1" "--host" ${MQTT_TEST_BROKER_HOST}
+)

+ 943 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTClient/test/test1.cpp

@@ -0,0 +1,943 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial implementation for embedded C client
+ *******************************************************************************/
+
+
+/**
+ * @file
+ * Tests for the Paho embedded C "high" level client
+ */
+
+ #include <stdio.h>
+ #include <string.h>
+ #include <memory.h>
+ //#define MQTT_DEBUG
+ #include "MQTTClient.h"
+
+ #define DEFAULT_STACK_SIZE -1
+
+ #include "linux.cpp"
+
+ #include <sys/time.h>
+ #include <stdlib.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+void usage(void)
+{
+	printf("help!!\n");
+	exit(EXIT_FAILURE);
+}
+
+struct Options
+{
+	char* host;         /**< connection to system under test. */
+  int port;
+	char* proxy_host;
+  int proxy_port;
+	int verbose;
+	int test_no;
+	int MQTTVersion;
+	int iterations;
+} options =
+{
+	(char*)"localhost",
+  1883,
+	(char*)"localhost",
+  1885,
+	0,
+	0,
+	4,
+	1,
+};
+
+void getopts(int argc, char** argv)
+{
+	int count = 1;
+
+	while (count < argc)
+	{
+		if (strcmp(argv[count], "--test_no") == 0)
+		{
+			if (++count < argc)
+				options.test_no = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--host") == 0)
+		{
+			if (++count < argc)
+			{
+				options.host = argv[count];
+				printf("\nSetting host to %s\n", options.host);
+			}
+			else
+				usage();
+		}
+    else if (strcmp(argv[count], "--port") == 0)
+    {
+      if (++count < argc)
+      {
+        options.port = atoi(argv[count]);
+        printf("\nSetting port to %d\n", options.port);
+      }
+      else
+        usage();
+    }
+		else if (strcmp(argv[count], "--proxy_host") == 0)
+		{
+			if (++count < argc)
+				options.proxy_host = argv[count];
+			else
+				usage();
+		}
+    else if (strcmp(argv[count], "--proxy_port") == 0)
+    {
+      if (++count < argc)
+      {
+        options.proxy_port = atoi(argv[count]);
+        printf("\nSetting proxy port to %d\n", options.proxy_port);
+      }
+      else
+        usage();
+    }
+		else if (strcmp(argv[count], "--MQTTversion") == 0)
+		{
+			if (++count < argc)
+			{
+				options.MQTTVersion = atoi(argv[count]);
+				printf("setting MQTT version to %d\n", options.MQTTVersion);
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--iterations") == 0)
+		{
+			if (++count < argc)
+				options.iterations = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--verbose") == 0)
+		{
+			options.verbose = 1;
+			printf("\nSetting verbose on\n");
+		}
+		count++;
+	}
+}
+
+
+#define LOGA_DEBUG 0
+#define LOGA_INFO 1
+#include <stdarg.h>
+#include <time.h>
+#include <sys/timeb.h>
+void MyLog(int LOGA_level, const char* format, ...)
+{
+	static char msg_buf[256];
+	va_list args;
+	struct timeb ts;
+
+	struct tm *timeinfo;
+
+	if (LOGA_level == LOGA_DEBUG && options.verbose == 0)
+	  return;
+
+	ftime(&ts);
+	timeinfo = localtime(&ts.time);
+	strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo);
+
+	sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm);
+
+	va_start(args, format);
+	vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), format, args);
+	va_end(args);
+
+	printf("%s\n", msg_buf);
+	fflush(stdout);
+}
+
+
+#if defined(WIN32) || defined(_WINDOWS)
+#define mqsleep(A) Sleep(1000*A)
+#define START_TIME_TYPE DWORD
+static DWORD start_time = 0;
+START_TIME_TYPE start_clock(void)
+{
+	return GetTickCount();
+}
+#elif defined(AIX)
+#define mqsleep sleep
+#define START_TIME_TYPE struct timespec
+START_TIME_TYPE start_clock(void)
+{
+	static struct timespec start;
+	clock_gettime(CLOCK_REALTIME, &start);
+	return start;
+}
+#else
+#define mqsleep sleep
+#define START_TIME_TYPE struct timeval
+/* TODO - unused - remove? static struct timeval start_time; */
+START_TIME_TYPE start_clock(void)
+{
+	struct timeval start_time;
+	gettimeofday(&start_time, NULL);
+	return start_time;
+}
+#endif
+
+
+#if defined(WIN32)
+long elapsed(START_TIME_TYPE start_time)
+{
+	return GetTickCount() - start_time;
+}
+#elif defined(AIX)
+#define assert(a)
+long elapsed(struct timespec start)
+{
+	struct timespec now, res;
+
+	clock_gettime(CLOCK_REALTIME, &now);
+	ntimersub(now, start, res);
+	return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
+}
+#else
+long elapsed(START_TIME_TYPE start_time)
+{
+	struct timeval now, res;
+
+	gettimeofday(&now, NULL);
+	timersub(&now, &start_time, &res);
+	return (res.tv_sec)*1000 + (res.tv_usec)/1000;
+}
+#endif
+
+
+#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
+#define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
+
+int tests = 0;
+int failures = 0;
+FILE* xml;
+START_TIME_TYPE global_start_time;
+char output[3000];
+char* cur_output = output;
+
+
+void write_test_result(void)
+{
+	long duration = elapsed(global_start_time);
+
+	fprintf(xml, " time=\"%ld.%.3ld\" >\n", duration / 1000, duration % 1000);
+	if (cur_output != output)
+	{
+		fprintf(xml, "%s", output);
+		cur_output = output;
+	}
+	fprintf(xml, "</testcase>\n");
+}
+
+
+void myassert(const char* filename, int lineno, const char* description, int value, const char* format, ...)
+{
+	++tests;
+	if (!value)
+	{
+		va_list args;
+
+		++failures;
+		MyLog(LOGA_INFO, (char*)"Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
+
+		va_start(args, format);
+		vprintf(format, args);
+		va_end(args);
+
+		cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
+                        description, filename, lineno);
+	}
+	else
+		MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", filename, lineno, description);
+}
+
+
+static volatile MQTT::MessageData* test1_message_data = NULL;
+static MQTT::Message pubmsg;
+
+void messageArrived(MQTT::MessageData& md)
+{
+    test1_message_data = &md;
+	  MQTT::Message &m = md.message;
+
+    assert("Good message lengths", pubmsg.payloadlen == m.payloadlen,
+         "payloadlen was %d", m.payloadlen);
+
+    if (pubmsg.payloadlen == m.payloadlen)
+        assert("Good message contents", memcmp(m.payload, pubmsg.payload, m.payloadlen) == 0,
+          "payload was %s", m.payload);
+}
+
+
+/*********************************************************************
+
+Test1: single-threaded client
+
+*********************************************************************/
+void test1_sendAndReceive(MQTT::Client<IPStack, Countdown, 1000>& client, int qos, const char* test_topic)
+{
+	char* topicName = NULL;
+	int topicLen;
+	int i = 0;
+	int iterations = 50;
+	int rc;
+  int wait_seconds;
+
+	MyLog(LOGA_DEBUG, "%d messages at QoS %d", iterations, qos);
+  memset(&pubmsg, '\0', sizeof(pubmsg));
+	pubmsg.payload = (void*)"a much longer message that we can shorten to the extent that we need to payload up to 11";
+	pubmsg.payloadlen = 11;
+	pubmsg.qos = (MQTT::QoS)qos;
+	pubmsg.retained = false;
+  pubmsg.dup = false;
+
+	for (i = 0; i < iterations; ++i)
+	{
+    test1_message_data = NULL;
+		rc = client.publish(test_topic, pubmsg);
+		assert("Good rc from publish", rc == MQTT::SUCCESS, "rc was %d", rc);
+
+    /* wait for the message to be received */
+    wait_seconds = 10;
+		while ((test1_message_data == NULL) && (wait_seconds-- > 0))
+		{
+      client.yield(100);
+		}
+		assert("Message Arrived", wait_seconds > 0, "Time out waiting for message %d\n", i);
+
+		if (!test1_message_data)
+			printf("No message received within timeout period\n");
+	}
+
+	/* wait to receive any outstanding messages */
+  wait_seconds = 2;
+  while (wait_seconds-- > 0)
+  {
+      client.yield(1000);
+  }
+}
+
+
+int test1(struct Options options)
+{
+	MQTT::QoS subsqos = MQTT::QOS2;
+	int rc = 0;
+	const char* test_topic = "C client test1";
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"single threaded client using receive\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 1 - single threaded client using receive");
+
+  IPStack ipstack = IPStack();
+	MQTT::Client<IPStack, Countdown, 1000> client = MQTT::Client<IPStack, Countdown, 1000>(ipstack);
+
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+  data.willFlag = 1;
+  data.MQTTVersion = options.MQTTVersion;
+  data.clientID.cstring = (char*)"single-threaded-test";
+  data.username.cstring = (char*)"testuser";
+  data.password.cstring = (char*)"testpassword";
+
+  data.keepAliveInterval = 20;
+  data.cleansession = 1;
+
+	data.will.message.cstring = (char*)"will message";
+	data.will.qos = 1;
+	data.will.retained = 0;
+	data.will.topicName.cstring = (char*)"will topic";
+
+	MyLog(LOGA_DEBUG, "Connecting");
+  rc = ipstack.connect(options.host, options.port);
+  assert("Good rc from TCP connect", rc == MQTT::SUCCESS, "rc was %d", rc);
+  if (rc != MQTT::SUCCESS)
+    goto exit;
+
+  rc = client.connect(data);
+	assert("Good rc from connect", rc == MQTT::SUCCESS, "rc was %d", rc);
+	if (rc != MQTT::SUCCESS)
+		goto exit;
+
+	rc = client.subscribe(test_topic, subsqos, messageArrived);
+	assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+
+	test1_sendAndReceive(client, 0, test_topic);
+	test1_sendAndReceive(client, 1, test_topic);
+	test1_sendAndReceive(client, 2, test_topic);
+
+	MyLog(LOGA_DEBUG, "Stopping\n");
+
+	rc = client.unsubscribe(test_topic);
+	assert("Unsubscribe successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+	rc = client.disconnect();
+	assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+	/* Just to make sure we can connect again */
+  rc = ipstack.connect(options.host, options.port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data);
+	assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+	rc = client.disconnect();
+	assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+exit:
+	MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+/*********************************************************************
+
+Test 2: connack return data
+
+*********************************************************************/
+int test2(struct Options options)
+{
+  MQTT::QoS subsqos = MQTT::QOS2;
+	int rc;
+  const char* test_topic = "C client test2";
+
+  fprintf(xml, "<testcase classname=\"test2\" name=\"connack return data\"");
+  global_start_time = start_clock();
+  failures = 0;
+  MyLog(LOGA_INFO, "Starting test 2 - connack return data");
+
+  IPStack ipstack = IPStack();
+  MQTT::Client<IPStack, Countdown, 1000> client = MQTT::Client<IPStack, Countdown, 1000>(ipstack);
+
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+  data.willFlag = 1;
+  data.MQTTVersion = options.MQTTVersion;
+  data.clientID.cstring = (char*)"connack-return-data";
+  data.username.cstring = (char*)"testuser";
+  data.password.cstring = (char*)"testpassword";
+
+  data.keepAliveInterval = 20;
+  data.cleansession = 1;
+
+  data.will.message.cstring = (char*)"will message";
+  data.will.qos = 1;
+  data.will.retained = 0;
+  data.will.topicName.cstring = (char*)"will topic";
+
+  MyLog(LOGA_DEBUG, "Connecting");
+  rc = ipstack.connect(options.host, options.port);
+  assert("Good rc from TCP connect", rc == MQTT::SUCCESS, "rc was %d", rc);
+  if (rc != MQTT::SUCCESS)
+    goto exit;
+
+  MQTT::connackData connack;
+  rc = client.connect(data, connack);
+  assert("Good rc from connect", rc == MQTT::SUCCESS, "rc was %d", rc);
+  if (rc != MQTT::SUCCESS)
+    goto exit;
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+         "sessionPresent was %d", connack.sessionPresent);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = ipstack.connect(options.host, options.port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  MQTT::subackData suback;
+  rc = client.subscribe(test_topic, subsqos, messageArrived, suback);
+  assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == MQTT::QOS2,
+         "rc was %d", suback.grantedQoS);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = ipstack.connect(options.host, options.port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 1", connack.sessionPresent == 1,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+  /* reconnect with cleansession true */
+  data.cleansession = 1;
+  rc = ipstack.connect(options.host, options.port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+exit:
+  MyLog(LOGA_INFO, "TEST2: test %s. %d tests run, %d failures.",
+      (failures == 0) ? "passed" : "failed", tests, failures);
+  write_test_result();
+  return failures;
+}
+
+
+/*********************************************************************
+
+Test 3: client session state
+
+*********************************************************************/
+static volatile MQTT::MessageData* test2_message_data = NULL;
+
+void messageArrived2(MQTT::MessageData& md)
+{
+    test2_message_data = &md;
+	  MQTT::Message &m = md.message;
+
+    assert("Good message lengths", pubmsg.payloadlen == m.payloadlen,
+         "payloadlen was %d", m.payloadlen);
+
+    if (pubmsg.payloadlen == m.payloadlen)
+        assert("Good message contents", memcmp(m.payload, pubmsg.payload, m.payloadlen) == 0,
+          "payload was %s", m.payload);
+}
+
+
+int check_subs_exist(MQTT::Client<IPStack, Countdown, 1000>& client, const char* test_topic, int which)
+{
+    int rc = MQTT::FAILURE;
+    int wait_seconds = 0;
+
+    memset(&pubmsg, '\0', sizeof(pubmsg));
+    pubmsg.payload = (void*)"a much longer message that we can shorten to the extent that we need to payload up to 11";
+    pubmsg.payloadlen = 11;
+    pubmsg.qos = MQTT::QOS2;
+    pubmsg.retained = false;
+    pubmsg.dup = false;
+
+    test1_message_data = test2_message_data = NULL;
+    rc = client.publish(test_topic, pubmsg);
+    assert("Good rc from publish", rc == MQTT::SUCCESS, "rc was %d", rc);
+
+    /* wait for the message to be received */
+    wait_seconds = 10;
+    while (wait_seconds-- > 0)
+    {
+        client.yield(100);
+    }
+
+    rc = (((which == 1 || which == 3) && test1_message_data) ||
+         (which == 2 && test1_message_data == NULL)) ? MQTT::SUCCESS : MQTT::FAILURE;
+    assert("test1 subscription", rc == MQTT::SUCCESS, "test1_message_data %p\n",
+            test1_message_data);
+    rc = (((which == 2 || which == 3) && test2_message_data) ||
+         (which == 1 && test2_message_data == NULL)) ? MQTT::SUCCESS : MQTT::FAILURE;
+    assert("test2 subscription", rc == MQTT::SUCCESS, "test2_message_data %p\n",
+             test2_message_data);
+    return rc;
+}
+
+
+int test3(struct Options options)
+{
+  MQTT::QoS subsqos = MQTT::QOS2;
+	int rc;
+  const char* test_topic = "C client test3";
+  int wait_seconds = 0;
+
+  fprintf(xml, "<testcase classname=\"test3\" name=\"session state\"");
+  global_start_time = start_clock();
+  failures = 0;
+  MyLog(LOGA_INFO, "Starting test 3 - session state");
+
+  IPStack ipstack = IPStack();
+  MQTT::Client<IPStack, Countdown, 1000> client = MQTT::Client<IPStack, Countdown, 1000>(ipstack);
+
+  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+  data.willFlag = 1;
+  data.MQTTVersion = options.MQTTVersion;
+  data.clientID.cstring = (char*)"connack-return-data";
+  data.username.cstring = (char*)"testuser";
+  data.password.cstring = (char*)"testpassword";
+
+  data.keepAliveInterval = 10;
+  data.cleansession = 1;
+
+  data.will.message.cstring = (char*)"will message";
+  data.will.qos = 1;
+  data.will.retained = 0;
+  data.will.topicName.cstring = (char*)"will topic";
+
+  assert("Good rc in connack", client.isConnected() == false,
+         "isconnected was %d", client.isConnected());
+
+  MyLog(LOGA_DEBUG, "Connecting");
+  rc = ipstack.connect(options.host, options.port);
+  assert("Good rc from TCP connect", rc == MQTT::SUCCESS, "rc was %d", rc);
+  if (rc != MQTT::SUCCESS)
+    goto exit;
+
+  MQTT::connackData connack;
+  rc = client.connect(data, connack);
+  assert("Good rc from connect", rc == MQTT::SUCCESS, "rc was %d", rc);
+  if (rc != MQTT::SUCCESS)
+    goto exit;
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+         "sessionPresent was %d", connack.sessionPresent);
+
+  assert("Good rc in connack", client.isConnected() == true,
+                "isconnected was %d", client.isConnected());
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = ipstack.connect(options.proxy_host, options.proxy_port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  MQTT::subackData suback;
+  rc = client.subscribe(test_topic, subsqos, messageArrived, suback);
+  assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == MQTT::QOS2,
+         "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(client, test_topic, 1);
+
+  rc = client.subscribe(test_topic, subsqos, messageArrived2, suback);
+  assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == MQTT::QOS2,
+                  "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(client, test_topic, 2);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = ipstack.connect(options.proxy_host, options.proxy_port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 1", connack.sessionPresent == 1,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  check_subs_exist(client, test_topic, 2);
+
+  rc = client.subscribe(test_topic, subsqos, messageArrived, suback);
+  assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == MQTT::QOS2,
+            "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(client, test_topic, 1);
+
+  // cause a connection FAILURE
+  memset(&pubmsg, '\0', sizeof(pubmsg));
+  pubmsg.payload = (void*)"TERMINATE";
+  pubmsg.payloadlen = strlen((char*)pubmsg.payload);
+  pubmsg.qos = MQTT::QOS0;
+  pubmsg.retained = false;
+  pubmsg.dup = false;
+  rc = client.publish("MQTTSAS topic", pubmsg);
+  assert("Good rc from publish", rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  // wait for failure to be noticed by keepalive
+  wait_seconds = 20;
+  while (client.isConnected() && (wait_seconds-- > 0))
+  {
+      client.yield(1000);
+  }
+  assert("Disconnected", !client.isConnected(), "isConnected was %d",
+         client.isConnected());
+  ipstack.disconnect();
+
+  /* reconnect with cleansession false */
+  data.cleansession = 0;
+  rc = ipstack.connect(options.host, options.port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 1", connack.sessionPresent == 1,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  check_subs_exist(client, test_topic, 1);
+
+  rc = client.subscribe(test_topic, subsqos, messageArrived2, suback);
+  assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == MQTT::QOS2,
+                  "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(client, test_topic, 2);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+  /* reconnect with cleansession true to clean up both server and client state */
+  data.cleansession = 1;
+  rc = ipstack.connect(options.host, options.port);
+  assert("TCP connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+  rc = client.connect(data, connack);
+  assert("Connect successful",  rc == MQTT::SUCCESS, "rc was %d", rc);
+
+  assert("Good rc in connack", connack.rc == 0, "rc was %d", connack.rc);
+  assert("Session present is 0", connack.sessionPresent == 0,
+           "sessionPresent was %d", connack.sessionPresent);
+
+  rc = client.subscribe(test_topic, subsqos, messageArrived2, suback);
+  assert("Good rc from subscribe", rc == MQTT::SUCCESS, "rc was %d", rc);
+  assert("Granted QoS rc from subscribe", suback.grantedQoS == MQTT::QOS2,
+                  "rc was %d", suback.grantedQoS);
+
+  check_subs_exist(client, test_topic, 2);
+
+  rc = client.disconnect();
+  assert("Disconnect successful", rc == MQTT::SUCCESS, "rc was %d", rc);
+  ipstack.disconnect();
+
+exit:
+  MyLog(LOGA_INFO, "TEST2: test %s. %d tests run, %d failures.",
+      (failures == 0) ? "passed" : "failed", tests, failures);
+  write_test_result();
+  return failures;
+}
+
+
+#if 0
+/*********************************************************************
+
+Test 4: connectionLost and will message
+
+*********************************************************************/
+MQTTClient test6_c1, test6_c2;
+volatile int test6_will_message_arrived = 0;
+volatile int test6_connection_lost_called = 0;
+
+void test6_connectionLost(void* context, char* cause)
+{
+	MQTTClient c = (MQTTClient)context;
+	printf("%s -> Callback: connection lost\n", (c == test6_c1) ? "Client-1" : "Client-2");
+	test6_connection_lost_called = 1;
+}
+
+void test6_deliveryComplete(void* context, MQTTClient_deliveryToken token)
+{
+	printf("Client-2 -> Callback: publish complete for token %d\n", token);
+}
+
+char* test6_will_topic = "C Test 2: will topic";
+char* test6_will_message = "will message from Client-1";
+
+int test6_messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* m)
+{
+	MQTTClient c = (MQTTClient)context;
+	printf("%s -> Callback: message received on topic '%s' is '%.*s'.\n",
+			 (c == test6_c1) ? "Client-1" : "Client-2", topicName, m->payloadlen, (char*)(m->payload));
+	if (c == test6_c2 && strcmp(topicName, test6_will_topic) == 0 && memcmp(m->payload, test6_will_message, m->payloadlen) == 0)
+		test6_will_message_arrived = 1;
+	MQTTClient_free(topicName);
+	MQTTClient_freeMessage(&m);
+	return 1;
+}
+
+
+int test6(struct Options options)
+{
+	char* testname = "test6";
+	MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
+	MQTTClient_willOptions wopts =  MQTTClient_willOptions_initializer;
+	MQTTClient_connectOptions opts2 = MQTTClient_connectOptions_initializer;
+	int rc, count;
+	char* mqttsas_topic = "MQTTSAS topic";
+
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 6 - connectionLost and will messages");
+	fprintf(xml, "<testcase classname=\"test1\" name=\"connectionLost and will messages\"");
+	global_start_time = start_clock();
+
+	opts.keepAliveInterval = 2;
+	opts.cleansession = 1;
+	opts.MQTTVersion = MQTTVERSION_3_1_1;
+	opts.will = &wopts;
+	opts.will->message = test6_will_message;
+	opts.will->qos = 1;
+	opts.will->retained = 0;
+	opts.will->topicName = test6_will_topic;
+	if (options.haconnections != NULL)
+	{
+		opts.serverURIs = options.haconnections;
+		opts.serverURIcount = options.hacount;
+	}
+
+	/* Client-1 with Will options */
+	rc = MQTTClient_create(&test6_c1, options.proxy_connection, "Client_1", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
+	assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	rc = MQTTClient_setCallbacks(test6_c1, (void*)test6_c1, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
+	assert("good rc from setCallbacks",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	/* Connect to the broker */
+	rc = MQTTClient_connect(test6_c1, &opts);
+	assert("good rc from connect",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+	if (rc != MQTTCLIENT_SUCCESS)
+		goto exit;
+
+	/* Client - 2 (multi-threaded) */
+	rc = MQTTClient_create(&test6_c2, options.connection, "Client_2", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
+	assert("good rc from create",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* Set the callback functions for the client */
+	rc = MQTTClient_setCallbacks(test6_c2, (void*)test6_c2, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
+	assert("good rc from setCallbacks",  rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* Connect to the broker */
+	opts2.keepAliveInterval = 20;
+	opts2.cleansession = 1;
+	MyLog(LOGA_INFO, "Connecting Client_2 ...");
+	rc = MQTTClient_connect(test6_c2, &opts2);
+	assert("Good rc from connect", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	rc = MQTTClient_subscribe(test6_c2, test6_will_topic, 2);
+	assert("Good rc from subscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	/* now send the command which will break the connection and cause the will message to be sent */
+	rc = MQTTClient_publish(test6_c1, mqttsas_topic, (int)strlen("TERMINATE"), "TERMINATE", 0, 0, NULL);
+	assert("Good rc from publish", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
+
+	MyLog(LOGA_INFO, "Waiting to receive the will message");
+	count = 0;
+	while (++count < 40)
+	{
+		#if defined(WIN32)
+			Sleep(1000L);
+		#else
+			sleep(1);
+		#endif
+		if (test6_will_message_arrived == 1 && test6_connection_lost_called == 1)
+			break;
+	}
+	assert("will message arrived", test6_will_message_arrived == 1,
+							"will_message_arrived was %d\n", test6_will_message_arrived);
+	assert("connection lost called", test6_connection_lost_called == 1,
+			         "connection_lost_called %d\n", test6_connection_lost_called);
+
+	rc = MQTTClient_unsubscribe(test6_c2, test6_will_topic);
+	assert("Good rc from unsubscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
+
+	rc = MQTTClient_isConnected(test6_c2);
+	assert("Client-2 still connected", rc == 1, "isconnected is %d", rc);
+
+	rc = MQTTClient_isConnected(test6_c1);
+	assert("Client-1 not connected", rc == 0, "isconnected is %d", rc);
+
+	rc = MQTTClient_disconnect(test6_c2, 100L);
+	assert("Good rc from disconnect", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
+
+	MQTTClient_destroy(&test6_c1);
+	MQTTClient_destroy(&test6_c2);
+
+exit:
+	MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.\n",
+			(failures == 0) ? "passed" : "failed", testname, tests, failures);
+	write_test_result();
+	return failures;
+}
+#endif
+
+int main(int argc, char** argv)
+{
+	int rc = 0;
+ 	int (*tests[])(Options) = {NULL, test1, test2, test3, /*test4, test5, test6, test6a*/};
+	int i;
+
+	xml = fopen("TEST-test1.xml", "w");
+	fprintf(xml, "<testsuite name=\"test1\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
+
+	//setenv("MQTT_C_CLIENT_TRACE", "ON", 1);
+	//setenv("MQTT_C_CLIENT_TRACE_LEVEL", "ERROR", 0);
+
+	getopts(argc, argv);
+
+	for (i = 0; i < options.iterations; ++i)
+	{
+	 	if (options.test_no == 0)
+		{ /* run all the tests */
+ 		   	for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no)
+				rc += tests[options.test_no](options); /* return number of failures.  0 = test succeeded */
+		}
+		else
+ 		   	rc = tests[options.test_no](options); /* run just the selected test */
+	}
+
+ 	if (rc == 0)
+		MyLog(LOGA_INFO, "verdict pass");
+	else
+		MyLog(LOGA_INFO, "verdict fail");
+
+	fprintf(xml, "</testsuite>\n");
+	fclose(xml);
+	return rc;
+}

+ 21 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/CMakeLists.txt

@@ -0,0 +1,21 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+project("paho-mqttpacket" C)
+
+ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(samples)
+ADD_SUBDIRECTORY(test)

+ 37 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/CMakeLists.txt

@@ -0,0 +1,37 @@
+#*******************************************************************************
+#  Copyright (c) 2017 IBM Corp.
+#
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  and Eclipse Distribution License v1.0 which accompany this distribution.
+#
+#  The Eclipse Public License is available at
+#     http://www.eclipse.org/legal/epl-v10.html
+#  and the Eclipse Distribution License is available at
+#    http://www.eclipse.org/org/documents/edl-v10.php.
+#
+#  Contributors:
+#     Ian Craggs - initial version
+#*******************************************************************************/
+
+# Samples
+
+include_directories(../src)
+
+add_executable(
+  pub0sub1
+  pub0sub1.c transport.c
+)
+target_link_libraries(pub0sub1 paho-embed-mqtt3c)
+
+add_executable(
+  pub0sub1_nb
+  pub0sub1_nb.c transport.c
+)
+target_link_libraries(pub0sub1_nb paho-embed-mqtt3c)
+
+add_executable(
+  qos0pub
+  qos0pub.c transport.c
+)
+target_link_libraries(qos0pub paho-embed-mqtt3c)

+ 3 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/build

@@ -0,0 +1,3 @@
+gcc -g -Wall pub0sub1_nb.c transport.c -I ../../src ../../src/MQTTConnectClient.c ../../src/MQTTSerializePublish.c ../../src/MQTTPacket.c ../../src/MQTTSubscribeClient.c -o pub0sub1_nb ../../src/MQTTDeserializePublish.c ../../src/MQTTConnectServer.c ../../src/MQTTSubscribeServer.c ../../src/MQTTUnsubscribeServer.c ../../src/MQTTUnsubscribeClient.c
+gcc -g -Wall ping_nb.c transport.c -I ../../src ../../src/MQTTConnectClient.c ../../src/MQTTPacket.c -o ping_nb
+

+ 267 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/ping_nb.c

@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Sergio R. Caprile
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+#define KEEPALIVE_INTERVAL 20
+
+/* This is to get a timebase in seconds to test the sample */
+#include <time.h>
+time_t old_t;
+void start_ping_timer(void)
+{
+	time(&old_t);
+	old_t += KEEPALIVE_INTERVAL/2 + 1;
+}
+
+int time_to_ping(void)
+{
+time_t t;
+
+	time(&t);
+	if(t >= old_t)
+	  	return 1;
+	return 0;
+}
+
+/* This is in order to get an asynchronous signal to stop the sample,
+as the code loops waiting for msgs on the subscribed topic.
+Your actual code will depend on your hw and approach, but this sample can be
+run on Linux so debugging of the non-hardware specific bare metal code is easier.
+See at bottom of file for details */
+#include <signal.h>
+
+int toStop = 0;
+
+void stop_init(void);
+/* */
+
+/* Same as above, we provide a set of functions to test/debug on a friendlier system;
+the init() and  close() actions on the serial are just for this, you will probably
+handle this on whatever handles your media in your application */
+void sampleserial_init(void);
+void sampleserial_close(void);
+int samplesend(unsigned char *address, unsigned int bytes);
+int samplerecv(unsigned char *address, unsigned int maxbytes);
+/* */
+
+/* You will use your hardware specifics here, see transport.h. */
+static transport_iofunctions_t iof = {samplesend, samplerecv};
+
+enum states { IDLE, SENDPING, GETPONG };
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	int mysock = 0;
+	unsigned char buf[200];
+	int buflen = sizeof(buf);
+	int len = 0;
+	MQTTTransport mytransport;
+	int state;
+
+	stop_init();
+	sampleserial_init();
+
+	mysock = transport_open(&iof);
+	if(mysock < 0)
+		return mysock;
+	/* You will (or already are) 'somehow' connect(ed) to host:port via your hardware specifics. E.g.:
+		you have a serial (RS-232/UART) link
+		you have a cell modem and you issue your AT+ magic
+		you have some TCP/IP which is not lwIP (nor a full-fledged socket compliant one)
+		 and you TCP connect
+	*/
+
+	mytransport.sck = &mysock;
+	mytransport.getfn = transport_getdatanb;
+	mytransport.state = 0;
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = KEEPALIVE_INTERVAL;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	len = MQTTSerialize_connect(buf, buflen, &data);
+	/* This one blocks until it finishes sending, you will probably not want this in real life,
+	in such a case replace this call by a scheme similar to the one you'll see in the main loop */
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+	printf("Sent MQTT connect\n");
+	/* wait for connack */
+	do {
+		int frc;
+		if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == CONNACK){
+			unsigned char sessionPresent, connack_rc;
+			if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0){
+				printf("Unable to connect, return code %d\n", connack_rc);
+				goto exit;
+			}
+			break;
+		}
+		else if (frc == -1)
+			goto exit;
+	} while (1); /* handle timeouts here */
+
+	printf("MQTT connected\n");
+	start_ping_timer();
+	state = IDLE;
+	while (!toStop)	{
+		switch(state){
+		case IDLE:
+			if(time_to_ping()){
+				len = MQTTSerialize_pingreq(buf, buflen);
+				transport_sendPacketBuffernb_start(mysock, buf, len);
+				state = SENDPING;
+			}
+			break;
+		case SENDPING:
+			switch(transport_sendPacketBuffernb(mysock)){
+			case TRANSPORT_DONE:
+				printf("Ping...");
+				start_ping_timer();
+				state = GETPONG;
+				break;
+			case TRANSPORT_ERROR:
+				/* handle any I/O errors here */
+				goto exit;
+				break;
+			case TRANSPORT_AGAIN:
+			default:
+				/* handle timeouts here, not probable unless there is a hardware problem */
+				break;
+			}
+			break;
+		case GETPONG:
+			if((rc=MQTTPacket_readnb(buf, buflen, &mytransport)) == PINGRESP){
+				printf("Pong\n");
+				start_ping_timer();
+				state = IDLE;
+			} else if(rc == -1){
+				/* handle I/O errors here */
+				printf("OOPS\n");
+				goto exit;
+			}	/* handle timeouts here */
+			break;
+		}
+	}
+
+	printf("disconnecting\n");
+	len = MQTTSerialize_disconnect(buf, buflen);
+	/* Same blocking related stuff here */
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+exit:
+	transport_close(mysock);
+	
+	sampleserial_close();
+	return 0;
+}
+
+
+/* To stop the sample */
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+void stop_init(void)
+{
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+}
+
+/* Serial hack:
+Simulate serial transfers on an established TCP connection
+ */
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> 
+#include <fcntl.h>
+
+static int sockfd;
+
+void sampleserial_init(void)
+{
+struct sockaddr_in serv_addr;
+
+
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	  perror(NULL);
+	  exit(2);
+	}
+	serv_addr.sin_family = AF_INET;
+	serv_addr.sin_addr.s_addr = inet_addr("198.41.30.241");
+	serv_addr.sin_port = htons(1883);
+	if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+		printf("ERROR connecting\n");
+		exit(-1);
+	}
+	printf("- TCP Connected to Eclipse\n");
+        /* set to non-blocking */
+	fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
+}
+
+void sampleserial_close(void)
+{
+	close(sockfd);
+}
+
+int samplesend(unsigned char *address, unsigned int bytes)
+{
+int len;
+
+	if(rand() > (RAND_MAX/2))	// 50% probability of being busy
+		return 0;
+	if(rand() > (RAND_MAX/2)){	// 50% probability of sending half the requested data (no room in buffer)
+		if(bytes > 1)
+			bytes /= 2;
+	}
+	if((len = write(sockfd, address, bytes)) >= 0)
+		return len;
+	if(errno == EAGAIN)
+		return 0;
+	return -1;
+}
+
+int samplerecv(unsigned char *address, unsigned int maxbytes)
+{
+int len;
+
+	if(rand() > (RAND_MAX/2))	// 50% probability of no data
+		return 0;
+	if(rand() > (RAND_MAX/2)){	// 50% probability of getting half the requested data (not arrived yet)
+		if(maxbytes > 1){
+			maxbytes /= 2;
+		}
+	}
+	if((len = read(sockfd, address, maxbytes)) >= 0)
+		return len;
+	if(errno == EAGAIN)
+		return 0;
+	return -1;
+}
+

+ 285 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/pub0sub1_nb.c

@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - port to the bare metal environment
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+/* This is in order to get an asynchronous signal to stop the sample,
+as the code loops waiting for msgs on the subscribed topic.
+Your actual code will depend on your hw and approach, but this sample can be
+run on Linux so debugging of the non-hardware specific bare metal code is easier.
+See at bottom of file for details */
+#include <signal.h>
+
+int toStop = 0;
+
+void stop_init(void);
+/* */
+
+/* Same as above, we provide a set of functions to test/debug on a friendlier system;
+the init() and  close() actions on the serial are just for this, you will probably
+handle this on whatever handles your media in your application */
+void sampleserial_init(void);
+void sampleserial_close(void);
+int samplesend(unsigned char *address, unsigned int bytes);
+int samplerecv(unsigned char *address, unsigned int maxbytes);
+/* */
+
+/* You will use your hardware specifics here, see transport.h. */
+static transport_iofunctions_t iof = {samplesend, samplerecv};
+
+enum states { READING, PUBLISHING };
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	int mysock = 0;
+	unsigned char buf[200];
+	int buflen = sizeof(buf);
+	int msgid = 1;
+	MQTTString topicString = MQTTString_initializer;
+	int req_qos = 0;
+	char* payload = "mypayload";
+	int payloadlen = strlen(payload);
+	int len = 0;
+	MQTTTransport mytransport;
+	int state = READING;
+
+	stop_init();
+	sampleserial_init();
+
+	mysock = transport_open(&iof);
+	if(mysock < 0)
+		return mysock;
+	/* You will (or already are) 'somehow' connect(ed) to host:port via your hardware specifics. E.g.:
+		you have a serial (RS-232/UART) link
+		you have a cell modem and you issue your AT+ magic
+		you have some TCP/IP which is not lwIP (nor a full-fledged socket compliant one)
+		 and you TCP connect
+	*/
+
+	mytransport.sck = &mysock;
+	mytransport.getfn = transport_getdatanb;
+	mytransport.state = 0;
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = 20;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	len = MQTTSerialize_connect(buf, buflen, &data);
+	/* This one blocks until it finishes sending, you will probably not want this in real life,
+	in such a case replace this call by a scheme similar to the one you'll see in the main loop */
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+	printf("Sent MQTT connect\n");
+	/* wait for connack */
+	do {
+		int frc;
+		if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == CONNACK){
+			unsigned char sessionPresent, connack_rc;
+			if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0){
+				printf("Unable to connect, return code %d\n", connack_rc);
+				goto exit;
+			}
+			break;
+		}
+		else if (frc == -1)
+			goto exit;
+	} while (1); /* handle timeouts here */
+
+	printf("MQTT connected\n");
+	/* subscribe */
+	topicString.cstring = "substopic";
+	len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);
+
+	/* This is equivalent to the one above, but using the non-blocking functions. You will probably not want this in real life,
+	in such a case replace this call by a scheme similar to the one you'll see in the main loop */
+	transport_sendPacketBuffernb_start(mysock, buf, len);
+	while((rc=transport_sendPacketBuffernb(mysock)) != TRANSPORT_DONE);
+	do {
+		int frc;
+		if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == SUBACK){ /* wait for suback */
+			unsigned short submsgid;
+			int subcount;
+			int granted_qos;
+
+			rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
+			if (granted_qos != 0){
+				printf("granted qos != 0, %d\n", granted_qos);
+				goto exit;
+			}
+			break;
+		}
+		else if (frc == -1)
+			goto exit;
+	} while (1); /* handle timeouts here */
+	printf("Subscribed\n");
+
+	/* loop getting msgs on subscribed topic */
+	topicString.cstring = "pubtopic";
+	state = READING;
+	while (!toStop)	{
+		/* do other stuff here */
+		switch(state){
+		case READING:
+			if((rc=MQTTPacket_readnb(buf, buflen, &mytransport)) == PUBLISH){
+				unsigned char dup;
+				int qos;
+				unsigned char retained;
+				unsigned short msgid;
+				int payloadlen_in;
+				unsigned char* payload_in;
+				int rc;
+				MQTTString receivedTopic;
+	
+				rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
+						&payload_in, &payloadlen_in, buf, buflen);
+				printf("message arrived %.*s\n", payloadlen_in, payload_in);
+				printf("publishing reading\n");
+				state = PUBLISHING;
+				len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char*)payload, payloadlen);
+				transport_sendPacketBuffernb_start(mysock, buf, len);
+			} else if(rc == -1){
+				/* handle I/O errors here */
+				goto exit;
+			}	/* handle timeouts here */
+			break;
+		case PUBLISHING:
+			switch(transport_sendPacketBuffernb(mysock)){
+			case TRANSPORT_DONE:
+				printf("Published\n");
+				state = READING;
+				break;
+			case TRANSPORT_ERROR:
+				/* handle any I/O errors here */
+				goto exit;
+				break;
+			case TRANSPORT_AGAIN:
+			default:
+				/* handle timeouts here, not probable unless there is a hardware problem */
+				break;
+			}
+			break;
+		}
+	}
+
+	printf("disconnecting\n");
+	len = MQTTSerialize_disconnect(buf, buflen);
+	/* Same blocking related stuff here */
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+exit:
+	transport_close(mysock);
+	
+	sampleserial_close();
+	return 0;
+}
+
+
+/* To stop the sample */
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+void stop_init(void)
+{
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+}
+
+/* Serial hack:
+Simulate serial transfers on an established TCP connection
+ */
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h> 
+#include <fcntl.h>
+
+static int sockfd;
+
+void sampleserial_init(void)
+{
+struct sockaddr_in serv_addr;
+
+
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	  perror(NULL);
+	  exit(2);
+	}
+	serv_addr.sin_family = AF_INET;
+	serv_addr.sin_addr.s_addr = inet_addr("198.41.30.241");
+	serv_addr.sin_port = htons(1883);
+	if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+		printf("ERROR connecting\n");
+		exit(-1);
+	}
+	printf("- TCP Connected to Eclipse\n");
+        /* set to non-blocking */
+	fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
+}
+
+void sampleserial_close(void)
+{
+	close(sockfd);
+}
+
+int samplesend(unsigned char *address, unsigned int bytes)
+{
+int len;
+
+	if(rand() > (RAND_MAX/2))	// 50% probability of being busy
+		return 0;
+	if(rand() > (RAND_MAX/2)){	// 50% probability of sending half the requested data (no room in buffer)
+		if(bytes > 1)
+			bytes /= 2;
+	}
+	if((len = write(sockfd, address, bytes)) >= 0)
+		return len;
+	if(errno == EAGAIN)
+		return 0;
+	return -1;
+}
+
+int samplerecv(unsigned char *address, unsigned int maxbytes)
+{
+int len;
+
+	if(rand() > (RAND_MAX/2))	// 50% probability of no data
+		return 0;
+	if(rand() > (RAND_MAX/2)){	// 50% probability of getting half the requested data (not arrived yet)
+		if(maxbytes > 1){
+			maxbytes /= 2;
+		}
+	}
+	if((len = read(sockfd, address, maxbytes)) >= 0)
+		return len;
+	if(errno == EAGAIN)
+		return 0;
+	return -1;
+}
+

+ 122 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/transport.c

@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - port to the bare metal environment and serial media specifics
+ *******************************************************************************/
+
+/** By the way, this is a nice bare bones example, easier to expand to whatever non-OS
+media you might have */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "transport.h"
+
+/**
+This simple low-level implementation assumes a single connection for a single thread. Thus, single static
+variables are used for that connection.
+On other scenarios, you might want to put all these variables into a structure and index via the 'sock'
+parameter, as some functions show in the comments
+The blocking rx function is not supported.
+If you plan on writing one, take into account that the current implementation of
+MQTTPacket_read() has a function pointer for a function call to get the data to a buffer, but no provisions
+to know the caller or other indicator (the socket id): int (*getfn)(unsigned char*, int)
+*/
+static transport_iofunctions_t *io = NULL;
+static unsigned char *from = NULL;		// to keep track of data sending
+static int howmany;				// ditto
+
+
+void transport_sendPacketBuffernb_start(int sock, unsigned char* buf, int buflen)
+{
+	from = buf;			// from[sock] or mystruct[sock].from
+	howmany = buflen;		// myhowmany[sock] or mystruct[sock].howmany
+}
+
+int transport_sendPacketBuffernb(int sock)
+{
+transport_iofunctions_t *myio = io;	// io[sock] or mystruct[sock].io
+int len;
+
+	/* you should have called open() with a valid pointer to a valid struct and 
+	called sendPacketBuffernb_start with a valid buffer, before calling this */
+	assert((myio != NULL) && (myio->send != NULL) && (from != NULL));
+	if((len = myio->send(from, howmany)) > 0){
+		from += len;
+		if((howmany -= len) <= 0){
+			return TRANSPORT_DONE;
+		}
+	} else if(len < 0){
+		return TRANSPORT_ERROR;
+	}
+	return TRANSPORT_AGAIN;
+}
+
+int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen)
+{
+int rc;
+
+	transport_sendPacketBuffernb_start(sock, buf, buflen);
+	while((rc=transport_sendPacketBuffernb(sock)) == TRANSPORT_AGAIN){
+		/* this is unlikely to loop forever unless there is a hardware problem */
+	}
+	if(rc == TRANSPORT_DONE){
+		return buflen;
+	}
+	return TRANSPORT_ERROR;
+}
+
+
+int transport_getdata(unsigned char* buf, int count)
+{
+	assert(0);		/* This function is NOT supported, it is just here to tease you */
+	return TRANSPORT_ERROR;	/* nah, it is here for similarity with other transport examples */
+}
+
+int transport_getdatanb(void *sck, unsigned char* buf, int count)
+{
+//int sock = *((int *)sck); 		/* sck: pointer to whatever the system may use to identify the transport */
+transport_iofunctions_t *myio = io;	// io[sock] or mystruct[sock].io
+int len;
+	
+	/* you should have called open() with a valid pointer to a valid struct before calling this */
+	assert((myio != NULL) && (myio->recv != NULL));
+	/* this call will return immediately if no bytes, or return whatever outstanding bytes we have,
+	 upto count */
+	if((len = myio->recv(buf, count)) >= 0)
+		return len;
+	return TRANSPORT_ERROR;
+}
+
+/**
+return >=0 for a connection descriptor, <0 for an error code
+*/
+int transport_open(transport_iofunctions_t *thisio)
+{
+int idx=0;	// for multiple connections, you might, basically turn myio into myio[MAX_CONNECTIONS],
+
+	//if((idx=assignidx()) >= MAX_CONNECTIONS)	// somehow assign an index,
+	//	return TRANSPORT_ERROR;
+	io = thisio;					// store myio[idx] = thisio, or mystruct[idx].io = thisio, 
+	return idx;					// and return the index used
+}
+
+int transport_close(int sock)
+{
+int rc=TRANSPORT_DONE;
+
+	return rc;
+}

+ 70 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/baremetalserial/transport.h

@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - media specifics, nice api doc :^)
+ *******************************************************************************/
+
+typedef struct {
+	int (*send)(unsigned char *address, unsigned int bytes); 	///< pointer to function to send 'bytes' bytes, returns the actual number of bytes sent
+	int (*recv)(unsigned char *address, unsigned int maxbytes); 	///< pointer to function to receive upto 'maxbytes' bytes, returns the actual number of bytes copied
+} transport_iofunctions_t;
+
+#define TRANSPORT_DONE	1
+#define TRANSPORT_AGAIN	0
+#define TRANSPORT_ERROR	-1
+/**
+@note Blocks until requested buflen is sent
+*/
+int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen);
+/**
+@note Blocks until requested count is received, as MQTTPacket_read() expects
+@warning This function is not supported (not implemented)
+@warning unless you provide a timeout, this function can block forever. Socket based systems do have
+a built in timeout, if your system can provide this, do modify this function, otherwise use getdatanb() instead
+@returns number of bytes read
+*/
+int transport_getdata(unsigned char* buf, int count);
+
+/**
+This is a bare metal implementation, so we must have non-blocking functions,
+the process of pumping to serial lines can result a bit slow and we don't want to busy wait.
+This function starts the process, you will call sendPacketBuffernb() until it reports success (or error)
+*/
+void transport_sendPacketBuffernb_start(int sock, unsigned char* buf, int buflen);
+/**
+This is a bare metal implementation, so we must have non-blocking functions,
+the process of pumping to serial lines can result a bit slow and we don't want to busy wait
+@returns TRANSPORT_DONE if finished, TRANSPORT_AGAIN for call again, or TRANSPORT_ERROR on error
+@note you will call again until it finishes (this is stream)
+*/
+int transport_sendPacketBuffernb(int sock);
+
+/**
+This is a bare metal implementation, so we must have non-blocking functions,
+the process of sucking from serial lines can result a bit slow and we don't want to busy wait
+@return the actual number of bytes read, 0 for none, or TRANSPORT_ERROR on error
+@note you will call again until total number of expected bytes is read (this is stream)
+*/
+int transport_getdatanb(void *sck, unsigned char* buf, int count);
+
+/**
+We assume whatever connection needs to be done, it is externally established by the specifics of the hardware
+E.g.:
+A cell modem: you will call AT+whatever and put the modem in transparent mode, OR, you will embed
+the AT+xSENDx / AT+xRECVx commands into the former sendPacketBuffer() and getdatanb() functions
+@param	thisio	pointer to a structure containing all necessary stuff to handle direct serial I/O
+@returns	whatever indicator the system assigns to this link, if any. (a.k.a. : 'sock'), or TRANSPORT_ERROR for error
+*/
+int transport_open(transport_iofunctions_t *thisio);
+int transport_close(int sock);

+ 6 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/build

@@ -0,0 +1,6 @@
+gcc -Wall -c transport.c -Os -s
+gcc qos0pub.c transport.o -I ../src ../src/MQTTConnectClient.c ../src/MQTTSerializePublish.c ../src/MQTTPacket.c -o qos0pub -Os -s
+
+gcc pub0sub1.c transport.o -I ../src ../src/MQTTConnectClient.c ../src/MQTTSerializePublish.c ../src/MQTTPacket.c ../src/MQTTSubscribeClient.c -o pub0sub1 ../src/MQTTDeserializePublish.c -Os -s ../src/MQTTConnectServer.c ../src/MQTTSubscribeServer.c ../src/MQTTUnsubscribeServer.c ../src/MQTTUnsubscribeClient.c -ggdb
+gcc pub0sub1_nb.c transport.o -I ../src ../src/MQTTConnectClient.c ../src/MQTTSerializePublish.c ../src/MQTTPacket.c ../src/MQTTSubscribeClient.c -o pub0sub1_nb ../src/MQTTDeserializePublish.c -Os -s ../src/MQTTConnectServer.c ../src/MQTTSubscribeServer.c ../src/MQTTUnsubscribeServer.c ../src/MQTTUnsubscribeClient.c -ggdb
+

+ 4 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/null.c

@@ -0,0 +1,4 @@
+int main(int argc, char **argv)
+{
+    return 0;
+}

+ 142 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/ping.c

@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - port
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+#define KEEPALIVE_INTERVAL 20
+
+/* This is to get a timebase in seconds to test the sample */
+#include <time.h>
+time_t old_t;
+void start_ping_timer(void)
+{
+	time(&old_t);
+	old_t += KEEPALIVE_INTERVAL/2 + 1;
+}
+
+int time_to_ping(void)
+{
+time_t t;
+
+	time(&t);
+	if(t >= old_t)
+	  	return 1;
+	return 0;
+}
+
+/* This is in order to get an asynchronous signal to stop the sample,
+as the code loops waiting for msgs on the subscribed topic.
+Your actual code will depend on your hw and approach*/
+#include <signal.h>
+
+int toStop = 0;
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+void stop_init(void)
+{
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+}
+/* */
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	int mysock = 0;
+	unsigned char buf[200];
+	int buflen = sizeof(buf);
+	int len = 0;
+	char *host = "m2m.eclipse.org";
+	int port = 1883;
+
+	stop_init();
+	if (argc > 1)
+		host = argv[1];
+
+	if (argc > 2)
+		port = atoi(argv[2]);
+
+	mysock = transport_open(host, port);
+	if(mysock < 0)
+		return mysock;
+
+	printf("Sending to hostname %s port %d\n", host, port);
+
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = KEEPALIVE_INTERVAL;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	len = MQTTSerialize_connect(buf, buflen, &data);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+	printf("Sent MQTT connect\n");
+	/* wait for connack */
+	if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK)
+	{
+		unsigned char sessionPresent, connack_rc;
+
+		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0)
+		{
+			printf("Unable to connect, return code %d\n", connack_rc);
+			goto exit;
+		}
+	}
+	else
+		goto exit;
+
+	printf("MQTT connected\n");
+	start_ping_timer();
+
+	while (!toStop)
+	{
+		while(!time_to_ping());
+		len = MQTTSerialize_pingreq(buf, buflen);
+		transport_sendPacketBuffer(mysock, buf, len);
+		printf("Ping...");
+		if (MQTTPacket_read(buf, buflen, transport_getdata) == PINGRESP){
+			printf("Pong\n");
+			start_ping_timer();
+		}
+		else {
+			printf("OOPS\n");
+			goto exit;
+		}
+		
+	}
+
+	printf("disconnecting\n");
+	len = MQTTSerialize_disconnect(buf, buflen);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+exit:
+	transport_close(mysock);
+
+	return 0;
+}

+ 157 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/ping_nb.c

@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - port and nonblocking
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+#define KEEPALIVE_INTERVAL 20
+
+/* This is to get a timebase in seconds to test the sample */
+#include <time.h>
+time_t old_t;
+void start_ping_timer(void)
+{
+	time(&old_t);
+	old_t += KEEPALIVE_INTERVAL/2 + 1;
+}
+
+int time_to_ping(void)
+{
+time_t t;
+
+	time(&t);
+	if(t >= old_t)
+	  	return 1;
+	return 0;
+}
+
+/* This is in order to get an asynchronous signal to stop the sample,
+as the code loops waiting for msgs on the subscribed topic.
+Your actual code will depend on your hw and approach*/
+#include <signal.h>
+
+int toStop = 0;
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+void stop_init(void)
+{
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+}
+/* */
+
+enum states { IDLE, GETPONG };
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	int mysock = 0;
+	unsigned char buf[200];
+	int buflen = sizeof(buf);
+	int len = 0;
+	char *host = "m2m.eclipse.org";
+	int port = 1883;
+	MQTTTransport mytransport;
+	int state;
+
+	stop_init();
+	if (argc > 1)
+		host = argv[1];
+
+	if (argc > 2)
+		port = atoi(argv[2]);
+
+	mysock = transport_open(host, port);
+	if(mysock < 0)
+		return mysock;
+
+	printf("Sending to hostname %s port %d\n", host, port);
+
+	mytransport.sck = &mysock;
+	mytransport.getfn = transport_getdatanb;
+	mytransport.state = 0;
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = KEEPALIVE_INTERVAL;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	len = MQTTSerialize_connect(buf, buflen, &data);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+	printf("Sent MQTT connect\n");
+	/* wait for connack */
+	do {
+		int frc;
+		if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == CONNACK){
+			unsigned char sessionPresent, connack_rc;
+			if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0){
+				printf("Unable to connect, return code %d\n", connack_rc);
+				goto exit;
+			}
+			break;
+		}
+		else if (frc == -1)
+			goto exit;
+	} while (1); /* handle timeouts here */
+
+	printf("MQTT connected\n");
+	start_ping_timer();
+	
+	state = IDLE;
+	while (!toStop)	{
+		switch(state){
+		case IDLE:
+			if(time_to_ping()){
+				len = MQTTSerialize_pingreq(buf, buflen);
+				transport_sendPacketBuffer(mysock, buf, len);
+				printf("Ping...");
+				state = GETPONG;
+			}
+			break;
+		case GETPONG:
+			if((rc=MQTTPacket_readnb(buf, buflen, &mytransport)) == PINGRESP){
+				printf("Pong\n");
+				start_ping_timer();
+				state = IDLE;
+			} else if(rc == -1){
+				printf("OOPS\n");
+				goto exit;
+			}
+			break;
+		}
+	}
+
+	printf("disconnecting\n");
+	len = MQTTSerialize_disconnect(buf, buflen);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+exit:
+	transport_close(mysock);
+	
+	return 0;
+}

+ 153 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/pub0sub1.c

@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - clarifications and/or documentation extension
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+/* This is in order to get an asynchronous signal to stop the sample,
+as the code loops waiting for msgs on the subscribed topic.
+Your actual code will depend on your hw and approach*/
+#include <signal.h>
+
+int toStop = 0;
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+void stop_init(void)
+{
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+}
+/* */
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	int mysock = 0;
+	unsigned char buf[200];
+	int buflen = sizeof(buf);
+	int msgid = 1;
+	MQTTString topicString = MQTTString_initializer;
+	int req_qos = 0;
+	char* payload = "mypayload";
+	int payloadlen = strlen(payload);
+	int len = 0;
+	char *host = "m2m.eclipse.org";
+	int port = 1883;
+
+	stop_init();
+	if (argc > 1)
+		host = argv[1];
+
+	if (argc > 2)
+		port = atoi(argv[2]);
+
+	mysock = transport_open(host, port);
+	if(mysock < 0)
+		return mysock;
+
+	printf("Sending to hostname %s port %d\n", host, port);
+
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = 20;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	len = MQTTSerialize_connect(buf, buflen, &data);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+	/* wait for connack */
+	if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK)
+	{
+		unsigned char sessionPresent, connack_rc;
+
+		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0)
+		{
+			printf("Unable to connect, return code %d\n", connack_rc);
+			goto exit;
+		}
+	}
+	else
+		goto exit;
+
+	/* subscribe */
+	topicString.cstring = "substopic";
+	len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);
+
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+	if (MQTTPacket_read(buf, buflen, transport_getdata) == SUBACK) 	/* wait for suback */
+	{
+		unsigned short submsgid;
+		int subcount;
+		int granted_qos;
+
+		rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
+		if (granted_qos != 0)
+		{
+			printf("granted qos != 0, %d\n", granted_qos);
+			goto exit;
+		}
+	}
+	else
+		goto exit;
+
+	/* loop getting msgs on subscribed topic */
+	topicString.cstring = "pubtopic";
+	while (!toStop)
+	{
+		/* transport_getdata() has a built-in 1 second timeout,
+		your mileage will vary */
+		if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH)
+		{
+			unsigned char dup;
+			int qos;
+			unsigned char retained;
+			unsigned short msgid;
+			int payloadlen_in;
+			unsigned char* payload_in;
+			int rc;
+			MQTTString receivedTopic;
+
+			rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
+					&payload_in, &payloadlen_in, buf, buflen);
+			printf("message arrived %.*s\n", payloadlen_in, payload_in);
+		}
+
+		printf("publishing reading\n");
+		len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char*)payload, payloadlen);
+		rc = transport_sendPacketBuffer(mysock, buf, len);
+	}
+
+	printf("disconnecting\n");
+	len = MQTTSerialize_disconnect(buf, buflen);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+exit:
+	transport_close(mysock);
+
+	return 0;
+}

+ 158 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/pub0sub1_nb.c

@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - clarifications and/or documentation extension
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+/* This is in order to get an asynchronous signal to stop the sample,
+as the code loops waiting for msgs on the subscribed topic.
+Your actual code will depend on your hw and approach*/
+#include <signal.h>
+
+int toStop = 0;
+
+void cfinish(int sig)
+{
+	signal(SIGINT, NULL);
+	toStop = 1;
+}
+
+void stop_init(void)
+{
+	signal(SIGINT, cfinish);
+	signal(SIGTERM, cfinish);
+}
+/* */
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	int mysock = 0;
+	unsigned char buf[200];
+	int buflen = sizeof(buf);
+	int msgid = 1;
+	MQTTString topicString = MQTTString_initializer;
+	int req_qos = 0;
+	char* payload = "mypayload";
+	int payloadlen = strlen(payload);
+	int len = 0;
+	char *host = "m2m.eclipse.org";
+	int port = 1883;
+	MQTTTransport mytransport;
+
+	stop_init();
+	if (argc > 1)
+		host = argv[1];
+
+	if (argc > 2)
+		port = atoi(argv[2]);
+
+	mysock = transport_open(host, port);
+	if(mysock < 0)
+		return mysock;
+
+	printf("Sending to hostname %s port %d\n", host, port);
+
+	mytransport.sck = &mysock;
+	mytransport.getfn = transport_getdatanb;
+	mytransport.state = 0;
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = 20;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	len = MQTTSerialize_connect(buf, buflen, &data);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+	/* wait for connack */
+	if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK)
+	{
+		unsigned char sessionPresent, connack_rc;
+
+		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0)
+		{
+			printf("Unable to connect, return code %d\n", connack_rc);
+			goto exit;
+		}
+	}
+	else
+		goto exit;
+
+	/* subscribe */
+	topicString.cstring = "substopic";
+	len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);
+
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+	do {
+		int frc;
+		if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == SUBACK) /* wait for suback */
+		{
+			unsigned short submsgid;
+			int subcount;
+			int granted_qos;
+
+			rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
+			if (granted_qos != 0)
+			{
+				printf("granted qos != 0, %d\n", granted_qos);
+				goto exit;
+			}
+			break;
+		}
+		else if (frc == -1)
+			goto exit;
+	} while (1); /* handle timeouts here */
+	/* loop getting msgs on subscribed topic */
+	topicString.cstring = "pubtopic";
+	while (!toStop)
+	{
+		/* handle timeouts */
+		if (MQTTPacket_readnb(buf, buflen, &mytransport) == PUBLISH)
+		{
+			unsigned char dup;
+			int qos;
+			unsigned char retained;
+			unsigned short msgid;
+			int payloadlen_in;
+			unsigned char* payload_in;
+			int rc;
+			MQTTString receivedTopic;
+
+			rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
+					&payload_in, &payloadlen_in, buf, buflen);
+			printf("message arrived %.*s\n", payloadlen_in, payload_in);
+			printf("publishing reading\n");
+			len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char*)payload, payloadlen);
+			rc = transport_sendPacketBuffer(mysock, buf, len);
+		}
+	}
+
+	printf("disconnecting\n");
+	len = MQTTSerialize_disconnect(buf, buflen);
+	rc = transport_sendPacketBuffer(mysock, buf, len);
+
+exit:
+	transport_close(mysock);
+
+	return 0;
+}

+ 76 - 0
iot_link/network/mqtt/paho_mqtt/paho/MQTTPacket/samples/qos0pub.c

@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - clarifications and/or documentation extension
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MQTTPacket.h"
+#include "transport.h"
+
+
+int main(int argc, char *argv[])
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	char buf[200];
+	int buflen = sizeof(buf);
+	int mysock = 0;
+	MQTTString topicString = MQTTString_initializer;
+	char* payload = "mypayload";
+	int payloadlen = strlen(payload);
+	int len = 0;
+	char *host = "m2m.eclipse.org";
+	int port = 1883;
+
+	if (argc > 1)
+		host = argv[1];
+
+	if (argc > 2)
+		port = atoi(argv[2]);
+
+	mysock = transport_open(host,port);
+	if(mysock < 0)
+		return mysock;
+
+	printf("Sending to hostname %s port %d\n", host, port);
+
+	data.clientID.cstring = "me";
+	data.keepAliveInterval = 20;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+	data.MQTTVersion = 4;
+
+	len = MQTTSerialize_connect((unsigned char *)buf, buflen, &data);
+
+	topicString.cstring = "mytopic";
+	len += MQTTSerialize_publish((unsigned char *)(buf + len), buflen - len, 0, 0, 0, 0, topicString, (unsigned char *)payload, payloadlen);
+
+	len += MQTTSerialize_disconnect((unsigned char *)(buf + len), buflen - len);
+
+	rc = transport_sendPacketBuffer(mysock, (unsigned char*)buf, len);
+	if (rc == len)
+		printf("Successfully published\n");
+	else
+		printf("Publish failed\n");
+
+exit:
+	transport_close(mysock);
+
+	return 0;
+}

Some files were not shown because too many files changed in this diff