From 54022c2481d45df22f9b3a3c39500fae542a01f5 Mon Sep 17 00:00:00 2001 From: supowang Date: Tue, 9 Mar 2021 16:30:41 +0800 Subject: [PATCH] update mqtt client update mqtt client --- components/connectivity/mqttclient/README.md | 170 +++++++------- .../connectivity/mqttclient/README_CN.md | 211 ++++++++++++++++++ .../connectivity/mqttclient/README_EN.md | 209 ----------------- .../mqttclient/common/mqtt_error.h | 10 +- .../mqttclient/common/mqtt_list.h | 10 +- .../connectivity/mqttclient/common/mqtt_log.h | 10 +- .../connectivity/mqttclient/common/random.h | 10 +- .../mqttclient/mqttclient/mqttclient.c | 202 ++++++++++++----- .../mqttclient/mqttclient/mqttclient.h | 11 +- .../mqttclient/network/nettype_tcp.h | 10 +- .../mqttclient/network/nettype_tls.c | 4 +- .../mqttclient/network/nettype_tls.h | 10 +- .../connectivity/mqttclient/network/network.h | 10 +- .../TencentOS-tiny/platform_net_socket.c | 2 +- .../TencentOS-tiny/platform_net_socket.h | 2 +- .../connectivity/mqttclient/test/test.c | 100 --------- .../connectivity/mqttclient/test/test_ca.c | 75 ------- 17 files changed, 514 insertions(+), 542 deletions(-) create mode 100644 components/connectivity/mqttclient/README_CN.md delete mode 100644 components/connectivity/mqttclient/README_EN.md delete mode 100644 components/connectivity/mqttclient/test/test.c delete mode 100644 components/connectivity/mqttclient/test/test_ca.c diff --git a/components/connectivity/mqttclient/README.md b/components/connectivity/mqttclient/README.md index c29ed2bb..cc18e21c 100644 --- a/components/connectivity/mqttclient/README.md +++ b/components/connectivity/mqttclient/README.md @@ -8,63 +8,62 @@ ![](https://img.shields.io/badge/platform-Linux|Windows|Mac|Embedded-orange.svg) -[English Documents](README.md) - +[中文说明](README_CN.md) # mqttclient -**一个高性能、高稳定性的跨平台MQTT客户端** +**A high-performance, high-stability, cross-platform MQTT client** -一个高性能、高稳定性的跨平台MQTT客户端,基于socket API之上开发,可以在嵌入式设备(FreeRTOS/LiteOS/RT-Thread/TencentOS tiny)、Linux、Windows、Mac上使用,拥有非常简洁的API接口,以极少的资源实现QOS2的服务质量,并且无缝衔接了mbedtls加密库。 +A high-performance, high-stability, cross-platform MQTT client, developed based on the socket API, can be used on embedded devices (FreeRTOS/LiteOS/RT-Thread/TencentOS tiny), Linux, Windows, Mac, and has a very concise The API interface realizes the quality of service of QOS2 with very few resources, and seamlessly connects the mbedtls encryption library. -## 优势: +## Advantage: -- **具有极高的稳定性**:无论是**掉线重连**,**丢包重发**,都是**严格遵循MQTT协议标准**执行,除此之外对**大数据量**的测试无论是收是发,都是非常稳定,**高频**测试也是非常稳定。 +- **Extremely high stability**: Whether it is **drop and reconnect**, **packet loss and retransmission**, it is **strictly abide by the MQTT protocol standard**, in addition to The test of **large data volume** is very stable whether it is receiving or sending, and the **high frequency** test is also very stable. -- **轻量级**:整个代码工程极其简单,不使用mbedtls情况下,占用资源极少,作者曾使用esp8266模组与云端通信,整个工程代码消耗的RAM不足15k。 +- **Lightweight**: The entire code project is extremely simple. Without mbedtls, it takes up very few resources. The author used the esp8266 module to communicate with the cloud. The entire project code consumes less than 15k of RAM. -- **支持mbedtls加密传输**,让网络传输更加安全,而且接口层完全不需要用户理会,无论是否加密,mqttclient对用户提供的API接口是**固定**的,这就很好的兼容了一套代应用层的码可以加密传输也可以不加密传输。 +- **Support mbedtls encrypted transmission**, make the network transmission more secure, and the interface layer does not require users to care, no matter whether it is encrypted or not, mqttclient is **fixed** for the API interface provided by the user, which is very compatible A set of codes on behalf of the application layer can be transmitted with or without encryption. -- **支持多客户端**,同时兼容多个客户端运行工作,一个设备连接多个的服务器。 +- **Supports multiple clients**, compatible with multiple clients running at the same time, one device connected to multiple servers. -- **支持同步异步处理**,应用程序无需阻塞等待浪费CPU资源。 +- **Supports synchronous and asynchronous processing**, applications need not block and wait to waste CPU resources. -- **支持拦截器配置**,在某些平台中,客户端会默认自动订阅系统主题,而且每次来自服务器的主题都是变动的,此时需要使用拦截器进行拦截,分离主题与数据信息,并递交给用户,极大提高灵活性。 +- **Support interceptor configuration**, on some platforms, the client will automatically subscribe to the system theme by default, and the theme from the server changes every time. In this case, you need to use an interceptor to intercept and separate the theme and data Information and deliver it to users, greatly improving flexibility. -- **拥有在线代码生成工具**,极其简单配置就可以生成对应的代码,地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) +- **With online code generation tool**, the code can be generated with extremely simple configuration, address: [https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) -- **拥有极简的API接口**,总的来说,mqttclient的配置都有默认值,基本无需配置都能使用的,也可以随意配置,对配置都有健壮性检测,这样子设计的API接口也是非常简单。 +- **Has a very simple API interface**, in general, mqttclient configuration has default values, basically can be used without configuration, can also be arbitrarily configured, the configuration has robustness detection, so designed The API interface is also very simple. -- **多功能参数可配置可裁剪**,重连时间间隔、心跳周期、最大订阅数量、命令超时、读写缓冲区大小、拦截器处理等等参数功能可裁剪可配置,满足开发者再复杂、简单等各种开发环境下的使用需求。 +- **Multifunctional parameters can be configured and tailored**, reconnect time interval, heartbeat period, maximum number of subscriptions, command timeout, read and write buffer size, interceptor processing, etc. Parameters can be tailored and configurable to meet the needs of developers Complex and simple to use in various development environments. -- **支持自动重新订阅主题**,在自动重连后保证主题不会丢失。 +- **Support automatic re-subscription of topics**, after automatic reconnection to ensure that the topics will not be lost. -- **支持主题通配符`“#”、“+”`**。 +- **Support theme wildcards ""#", "+"`**. -- **订阅的主题与消息处理完全分离**,让编程逻辑更加简单易用,用户无需理会错综复杂的逻辑关系。 +- **Subscribed topics are completely separated from message processing**, making programming logic easier and easier to use, users don’t have to deal with intricate logical relationships. -- **mqttclient内部已实现保活处理机制**,无需用户过多关心理会,用户只需专心处理应用功能即可。 +- **The keep-alive processing mechanism has been implemented in mqttclient**, without the user having to deal with the psychological experience, the user only needs to concentrate on the application function. -- **拥有非常好的设计**,以极少的资源设计了**记录机制**,当报文在丢失的时候进行重发操作,确保qos1、qos2服务质量等级的报文保证其服务质量。 +- **Has a very good design**, designed the **recording mechanism** with very few resources, and retransmits the message when it is lost to ensure that the qos1 and qos2 service quality levels guarantee its service quality. -- **有非常好的代码风格与思想**:整个代码采用分层式设计,代码实现采用异步处理的思想,降低耦合,提高性能。 +- **There are very good code styles and ideas**: The whole code adopts a layered design, and the code implementation adopts the idea of ​​asynchronous processing to reduce coupling and improve performance. -- **基于标准BSD socket之上开发**,只要是兼容BSD socket的系统均可使用。 +- **Developed on top of standard BSD socket**, as long as it is compatible with BSD socket system. -- **无缝衔接salof**:它是一个同步异步日志输出框架,在空闲时候输出对应的日志信息,也可以将信息写入flash中保存,方便调试。 +- **Seamless connection of salof**: It is a synchronous and asynchronous log output framework. It outputs the corresponding log information when it is idle, and it can also write the information into flash to save it, which is convenient for debugging. -- **使用著名的 paho mqtt 库封包**。 +- **Use the famous paho mqtt library package**. -- **无其他依赖**。 +- **No other dependencies**. -## 在线代码生成工具 +## Online code generation tool -本项目拥有代码生成工具,只需要在线配置即可生成代码,极其简单易用,代码生成工具地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) +This project has a code generation tool that only requires online configuration to generate code, which is extremely simple and easy to use. The code generation tool address is: [https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) -![在线代码生成工具](png/mqtt-tool.png) +![Online code generation tool](png/mqtt-tool.png) -## 占用资源大小 +## occupied resource size -总计占 **10857字节** 的ROM,而RAM的开销则几乎只依赖动态内存,在不使用TLS加密传输的情况下,维持QOS0服务质量等级的通信动态内存大约仅需要**3694**字节,这包括1024读缓冲区 + 1024写缓冲区 + 1024内部线程栈大小,相对于其他MQTT客户端来说,mqttclient需要的RAM资源开销极少。 +A total of **10857 bytes** of ROM, and the overhead of RAM is almost only dependent on dynamic memory. Without using TLS encrypted transmission, the communication dynamic memory that maintains the QOS0 quality of service level requires only about **3694** bytes. Including 1024 read buffer + 1024 write buffer + 1024 internal thread stack size, compared with other MQTT clients, mqttclient requires very little RAM resource overhead. | Code | RO Data | RW Data | ZI Data | Object Name | | -- | -- | -- | -- | -- | @@ -87,125 +86,124 @@ | - | - | - | - | - | | 10066 | 791 | 8 | 0 | total | -## 整体框架 +## Overall framework -拥有非常明确的分层框架。 +Has a very clear layered framework. -![整体框架](png/mqttclient.png) +![Overall Frame](png/mqttclient.png) -- 在框架的最上方是**API**函数接口,实现了客户端的**申请、释放、设置参数、连接服务器、断开连接、订阅主题、取消订阅主题、发布消息**等函数接口。 +- At the top of the framework is the **API** function interface, which implements the client's **application, release, set parameters, connect to the server, disconnect, subscribe topic, unsubscribe topic, publish message** and other functional interfaces. -- 使用了著名的**paho mqtt**库作为MQTT报文封包库。 +- The famous **paho mqtt** library is used as the MQTT message packet library. -- 采用异步处理的机制去管理所有的ack,它在发送报文的时候不用等待服务器的应答,只是记录下来,在收到服务器的ack后,取消这个记录,**效率极高**;而在发送mqtt报文(QoS1/QoS2)的时候没有收到服务器的应答时,将**重发**该报文。 +- Asynchronous processing mechanism is used to manage all the acks. It does not need to wait for the server's response when sending the message, but only records it. After receiving the server's ack, cancel this record, **very efficient**; and When the mqtt message (QoS1/QoS2) is sent and no response is received from the server, the message will be **retransmitted**. -- 内部实现了一个**mqtt yield**线程,统一处理所有的内容,比如**超时的处理、ack报文的处理、收到来自服务器的publish报文**,此时会去调用回调函数告知用户收到的数据,**发布释放、发布完成报文的处理、心跳报文(保持活性),当与服务器断开连接时需要尝试重连、重新订阅主题,重新发送报文或者应答**等。 +- An **mqtt yield** thread is implemented internally to handle all content in a unified manner, such as **timeout processing, ack message processing, and receiving publish message from the server**, at this time the callback function will be called Inform the user of the data received, **post release, post completion message processing, heartbeat message (keep alive), when disconnected from the server, you need to try to reconnect, resubscribe to the topic, resend the message or reply* *Wait. -- 报文的处理,如**读写报文、解码mqtt报文、设置报文(dup标记)、销毁报文**等操作。 +- Message processing, such as **reading and writing messages, decoding mqtt messages, setting messages (dup flag), destroying messages** and other operations. -- **network**是网络组件,它可以**自动选择数据通道**,如果是加密方式则通过**tls加密**进行数据传输,而tls可以选择mbedtls作为加密后端;也可以是**tcp直连**方式,最终都是通过tcp传输的。 +- **network** is a network component, which can **automatically select a data channel**, if it is an encryption method, **tls encryption** is used for data transmission, and tls can choose mbedtls as the encryption backend; it can also be The **tcp direct connection** method is ultimately transmitted via tcp. -- **platform**是平台抽象层,封装了不同系统的东西,比如**socke或者AT,线程、时间、互斥锁、内存管理**,这些是与系统打交道的,也是跨平台必要的封装。 +- **platform** is a platform abstraction layer that encapsulates things from different systems, such as socke or AT, thread, time, mutex, memory management**, these are dealing with the system and are also necessary for cross-platform Package. -- 最右边的则是通用的内容,**list的处理、日志库、错误处理、软件随机数发生器**等。 +- On the far right is the general content, **list processing, log library, error handling, software random number generator**, etc. -## 支持的平台 +## Supported platforms -**目前已实现了Linux、TencentOS tiny、FreeRTOS、RT-Thread平台(已做成软件包,名字为`kawaii-mqtt`),除此之外TencentOS tiny的AT框架亦可以使用,并且稳定性极好!** +**At present, Linux, TencentOS tiny, FreeRTOS, RT-Thread platforms have been implemented (software package is named kawaii-mqtt`), in addition to TencentOS tiny AT framework can also be used, and the stability is excellent!** -| 平台 | 代码位置 | +| Platform | Code Location | | -------------- | -------- | -| Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) | +| Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) | | TencentOS tiny | [https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429](https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429) | -| TencentOS tiny AT 框架 | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) | -| RT-Thread | [https://github.com/jiejieTop/kawaii-mqtt](https://github.com/jiejieTop/kawaii-mqtt) | -| FreeRTOS | [https://github.com/jiejieTop/freertos-mqttclient](https://github.com/jiejieTop/freertos-mqttclient) | +| TencentOS tiny AT framework | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) | +| RT-Thread | [https://github.com/jiejieTop/kawaii-mqtt](https://github.com/jiejieTop/kawaii-mqtt) | +| FreeRTOS | [https://github.com/jiejieTop/freertos-mqttclient](https://github.com/jiejieTop/freertos-mqttclient) | -## 版本 +## Version -| 发布版本 | 描述 | +| Release Version | Description | | --- | --- | -| [v1.0.0] | 初次发布,完成基本框架及其稳定性验证 | -| [v1.0.1] | 修复主动与服务器断开连接时的逻辑处理 | -| [v1.0.2] | 添加新特性——拦截器,修复一些小bug | -| [v1.0.3] | 避免造成全局污染修改了log、list相关函数的命名 | -| [v1.0.4] | 重新调整了network结构与mbedtls数据通道 | -| [v1.1.0] | 一个较大版本的更新,重构部分代码,优化MQTT处理的逻辑,提升整体的稳定性,支持多客户端,支持设置遗嘱,优化API接口,增加多个云平台的测试代码与说明文档,增加在线代码生成工具、在线裁剪配置工具 | +| [v1.0.0] | Initial release, complete basic framework and stability verification | +| [v1.0.1] | Fix the logical processing when actively disconnecting from the server | +| [v1.0.2] | Add a new feature-interceptor, fix some small bugs | +| [v1.0.3] | To avoid global pollution, modify the naming of log and list related functions | +| [v1.0.4] | Network structure and mbedtls data channel readjusted | +| [v1.1.0] | A larger version of the update, refactoring part of the code, optimizing the logic of MQTT processing, improving the overall stability, supporting multiple clients, supporting setting the will, optimizing the API interface, and adding multiple cloud platforms Test code and documentation, add online code generation tool, online cutting configuration tool | +## question -## 问题 +Welcome to submit issues and bug reports in the form of [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues) -欢迎以 [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues) 的形式提交问题和bug报告 +## Copyright and License -## 版权和许可 +mqttclient follows the [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) open source agreement. Encourage code sharing and respect the copyright of the original author. You can freely use and modify the source code, or you can publish the modified code as open source or closed source software. -mqttclient 遵循 [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 开源协议。鼓励代码共享和尊重原作者的著作权,可以自由的使用、修改源代码,也可以将修改后的代码作为开源或闭源软件发布。 +## Test and use under Linux platform -## linux平台下测试使用 - -### 安装cmake: +### Install cmake: ```bash sudo apt-get install cmake g++ ``` -### 测试程序 +### test program -| 测试平台 | 位置 | -| -- | -- | -| emqx(我私人部署的服务器) | [./test/emqx/test.c](./test/emqx/test.c) | -| 百度天工 | [./test/baidu/test.c](./test/baidu/test.c) | +| Test Platform | Location | +| - | - | +| emqx (my privately deployed server) | [./test/emqx/test.c](./test/emqx/test.c) | +| Baidu Tiangong | [./test/baidu/test.c](./test/baidu/test.c) | | onenet | [./test/onenet/test.c](./test/onenet/test.c) | -| 阿里云物联 | [./test/ali/test.c](./test/ali/test.c) | +| Alibaba Cloud Internet of Things | [./test/ali/test.c](./test/ali/test.c) | -### 编译 & 运行 +### Compile & Run ```bash ./build.sh ``` -运行**build.sh**脚本后会在 **./build/bin/**目录下生成可执行文件**emqx**、**baidu**、**onenet**等多个平台的可执行程序,直接运行即可。 +After running the **build.sh** script, the executable files **emqx**, **baidu**, **onenet** and other platforms will be generated under the **./build/bin/** directory Executable programs can be run directly. ```bash - ./build/bin/emqx + ./build/bin/emqx ``` -### 编译成动态库libmqttclient.so +### Compile into a dynamic library libmqttclient.so ```bash ./make-libmqttclient.sh ``` -运行`make-libmqttclient.sh`脚本后会在 `./libmqttclient/lib`目录下生成一个动态库文件`libmqttclient.so`,并安装到系统的`/usr/lib `目录下,相关头文件已经拷贝到`./libmqttclient/include`目录下,将其拷贝到你的工程中即可,编译应用程序的时候只需要链接动态库即可`-lmqttclient -lpthread`,动态库的配置文件是根据`./test/mqtt_config.h`配置的。 +After running the `make-libmqttclient.sh` script, a dynamic library file `libmqttclient.so` will be generated in the `./libmqttclient/lib` directory, and installed into the system’s `/usr/lib` directory, the relevant header files have been Copy to the `./libmqttclient/include` directory and copy it to your project. You only need to link the dynamic library when compiling the application. `-lmqttclient -lpthread`, the configuration file of the dynamic library is based on` ./test/mqtt_config.h` configuration. -如果你是用交叉编译器的话,则应该根据你使用的编译器导出对应的环境变量(此处使用的交叉编译器是arm-linux-gnueabihf-gcc),同时你也必须将动态库文件`libmqttclient.so`拷贝到你的嵌入式系统的`/usr/lib `目录下: +If you are using a cross-compiler, you should export the corresponding environment variables according to the compiler you are using (the cross-compiler used here is arm-linux-gnueabihf-gcc), and you must also set the dynamic library file `libmqttclient .so` is copied to the `/usr/lib` directory of your embedded system: ```bash - export CROSS_COMPILE=arm-linux-gnueabihf- + export CROSS_COMPILE=arm-linux-gnueabihf- ``` -如若需要卸载**libmqttclient.so**,执行以下命令即可: +If you need to uninstall **libmqttclient.so**, execute the following command: ```bash ./make-libmqttclient.sh remove ``` -## 学习更多 +## Learn more -请看文档: +Please see the documentation: -- [MQTT协议简介](./docs/mqtt-introduction.md) +- [MQTT Protocol Introduction](./docs/mqtt-introduction.md) -- [MQTT协议通信过程](./docs/mqtt-communication.md) +- [MQTT protocol communication process](./docs/mqtt-communication.md) -- [mqttclient代码生成工具](./docs/mqtt-tool.md) +- [mqttclient code generation tool](./docs/mqtt-tool.md) -- [mqttclient配置及裁剪工具](./docs/mqtt-config.md) +- [mqttclient configuration and cutting tool](./docs/mqtt-config.md) -- [mqttclient设计与实现方式](./docs/mqtt-design.md) +- [mqttclient design and implementation](./docs/mqtt-design.md) -- [mqttclient连接到百度天工物接入](./docs/mqtt-baidu.md) +- [mqttclient connects to Baidu Tiangongwu Access](./docs/mqtt-baidu.md) -- [mqttclient连接到OneNET云平台](./docs/mqtt-onenet.md) +- [mqttclient connects to OneNET cloud platform](./docs/mqtt-onenet.md) -- [mqttclient连接到阿里云物联网平台](./docs/mqtt-aliyun.md) +- [mqttclient connects to Alibaba Cloud IoT platform](./docs/mqtt-aliyun.md) diff --git a/components/connectivity/mqttclient/README_CN.md b/components/connectivity/mqttclient/README_CN.md new file mode 100644 index 00000000..c29ed2bb --- /dev/null +++ b/components/connectivity/mqttclient/README_CN.md @@ -0,0 +1,211 @@ +[![](https://img.shields.io/github/v/tag/jiejietop/mqttclient?color=brightgreen&label=version)](https://github.com/jiejieTop/mqttclient/releases) + +[![license](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) + +![](https://img.shields.io/github/forks/jiejieTop/mqttclient) + +![](https://img.shields.io/github/stars/jiejieTop/mqttclient) + +![](https://img.shields.io/badge/platform-Linux|Windows|Mac|Embedded-orange.svg) + +[English Documents](README.md) + +# mqttclient + +**一个高性能、高稳定性的跨平台MQTT客户端** + +一个高性能、高稳定性的跨平台MQTT客户端,基于socket API之上开发,可以在嵌入式设备(FreeRTOS/LiteOS/RT-Thread/TencentOS tiny)、Linux、Windows、Mac上使用,拥有非常简洁的API接口,以极少的资源实现QOS2的服务质量,并且无缝衔接了mbedtls加密库。 + +## 优势: + +- **具有极高的稳定性**:无论是**掉线重连**,**丢包重发**,都是**严格遵循MQTT协议标准**执行,除此之外对**大数据量**的测试无论是收是发,都是非常稳定,**高频**测试也是非常稳定。 + +- **轻量级**:整个代码工程极其简单,不使用mbedtls情况下,占用资源极少,作者曾使用esp8266模组与云端通信,整个工程代码消耗的RAM不足15k。 + +- **支持mbedtls加密传输**,让网络传输更加安全,而且接口层完全不需要用户理会,无论是否加密,mqttclient对用户提供的API接口是**固定**的,这就很好的兼容了一套代应用层的码可以加密传输也可以不加密传输。 + +- **支持多客户端**,同时兼容多个客户端运行工作,一个设备连接多个的服务器。 + +- **支持同步异步处理**,应用程序无需阻塞等待浪费CPU资源。 + +- **支持拦截器配置**,在某些平台中,客户端会默认自动订阅系统主题,而且每次来自服务器的主题都是变动的,此时需要使用拦截器进行拦截,分离主题与数据信息,并递交给用户,极大提高灵活性。 + +- **拥有在线代码生成工具**,极其简单配置就可以生成对应的代码,地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) + +- **拥有极简的API接口**,总的来说,mqttclient的配置都有默认值,基本无需配置都能使用的,也可以随意配置,对配置都有健壮性检测,这样子设计的API接口也是非常简单。 + +- **多功能参数可配置可裁剪**,重连时间间隔、心跳周期、最大订阅数量、命令超时、读写缓冲区大小、拦截器处理等等参数功能可裁剪可配置,满足开发者再复杂、简单等各种开发环境下的使用需求。 + +- **支持自动重新订阅主题**,在自动重连后保证主题不会丢失。 + +- **支持主题通配符`“#”、“+”`**。 + +- **订阅的主题与消息处理完全分离**,让编程逻辑更加简单易用,用户无需理会错综复杂的逻辑关系。 + +- **mqttclient内部已实现保活处理机制**,无需用户过多关心理会,用户只需专心处理应用功能即可。 + +- **拥有非常好的设计**,以极少的资源设计了**记录机制**,当报文在丢失的时候进行重发操作,确保qos1、qos2服务质量等级的报文保证其服务质量。 + +- **有非常好的代码风格与思想**:整个代码采用分层式设计,代码实现采用异步处理的思想,降低耦合,提高性能。 + +- **基于标准BSD socket之上开发**,只要是兼容BSD socket的系统均可使用。 + +- **无缝衔接salof**:它是一个同步异步日志输出框架,在空闲时候输出对应的日志信息,也可以将信息写入flash中保存,方便调试。 + +- **使用著名的 paho mqtt 库封包**。 + +- **无其他依赖**。 + +## 在线代码生成工具 + +本项目拥有代码生成工具,只需要在线配置即可生成代码,极其简单易用,代码生成工具地址:[https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) + +![在线代码生成工具](png/mqtt-tool.png) + +## 占用资源大小 + +总计占 **10857字节** 的ROM,而RAM的开销则几乎只依赖动态内存,在不使用TLS加密传输的情况下,维持QOS0服务质量等级的通信动态内存大约仅需要**3694**字节,这包括1024读缓冲区 + 1024写缓冲区 + 1024内部线程栈大小,相对于其他MQTT客户端来说,mqttclient需要的RAM资源开销极少。 + +| Code | RO Data | RW Data | ZI Data | Object Name | +| -- | -- | -- | -- | -- | +| 7118 | 791 | 0 | 0 | mqttclient.o | +| 546 | 0 | 0 | 0 | mqttconnectclient.o | +| 212 | 0 | 0 | 0 | mqttdeserializepublish.o | +| 476 | 0 | 4 | 0 | mqttpacket.o | +| 236 | 0 | 0 | 0 | mqttserializepublish.o | +| 310 | 0 | 0 | 0 | mqttsubscribeclient.o | +| 38 | 0 | 0 | 0 | mqttunsubscribeclient.o | +| 56 | 0 | 0 | 0 | nettype_tcp.o | +| 62 | 0 | 0 | 0 | network.o | +| 24 | 0 | 0 | 0 | platform_memory.o | +| 40 | 0 | 0 | 0 | platform_mutex.o | +| 344 | 0 | 0 | 0 | platform_net_socket.o | +| 94 | 0 | 0 | 0 | platform_thread.o | +| 70 | 0 | 0 | 0 | platform_timer.o | +| 246 | 0 | 4 | 0 | random.o | +| 62 | 0 | 0 | 0 | mqtt_list.o | +| - | - | - | - | - | +| 10066 | 791 | 8 | 0 | total | + +## 整体框架 + +拥有非常明确的分层框架。 + +![整体框架](png/mqttclient.png) + +- 在框架的最上方是**API**函数接口,实现了客户端的**申请、释放、设置参数、连接服务器、断开连接、订阅主题、取消订阅主题、发布消息**等函数接口。 + +- 使用了著名的**paho mqtt**库作为MQTT报文封包库。 + +- 采用异步处理的机制去管理所有的ack,它在发送报文的时候不用等待服务器的应答,只是记录下来,在收到服务器的ack后,取消这个记录,**效率极高**;而在发送mqtt报文(QoS1/QoS2)的时候没有收到服务器的应答时,将**重发**该报文。 + +- 内部实现了一个**mqtt yield**线程,统一处理所有的内容,比如**超时的处理、ack报文的处理、收到来自服务器的publish报文**,此时会去调用回调函数告知用户收到的数据,**发布释放、发布完成报文的处理、心跳报文(保持活性),当与服务器断开连接时需要尝试重连、重新订阅主题,重新发送报文或者应答**等。 + +- 报文的处理,如**读写报文、解码mqtt报文、设置报文(dup标记)、销毁报文**等操作。 + +- **network**是网络组件,它可以**自动选择数据通道**,如果是加密方式则通过**tls加密**进行数据传输,而tls可以选择mbedtls作为加密后端;也可以是**tcp直连**方式,最终都是通过tcp传输的。 + +- **platform**是平台抽象层,封装了不同系统的东西,比如**socke或者AT,线程、时间、互斥锁、内存管理**,这些是与系统打交道的,也是跨平台必要的封装。 + +- 最右边的则是通用的内容,**list的处理、日志库、错误处理、软件随机数发生器**等。 + +## 支持的平台 + +**目前已实现了Linux、TencentOS tiny、FreeRTOS、RT-Thread平台(已做成软件包,名字为`kawaii-mqtt`),除此之外TencentOS tiny的AT框架亦可以使用,并且稳定性极好!** + +| 平台 | 代码位置 | +| -------------- | -------- | +| Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) | +| TencentOS tiny | [https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429](https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429) | +| TencentOS tiny AT 框架 | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) | +| RT-Thread | [https://github.com/jiejieTop/kawaii-mqtt](https://github.com/jiejieTop/kawaii-mqtt) | +| FreeRTOS | [https://github.com/jiejieTop/freertos-mqttclient](https://github.com/jiejieTop/freertos-mqttclient) | + + +## 版本 + +| 发布版本 | 描述 | +| --- | --- | +| [v1.0.0] | 初次发布,完成基本框架及其稳定性验证 | +| [v1.0.1] | 修复主动与服务器断开连接时的逻辑处理 | +| [v1.0.2] | 添加新特性——拦截器,修复一些小bug | +| [v1.0.3] | 避免造成全局污染修改了log、list相关函数的命名 | +| [v1.0.4] | 重新调整了network结构与mbedtls数据通道 | +| [v1.1.0] | 一个较大版本的更新,重构部分代码,优化MQTT处理的逻辑,提升整体的稳定性,支持多客户端,支持设置遗嘱,优化API接口,增加多个云平台的测试代码与说明文档,增加在线代码生成工具、在线裁剪配置工具 | + +## 问题 + +欢迎以 [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues) 的形式提交问题和bug报告 + +## 版权和许可 + +mqttclient 遵循 [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) 开源协议。鼓励代码共享和尊重原作者的著作权,可以自由的使用、修改源代码,也可以将修改后的代码作为开源或闭源软件发布。 + +## linux平台下测试使用 + +### 安装cmake: + +```bash + sudo apt-get install cmake g++ +``` + +### 测试程序 + +| 测试平台 | 位置 | +| -- | -- | +| emqx(我私人部署的服务器) | [./test/emqx/test.c](./test/emqx/test.c) | +| 百度天工 | [./test/baidu/test.c](./test/baidu/test.c) | +| onenet | [./test/onenet/test.c](./test/onenet/test.c) | +| 阿里云物联 | [./test/ali/test.c](./test/ali/test.c) | + +### 编译 & 运行 + +```bash + ./build.sh +``` + +运行**build.sh**脚本后会在 **./build/bin/**目录下生成可执行文件**emqx**、**baidu**、**onenet**等多个平台的可执行程序,直接运行即可。 + +```bash + ./build/bin/emqx +``` + +### 编译成动态库libmqttclient.so + +```bash + ./make-libmqttclient.sh +``` + +运行`make-libmqttclient.sh`脚本后会在 `./libmqttclient/lib`目录下生成一个动态库文件`libmqttclient.so`,并安装到系统的`/usr/lib `目录下,相关头文件已经拷贝到`./libmqttclient/include`目录下,将其拷贝到你的工程中即可,编译应用程序的时候只需要链接动态库即可`-lmqttclient -lpthread`,动态库的配置文件是根据`./test/mqtt_config.h`配置的。 + +如果你是用交叉编译器的话,则应该根据你使用的编译器导出对应的环境变量(此处使用的交叉编译器是arm-linux-gnueabihf-gcc),同时你也必须将动态库文件`libmqttclient.so`拷贝到你的嵌入式系统的`/usr/lib `目录下: + +```bash + export CROSS_COMPILE=arm-linux-gnueabihf- +``` + +如若需要卸载**libmqttclient.so**,执行以下命令即可: + +```bash + ./make-libmqttclient.sh remove +``` + +## 学习更多 + +请看文档: + +- [MQTT协议简介](./docs/mqtt-introduction.md) + +- [MQTT协议通信过程](./docs/mqtt-communication.md) + +- [mqttclient代码生成工具](./docs/mqtt-tool.md) + +- [mqttclient配置及裁剪工具](./docs/mqtt-config.md) + +- [mqttclient设计与实现方式](./docs/mqtt-design.md) + +- [mqttclient连接到百度天工物接入](./docs/mqtt-baidu.md) + +- [mqttclient连接到OneNET云平台](./docs/mqtt-onenet.md) + +- [mqttclient连接到阿里云物联网平台](./docs/mqtt-aliyun.md) diff --git a/components/connectivity/mqttclient/README_EN.md b/components/connectivity/mqttclient/README_EN.md deleted file mode 100644 index cc18e21c..00000000 --- a/components/connectivity/mqttclient/README_EN.md +++ /dev/null @@ -1,209 +0,0 @@ -[![](https://img.shields.io/github/v/tag/jiejietop/mqttclient?color=brightgreen&label=version)](https://github.com/jiejieTop/mqttclient/releases) - -[![license](https://img.shields.io/badge/license-Apache-blue.svg)](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) - -![](https://img.shields.io/github/forks/jiejieTop/mqttclient) - -![](https://img.shields.io/github/stars/jiejieTop/mqttclient) - -![](https://img.shields.io/badge/platform-Linux|Windows|Mac|Embedded-orange.svg) - -[中文说明](README_CN.md) -# mqttclient - -**A high-performance, high-stability, cross-platform MQTT client** - -A high-performance, high-stability, cross-platform MQTT client, developed based on the socket API, can be used on embedded devices (FreeRTOS/LiteOS/RT-Thread/TencentOS tiny), Linux, Windows, Mac, and has a very concise The API interface realizes the quality of service of QOS2 with very few resources, and seamlessly connects the mbedtls encryption library. - -## Advantage: - -- **Extremely high stability**: Whether it is **drop and reconnect**, **packet loss and retransmission**, it is **strictly abide by the MQTT protocol standard**, in addition to The test of **large data volume** is very stable whether it is receiving or sending, and the **high frequency** test is also very stable. - -- **Lightweight**: The entire code project is extremely simple. Without mbedtls, it takes up very few resources. The author used the esp8266 module to communicate with the cloud. The entire project code consumes less than 15k of RAM. - -- **Support mbedtls encrypted transmission**, make the network transmission more secure, and the interface layer does not require users to care, no matter whether it is encrypted or not, mqttclient is **fixed** for the API interface provided by the user, which is very compatible A set of codes on behalf of the application layer can be transmitted with or without encryption. - -- **Supports multiple clients**, compatible with multiple clients running at the same time, one device connected to multiple servers. - -- **Supports synchronous and asynchronous processing**, applications need not block and wait to waste CPU resources. - -- **Support interceptor configuration**, on some platforms, the client will automatically subscribe to the system theme by default, and the theme from the server changes every time. In this case, you need to use an interceptor to intercept and separate the theme and data Information and deliver it to users, greatly improving flexibility. - -- **With online code generation tool**, the code can be generated with extremely simple configuration, address: [https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) - -- **Has a very simple API interface**, in general, mqttclient configuration has default values, basically can be used without configuration, can also be arbitrarily configured, the configuration has robustness detection, so designed The API interface is also very simple. - -- **Multifunctional parameters can be configured and tailored**, reconnect time interval, heartbeat period, maximum number of subscriptions, command timeout, read and write buffer size, interceptor processing, etc. Parameters can be tailored and configurable to meet the needs of developers Complex and simple to use in various development environments. - -- **Support automatic re-subscription of topics**, after automatic reconnection to ensure that the topics will not be lost. - -- **Support theme wildcards ""#", "+"`**. - -- **Subscribed topics are completely separated from message processing**, making programming logic easier and easier to use, users don’t have to deal with intricate logical relationships. - -- **The keep-alive processing mechanism has been implemented in mqttclient**, without the user having to deal with the psychological experience, the user only needs to concentrate on the application function. - -- **Has a very good design**, designed the **recording mechanism** with very few resources, and retransmits the message when it is lost to ensure that the qos1 and qos2 service quality levels guarantee its service quality. - -- **There are very good code styles and ideas**: The whole code adopts a layered design, and the code implementation adopts the idea of ​​asynchronous processing to reduce coupling and improve performance. - -- **Developed on top of standard BSD socket**, as long as it is compatible with BSD socket system. - -- **Seamless connection of salof**: It is a synchronous and asynchronous log output framework. It outputs the corresponding log information when it is idle, and it can also write the information into flash to save it, which is convenient for debugging. - -- **Use the famous paho mqtt library package**. - -- **No other dependencies**. - -## Online code generation tool - -This project has a code generation tool that only requires online configuration to generate code, which is extremely simple and easy to use. The code generation tool address is: [https://jiejietop.gitee.io/mqtt/index.html](https://jiejietop.gitee.io/mqtt/index.html) - -![Online code generation tool](png/mqtt-tool.png) - -## occupied resource size - -A total of **10857 bytes** of ROM, and the overhead of RAM is almost only dependent on dynamic memory. Without using TLS encrypted transmission, the communication dynamic memory that maintains the QOS0 quality of service level requires only about **3694** bytes. Including 1024 read buffer + 1024 write buffer + 1024 internal thread stack size, compared with other MQTT clients, mqttclient requires very little RAM resource overhead. - -| Code | RO Data | RW Data | ZI Data | Object Name | -| -- | -- | -- | -- | -- | -| 7118 | 791 | 0 | 0 | mqttclient.o | -| 546 | 0 | 0 | 0 | mqttconnectclient.o | -| 212 | 0 | 0 | 0 | mqttdeserializepublish.o | -| 476 | 0 | 4 | 0 | mqttpacket.o | -| 236 | 0 | 0 | 0 | mqttserializepublish.o | -| 310 | 0 | 0 | 0 | mqttsubscribeclient.o | -| 38 | 0 | 0 | 0 | mqttunsubscribeclient.o | -| 56 | 0 | 0 | 0 | nettype_tcp.o | -| 62 | 0 | 0 | 0 | network.o | -| 24 | 0 | 0 | 0 | platform_memory.o | -| 40 | 0 | 0 | 0 | platform_mutex.o | -| 344 | 0 | 0 | 0 | platform_net_socket.o | -| 94 | 0 | 0 | 0 | platform_thread.o | -| 70 | 0 | 0 | 0 | platform_timer.o | -| 246 | 0 | 4 | 0 | random.o | -| 62 | 0 | 0 | 0 | mqtt_list.o | -| - | - | - | - | - | -| 10066 | 791 | 8 | 0 | total | - -## Overall framework - -Has a very clear layered framework. - -![Overall Frame](png/mqttclient.png) - -- At the top of the framework is the **API** function interface, which implements the client's **application, release, set parameters, connect to the server, disconnect, subscribe topic, unsubscribe topic, publish message** and other functional interfaces. - -- The famous **paho mqtt** library is used as the MQTT message packet library. - -- Asynchronous processing mechanism is used to manage all the acks. It does not need to wait for the server's response when sending the message, but only records it. After receiving the server's ack, cancel this record, **very efficient**; and When the mqtt message (QoS1/QoS2) is sent and no response is received from the server, the message will be **retransmitted**. - -- An **mqtt yield** thread is implemented internally to handle all content in a unified manner, such as **timeout processing, ack message processing, and receiving publish message from the server**, at this time the callback function will be called Inform the user of the data received, **post release, post completion message processing, heartbeat message (keep alive), when disconnected from the server, you need to try to reconnect, resubscribe to the topic, resend the message or reply* *Wait. - -- Message processing, such as **reading and writing messages, decoding mqtt messages, setting messages (dup flag), destroying messages** and other operations. - -- **network** is a network component, which can **automatically select a data channel**, if it is an encryption method, **tls encryption** is used for data transmission, and tls can choose mbedtls as the encryption backend; it can also be The **tcp direct connection** method is ultimately transmitted via tcp. - -- **platform** is a platform abstraction layer that encapsulates things from different systems, such as socke or AT, thread, time, mutex, memory management**, these are dealing with the system and are also necessary for cross-platform Package. - -- On the far right is the general content, **list processing, log library, error handling, software random number generator**, etc. - -## Supported platforms - -**At present, Linux, TencentOS tiny, FreeRTOS, RT-Thread platforms have been implemented (software package is named kawaii-mqtt`), in addition to TencentOS tiny AT framework can also be used, and the stability is excellent!** - -| Platform | Code Location | -| -------------- | -------- | -| Linux | [https://github.com/jiejieTop/mqttclient](https://github.com/jiejieTop/mqttclient) | -| TencentOS tiny | [https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429](https://github.com/Tencent/TencentOS-tiny/tree/master/board/Fire_STM32F429) | -| TencentOS tiny AT framework | [https://github.com/jiejieTop/gokit3-board-mqttclient](https://github.com/jiejieTop/gokit3-board-mqttclient) | -| RT-Thread | [https://github.com/jiejieTop/kawaii-mqtt](https://github.com/jiejieTop/kawaii-mqtt) | -| FreeRTOS | [https://github.com/jiejieTop/freertos-mqttclient](https://github.com/jiejieTop/freertos-mqttclient) | - - -## Version - -| Release Version | Description | -| --- | --- | -| [v1.0.0] | Initial release, complete basic framework and stability verification | -| [v1.0.1] | Fix the logical processing when actively disconnecting from the server | -| [v1.0.2] | Add a new feature-interceptor, fix some small bugs | -| [v1.0.3] | To avoid global pollution, modify the naming of log and list related functions | -| [v1.0.4] | Network structure and mbedtls data channel readjusted | -| [v1.1.0] | A larger version of the update, refactoring part of the code, optimizing the logic of MQTT processing, improving the overall stability, supporting multiple clients, supporting setting the will, optimizing the API interface, and adding multiple cloud platforms Test code and documentation, add online code generation tool, online cutting configuration tool | -## question - -Welcome to submit issues and bug reports in the form of [GitHub Issues](https://github.com/jiejieTop/mqttclient/issues) - -## Copyright and License - -mqttclient follows the [Apache License v2.0](https://github.com/jiejieTop/mqttclient/blob/master/LICENSE) open source agreement. Encourage code sharing and respect the copyright of the original author. You can freely use and modify the source code, or you can publish the modified code as open source or closed source software. - -## Test and use under Linux platform - -### Install cmake: - -```bash - sudo apt-get install cmake g++ -``` - -### test program - -| Test Platform | Location | -| - | - | -| emqx (my privately deployed server) | [./test/emqx/test.c](./test/emqx/test.c) | -| Baidu Tiangong | [./test/baidu/test.c](./test/baidu/test.c) | -| onenet | [./test/onenet/test.c](./test/onenet/test.c) | -| Alibaba Cloud Internet of Things | [./test/ali/test.c](./test/ali/test.c) | - -### Compile & Run - -```bash - ./build.sh -``` - -After running the **build.sh** script, the executable files **emqx**, **baidu**, **onenet** and other platforms will be generated under the **./build/bin/** directory Executable programs can be run directly. - -```bash - ./build/bin/emqx -``` - -### Compile into a dynamic library libmqttclient.so - -```bash - ./make-libmqttclient.sh -``` - -After running the `make-libmqttclient.sh` script, a dynamic library file `libmqttclient.so` will be generated in the `./libmqttclient/lib` directory, and installed into the system’s `/usr/lib` directory, the relevant header files have been Copy to the `./libmqttclient/include` directory and copy it to your project. You only need to link the dynamic library when compiling the application. `-lmqttclient -lpthread`, the configuration file of the dynamic library is based on` ./test/mqtt_config.h` configuration. - -If you are using a cross-compiler, you should export the corresponding environment variables according to the compiler you are using (the cross-compiler used here is arm-linux-gnueabihf-gcc), and you must also set the dynamic library file `libmqttclient .so` is copied to the `/usr/lib` directory of your embedded system: - -```bash - export CROSS_COMPILE=arm-linux-gnueabihf- -``` - -If you need to uninstall **libmqttclient.so**, execute the following command: - -```bash - ./make-libmqttclient.sh remove -``` - -## Learn more - -Please see the documentation: - -- [MQTT Protocol Introduction](./docs/mqtt-introduction.md) - -- [MQTT protocol communication process](./docs/mqtt-communication.md) - -- [mqttclient code generation tool](./docs/mqtt-tool.md) - -- [mqttclient configuration and cutting tool](./docs/mqtt-config.md) - -- [mqttclient design and implementation](./docs/mqtt-design.md) - -- [mqttclient connects to Baidu Tiangongwu Access](./docs/mqtt-baidu.md) - -- [mqttclient connects to OneNET cloud platform](./docs/mqtt-onenet.md) - -- [mqttclient connects to Alibaba Cloud IoT platform](./docs/mqtt-aliyun.md) diff --git a/components/connectivity/mqttclient/common/mqtt_error.h b/components/connectivity/mqttclient/common/mqtt_error.h index 01ff7f46..b423f922 100644 --- a/components/connectivity/mqttclient/common/mqtt_error.h +++ b/components/connectivity/mqttclient/common/mqtt_error.h @@ -2,12 +2,16 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-15 00:42:16 - * @LastEditTime: 2020-04-27 23:35:05 + * @LastEditTime: 2020-10-17 14:16:15 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _MQTT_ERROR_H_ #define _MQTT_ERROR_H_ +#ifdef __cplusplus +extern "C" { +#endif + typedef enum mqtt_error { MQTT_SSL_CERT_ERROR = -0x001C, /* cetr parse failed */ MQTT_SOCKET_FAILED_ERROR = -0x001B, /* socket fd failed */ @@ -42,4 +46,8 @@ typedef enum mqtt_error { #define RETURN_ERROR(x) { return x; } +#ifdef __cplusplus +} +#endif + #endif diff --git a/components/connectivity/mqttclient/common/mqtt_list.h b/components/connectivity/mqttclient/common/mqtt_list.h index 58b528b2..b5eaee67 100644 --- a/components/connectivity/mqttclient/common/mqtt_list.h +++ b/components/connectivity/mqttclient/common/mqtt_list.h @@ -2,12 +2,16 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-11 22:47:55 - * @LastEditTime: 2020-04-27 23:25:37 + * @LastEditTime: 2020-10-17 14:18:02 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _MQTT_LIST_H_ #define _MQTT_LIST_H_ +#ifdef __cplusplus +extern "C" { +#endif + typedef struct mqtt_list_node { struct mqtt_list_node *next; struct mqtt_list_node *prev; @@ -58,5 +62,9 @@ void mqtt_list_move(mqtt_list_t *node, mqtt_list_t *list); void mqtt_list_move_tail(mqtt_list_t *node, mqtt_list_t *list); int mqtt_list_is_empty(mqtt_list_t *list); +#ifdef __cplusplus +} +#endif + #endif /* _LIST_H_ */ diff --git a/components/connectivity/mqttclient/common/mqtt_log.h b/components/connectivity/mqttclient/common/mqtt_log.h index be924321..d75a46da 100644 --- a/components/connectivity/mqttclient/common/mqtt_log.h +++ b/components/connectivity/mqttclient/common/mqtt_log.h @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-27 03:25:58 - * @LastEditTime: 2020-06-17 20:28:18 + * @LastEditTime: 2020-10-17 14:15:55 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _MQTT_LOG_H_ @@ -10,6 +10,10 @@ #include "mqtt_defconfig.h" +#ifdef __cplusplus +extern "C" { +#endif + #define MQTT_LOG_BASE_LEVEL (0) #define MQTT_LOG_ERR_LEVEL (MQTT_LOG_BASE_LEVEL + 1) #define MQTT_LOG_WARN_LEVEL (MQTT_LOG_ERR_LEVEL + 1) @@ -60,4 +64,8 @@ #define mqtt_log_init() #endif +#ifdef __cplusplus +} +#endif + #endif /* _LOG_H_ */ diff --git a/components/connectivity/mqttclient/common/random.h b/components/connectivity/mqttclient/common/random.h index 2ca09ab6..d8ad75a1 100644 --- a/components/connectivity/mqttclient/common/random.h +++ b/components/connectivity/mqttclient/common/random.h @@ -2,17 +2,25 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2020-01-09 19:59:19 - * @LastEditTime : 2020-01-10 08:52:45 + * @LastEditTime: 2020-10-17 14:18:15 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _RANDOM_H_ #define _RANDOM_H_ +#ifdef __cplusplus +extern "C" { +#endif + #define RANDOM_MAX 0x7FFFFFFF int random_number(void); int random_number_range(unsigned int min, unsigned int max); char *random_string(unsigned int len); +#ifdef __cplusplus +} +#endif + #endif /* _RANDOM_H_ */ diff --git a/components/connectivity/mqttclient/mqttclient/mqttclient.c b/components/connectivity/mqttclient/mqttclient/mqttclient.c index f4c82d52..5a214e9b 100644 --- a/components/connectivity/mqttclient/mqttclient/mqttclient.c +++ b/components/connectivity/mqttclient/mqttclient/mqttclient.c @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-09 21:31:25 - * @LastEditTime: 2020-06-16 17:34:37 + * @LastEditTime: 2021-01-14 10:00:12 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #include "mqttclient.h" @@ -154,7 +154,6 @@ static int mqtt_read_packet(mqtt_client_t* c, int* packet_type, platform_timer_t if (NULL == packet_type) RETURN_ERROR(MQTT_NULL_VALUE_ERROR); - platform_timer_init(timer); platform_timer_cutdown(timer, c->mqtt_cmd_timeout); /* 1. read the header byte. This has the packet type in it */ @@ -193,7 +192,6 @@ static int mqtt_send_packet(mqtt_client_t* c, int length, platform_timer_t* time int len = 0; int sent = 0; - platform_timer_init(timer); platform_timer_cutdown(timer, c->mqtt_cmd_timeout); /* send mqtt packet in a blocking manner or exit when it timer is expired */ @@ -304,7 +302,7 @@ static int mqtt_deliver_message(mqtt_client_t* c, MQTTString* topic_name, mqtt_m rc = MQTT_SUCCESS_ERROR; } - memset(message->payload, 0, strlen(message->payload)); + memset(message->payload, 0, strlen((const char *)message->payload)); memset(topic_name->lenstring.data, 0, topic_name->lenstring.len); RETURN_ERROR(rc); @@ -319,7 +317,7 @@ static ack_handlers_t *mqtt_ack_handler_create(mqtt_client_t* c, int type, uint1 return NULL; mqtt_list_init(&ack_handler->list); - platform_timer_init(&ack_handler->timer); + platform_timer_cutdown(&ack_handler->timer, c->mqtt_cmd_timeout); /* No response within timeout will be destroyed or resent */ ack_handler->type = type; @@ -343,7 +341,7 @@ static void mqtt_ack_handler_destroy(ack_handlers_t* ack_handler) static void mqtt_ack_handler_resend(mqtt_client_t* c, ack_handlers_t* ack_handler) { platform_timer_t timer; - platform_timer_init(&timer); + platform_timer_cutdown(&timer, c->mqtt_cmd_timeout); platform_timer_cutdown(&ack_handler->timer, c->mqtt_cmd_timeout); /* timeout, recutdown */ @@ -351,8 +349,9 @@ static void mqtt_ack_handler_resend(mqtt_client_t* c, ack_handlers_t* ack_handle memcpy(c->mqtt_write_buf, ack_handler->payload, ack_handler->payload_len); /* copy data to write buf form ack handler */ mqtt_send_packet(c, ack_handler->payload_len, &timer); /* resend data */ - MQTT_LOG_W("%s:%d %s()... resend %d package, packet_id is %d ", __FILE__, __LINE__, __FUNCTION__, ack_handler->type, ack_handler->packet_id); platform_mutex_unlock(&c->mqtt_write_lock); + MQTT_LOG_W("%s:%d %s()... resend %d package, packet_id is %d ", __FILE__, __LINE__, __FUNCTION__, ack_handler->type, ack_handler->packet_id); + } static int mqtt_ack_list_node_is_exist(mqtt_client_t* c, int type, uint16_t packet_id) @@ -495,15 +494,24 @@ static void mqtt_clean_session(mqtt_client_t* c) if (!(mqtt_list_is_empty(&c->mqtt_ack_handler_list))) { LIST_FOR_EACH_SAFE(curr, next, &c->mqtt_ack_handler_list) { ack_handler = LIST_ENTRY(curr, ack_handlers_t, list); + mqtt_list_del(&ack_handler->list); + //@lchnu, 2020-10-08, avoid socket disconnet when waiting for suback/unsuback.... + if(NULL != ack_handler->handler) { + mqtt_msg_handler_destory(ack_handler->handler); + ack_handler->handler = NULL; + } platform_memory_free(ack_handler); } mqtt_list_del_init(&c->mqtt_ack_handler_list); } + /* need clean mqtt_ack_handler_number value, find the bug by @lchnu */ + c->mqtt_ack_handler_number = 0; /* release all msg_handler_list memory */ if (!(mqtt_list_is_empty(&c->mqtt_msg_handler_list))) { LIST_FOR_EACH_SAFE(curr, next, &c->mqtt_msg_handler_list) { msg_handler = LIST_ENTRY(curr, message_handlers_t, list); + mqtt_list_del(&msg_handler->list); msg_handler->topic_filter = NULL; platform_memory_free(msg_handler); } @@ -538,9 +546,17 @@ static void mqtt_ack_list_scan(mqtt_client_t* c, uint8_t flag) /* timeout has occurred. for qos1 and qos2 packets, you need to resend them. */ mqtt_ack_handler_resend(c, ack_handler); continue; + } else if ((ack_handler->type == SUBACK) || (ack_handler->type == UNSUBACK)) { + + /*@lchnu, 2020-10-08, destory handler memory, if suback/unsuback is overdue!*/ + if (NULL != ack_handler->handler) { + mqtt_msg_handler_destory(ack_handler->handler); + ack_handler->handler = NULL; + } } /* if it is not a qos1 or qos2 message, it will be destroyed in every processing */ mqtt_ack_handler_destroy(ack_handler); + mqtt_subtract_ack_handler_num(c); /*@lchnu, 2020-10-08 */ } } @@ -589,14 +605,18 @@ static int mqtt_try_reconnect(mqtt_client_t* c) { int rc = MQTT_SUCCESS_ERROR; + /*before connect, call reconnect handler, it can used to update the mqtt password, eg: onenet platform need*/ + if (NULL != c->mqtt_reconnect_handler) { + c->mqtt_reconnect_handler(c, c->mqtt_reconnect_data); + } + rc = mqtt_try_do_reconnect(c); - if ((MQTT_SUCCESS_ERROR != rc) && (platform_timer_is_expired(&c->mqtt_reconnect_timer))) { - platform_timer_cutdown(&c->mqtt_reconnect_timer, c->mqtt_reconnect_try_duration); - if (NULL != c->mqtt_reconnect_handler) - c->mqtt_reconnect_handler(c, c->mqtt_reconnect_data); - RETURN_ERROR(MQTT_RECONNECT_TIMEOUT_ERROR); - } + if(MQTT_SUCCESS_ERROR != rc) { + /*connect fail must delay reconnect try duration time and let cpu time go out, the lowest priority task can run */ + mqtt_sleep_ms(c->mqtt_reconnect_try_duration); + RETURN_ERROR(MQTT_RECONNECT_TIMEOUT_ERROR); + } RETURN_ERROR(rc); } @@ -606,9 +626,7 @@ static int mqtt_publish_ack_packet(mqtt_client_t *c, uint16_t packet_id, int pac int len = 0; int rc = MQTT_SUCCESS_ERROR; platform_timer_t timer; - platform_timer_init(&timer); - platform_timer_cutdown(&timer, c->mqtt_cmd_timeout); - + platform_mutex_lock(&c->mqtt_write_lock); switch (packet_type) { @@ -796,7 +814,11 @@ static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer) rc = mqtt_read_packet(c, &packet_type, timer); switch (packet_type) { - case 0: /* timed out reading packet */ + case 0: /* timed out reading packet or an error occurred while reading data*/ + if (MQTT_BUFFER_TOO_SHORT_ERROR == rc) { + MQTT_LOG_E("the client read buffer is too short, please call mqtt_set_read_buf_size() to reset the buffer size"); + /* don't return directly, you need to stay active, because there is data readable now, but the buffer is too small */ + } break; case CONNACK: /* has been processed */ @@ -829,7 +851,7 @@ static int mqtt_packet_handle(mqtt_client_t* c, platform_timer_t* timer) break; default: - goto exit; + break; } rc = mqtt_keep_alive(c); @@ -866,7 +888,7 @@ static int mqtt_yield(mqtt_client_t* c, int timeout_ms) if (0 == timeout_ms) timeout_ms = c->mqtt_cmd_timeout; - platform_timer_init(&timer); + platform_timer_cutdown(&timer, timeout_ms); while (!platform_timer_is_expired(&timer)) { @@ -891,9 +913,6 @@ static int mqtt_yield(mqtt_client_t* c, int timeout_ms) } else if (MQTT_NOT_CONNECT_ERROR == rc) { MQTT_LOG_E("%s:%d %s()... mqtt not connect", __FILE__, __LINE__, __FUNCTION__); - - /* reconnect timer cutdown */ - platform_timer_cutdown(&c->mqtt_reconnect_timer, c->mqtt_reconnect_try_duration); } else { break; } @@ -907,7 +926,8 @@ static void mqtt_yield_thread(void *arg) int rc; client_state_t state; mqtt_client_t *c = (mqtt_client_t *)arg; - + platform_thread_t *thread_to_be_destoried = NULL; + state = mqtt_get_client_state(c); if (CLIENT_STATE_CONNECTED != state) { MQTT_LOG_W("%s:%d %s()..., mqtt is not connected to the server...", __FILE__, __LINE__, __FUNCTION__); @@ -917,17 +937,19 @@ static void mqtt_yield_thread(void *arg) while (1) { rc = mqtt_yield(c, c->mqtt_cmd_timeout); if (MQTT_CLEAN_SESSION_ERROR == rc) { - MQTT_LOG_E("%s:%d %s()..., mqtt clean session....", __FILE__, __LINE__, __FUNCTION__); + MQTT_LOG_W("%s:%d %s()..., mqtt clean session....", __FILE__, __LINE__, __FUNCTION__); network_disconnect(c->mqtt_network); mqtt_clean_session(c); goto exit; } else if (MQTT_RECONNECT_TIMEOUT_ERROR == rc) { - MQTT_LOG_E("%s:%d %s()..., mqtt reconnect timeout....", __FILE__, __LINE__, __FUNCTION__); + MQTT_LOG_W("%s:%d %s()..., mqtt reconnect timeout....", __FILE__, __LINE__, __FUNCTION__); } } exit: - platform_thread_destroy(c->mqtt_thread); + thread_to_be_destoried = c->mqtt_thread; + c->mqtt_thread = (platform_thread_t *)0; + platform_thread_destroy(thread_to_be_destoried); } static int mqtt_connect_with_results(mqtt_client_t* c) @@ -944,18 +966,7 @@ static int mqtt_connect_with_results(mqtt_client_t* c) if (CLIENT_STATE_CONNECTED == mqtt_get_client_state(c)) RETURN_ERROR(MQTT_SUCCESS_ERROR); - if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_read_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_read_buf_size)) - c->mqtt_read_buf_size = MQTT_DEFAULT_BUF_SIZE; - if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_write_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_write_buf_size)) - c->mqtt_write_buf_size = MQTT_DEFAULT_BUF_SIZE; - - c->mqtt_read_buf = (uint8_t*) platform_memory_alloc(c->mqtt_write_buf_size); - c->mqtt_write_buf = (uint8_t*) platform_memory_alloc(c->mqtt_write_buf_size); - - if ((NULL == c->mqtt_read_buf) || (NULL == c->mqtt_write_buf)) { - MQTT_LOG_E("%s:%d %s()... malloc buf failed...", __FILE__, __LINE__, __FUNCTION__); - RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR); - } + #ifndef MQTT_NETWORK_TYPE_NO_TLS rc = network_init(c->mqtt_network, c->mqtt_host, c->mqtt_port, c->mqtt_ca); @@ -967,8 +978,6 @@ static int mqtt_connect_with_results(mqtt_client_t* c) if (MQTT_SUCCESS_ERROR != rc) { if (NULL != c->mqtt_network) { network_release(c->mqtt_network); - platform_memory_free(c->mqtt_network); - c->mqtt_network = NULL; RETURN_ERROR(rc); } } @@ -998,7 +1007,6 @@ static int mqtt_connect_with_results(mqtt_client_t* c) if ((len = MQTTSerialize_connect(c->mqtt_write_buf, c->mqtt_write_buf_size, &connect_data)) <= 0) goto exit; - platform_timer_init(&connect_timer); platform_timer_cutdown(&connect_timer, c->mqtt_cmd_timeout); /* send connect packet */ @@ -1024,6 +1032,11 @@ exit: mqtt_set_client_state(c, CLIENT_STATE_CONNECTED); platform_thread_startup(c->mqtt_thread); platform_thread_start(c->mqtt_thread); /* start run mqtt thread */ + } else { + /*creat the thread fail and disconnect the mqtt socket connect*/ + network_release(c->mqtt_network); + rc = MQTT_CONNECT_FAILED_ERROR; + MQTT_LOG_W("%s:%d %s()... mqtt yield thread creat faile...", __FILE__, __LINE__, __FUNCTION__); } } else { mqtt_set_client_state(c, CLIENT_STATE_CONNECTED); /* reconnect, mqtt thread is already exists */ @@ -1032,6 +1045,7 @@ exit: c->mqtt_ping_outstanding = 0; /* reset ping outstanding */ } else { + network_release(c->mqtt_network); mqtt_set_client_state(c, CLIENT_STATE_INITIALIZED); /* connect failed */ } @@ -1040,6 +1054,50 @@ exit: RETURN_ERROR(rc); } +static uint32_t mqtt_read_buf_malloc(mqtt_client_t* c, uint32_t size) +{ + MQTT_ROBUSTNESS_CHECK(c, 0); + + if (NULL != c->mqtt_read_buf) + platform_memory_free(c->mqtt_read_buf); + + c->mqtt_read_buf_size = size; + + /* limit the size of the read buffer */ + if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_read_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_read_buf_size)) + c->mqtt_read_buf_size = MQTT_DEFAULT_BUF_SIZE; + + c->mqtt_read_buf = (uint8_t*) platform_memory_alloc(c->mqtt_read_buf_size); + + if (NULL == c->mqtt_read_buf) { + MQTT_LOG_E("%s:%d %s()... malloc read buf failed...", __FILE__, __LINE__, __FUNCTION__); + RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR); + } + return c->mqtt_read_buf_size; +} + +static uint32_t mqtt_write_buf_malloc(mqtt_client_t* c, uint32_t size) +{ + MQTT_ROBUSTNESS_CHECK(c, 0); + + if (NULL != c->mqtt_write_buf) + platform_memory_free(c->mqtt_write_buf); + + c->mqtt_write_buf_size = size; + + /* limit the size of the read buffer */ + if ((MQTT_MIN_PAYLOAD_SIZE >= c->mqtt_write_buf_size) || (MQTT_MAX_PAYLOAD_SIZE <= c->mqtt_write_buf_size)) + c->mqtt_write_buf_size = MQTT_DEFAULT_BUF_SIZE; + + c->mqtt_write_buf = (uint8_t*) platform_memory_alloc(c->mqtt_write_buf_size); + + if (NULL == c->mqtt_write_buf) { + MQTT_LOG_E("%s:%d %s()... malloc write buf failed...", __FILE__, __LINE__, __FUNCTION__); + RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR); + } + return c->mqtt_write_buf_size; +} + static int mqtt_init(mqtt_client_t* c) { /* network init */ @@ -1070,6 +1128,9 @@ static int mqtt_init(mqtt_client_t* c) c->mqtt_reconnect_data = NULL; c->mqtt_reconnect_handler = NULL; c->mqtt_interceptor_handler = NULL; + + mqtt_read_buf_malloc(c, MQTT_DEFAULT_BUF_SIZE); + mqtt_write_buf_malloc(c, MQTT_DEFAULT_BUF_SIZE); mqtt_list_init(&c->mqtt_msg_handler_list); mqtt_list_init(&c->mqtt_ack_handler_list); @@ -1077,7 +1138,6 @@ static int mqtt_init(mqtt_client_t* c) platform_mutex_init(&c->mqtt_write_lock); platform_mutex_init(&c->mqtt_global_lock); - platform_timer_init(&c->mqtt_reconnect_timer); platform_timer_init(&c->mqtt_last_sent); platform_timer_init(&c->mqtt_last_received); @@ -1098,12 +1158,20 @@ MQTT_CLIENT_SET_DEFINE(will_flag, uint32_t, 0) MQTT_CLIENT_SET_DEFINE(clean_session, uint32_t, 0) MQTT_CLIENT_SET_DEFINE(version, uint32_t, 0) MQTT_CLIENT_SET_DEFINE(cmd_timeout, uint32_t, 0) -MQTT_CLIENT_SET_DEFINE(read_buf_size, uint32_t, 0) -MQTT_CLIENT_SET_DEFINE(write_buf_size, uint32_t, 0) MQTT_CLIENT_SET_DEFINE(reconnect_try_duration, uint32_t, 0) MQTT_CLIENT_SET_DEFINE(reconnect_handler, reconnect_handler_t, NULL) MQTT_CLIENT_SET_DEFINE(interceptor_handler, interceptor_handler_t, NULL) +uint32_t mqtt_set_read_buf_size(mqtt_client_t *c, uint32_t size) +{ + return mqtt_read_buf_malloc(c, size); +} + +uint32_t mqtt_set_write_buf_size(mqtt_client_t *c, uint32_t size) +{ + return mqtt_write_buf_malloc(c, size); +} + void mqtt_sleep_ms(int ms) { platform_timer_usleep(ms * 1000); @@ -1120,6 +1188,9 @@ int mqtt_keep_alive(mqtt_client_t* c) if (platform_timer_is_expired(&c->mqtt_last_sent) || platform_timer_is_expired(&c->mqtt_last_received)) { if (c->mqtt_ping_outstanding) { MQTT_LOG_W("%s:%d %s()... ping outstanding", __FILE__, __LINE__, __FUNCTION__); + /*must realse the socket file descriptor zhaoshimin 20200629*/ + network_release(c->mqtt_network); + mqtt_set_client_state(c, CLIENT_STATE_DISCONNECTED); rc = MQTT_NOT_CONNECT_ERROR; /* PINGRESP not received in keepalive interval */ } else { @@ -1158,7 +1229,7 @@ int mqtt_release(mqtt_client_t* c) if (NULL == c) RETURN_ERROR(MQTT_NULL_VALUE_ERROR); - platform_timer_init(&timer); + platform_timer_cutdown(&timer, c->mqtt_cmd_timeout); /* wait for the clean session to complete */ @@ -1185,6 +1256,9 @@ int mqtt_release(mqtt_client_t* c) c->mqtt_write_buf = NULL; } + platform_mutex_destroy(&c->mqtt_write_lock); + platform_mutex_destroy(&c->mqtt_global_lock); + memset(c, 0, sizeof(mqtt_client_t)); RETURN_ERROR(MQTT_SUCCESS_ERROR); @@ -1202,7 +1276,7 @@ int mqtt_disconnect(mqtt_client_t* c) platform_timer_t timer; int len = 0; - platform_timer_init(&timer); + platform_timer_cutdown(&timer, c->mqtt_cmd_timeout); platform_mutex_lock(&c->mqtt_write_lock); @@ -1232,9 +1306,9 @@ int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, m if (CLIENT_STATE_CONNECTED != mqtt_get_client_state(c)) RETURN_ERROR(MQTT_NOT_CONNECT_ERROR); - platform_mutex_lock(&c->mqtt_write_lock); - packet_id = mqtt_get_next_packet_id(c); + + platform_mutex_lock(&c->mqtt_write_lock); /* serialize subscribe packet and send it */ len = MQTTSerialize_subscribe(c->mqtt_write_buf, c->mqtt_write_buf_size, 0, packet_id, 1, &topic, (int*)&qos); @@ -1249,8 +1323,10 @@ int mqtt_subscribe(mqtt_client_t* c, const char* topic_filter, mqtt_qos_t qos, m /* create a message and record it */ msg_handler = mqtt_msg_handler_create(topic_filter, qos, handler); - if (NULL == msg_handler) - RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR); + if (NULL == msg_handler) { + rc = MQTT_MEM_NOT_ENOUGH_ERROR; + goto exit; + } rc = mqtt_ack_list_record(c, SUBACK, packet_id, len, msg_handler); @@ -1274,20 +1350,22 @@ int mqtt_unsubscribe(mqtt_client_t* c, const char* topic_filter) if (CLIENT_STATE_CONNECTED != mqtt_get_client_state(c)) RETURN_ERROR(MQTT_NOT_CONNECT_ERROR); - platform_mutex_lock(&c->mqtt_write_lock); packet_id = mqtt_get_next_packet_id(c); + platform_mutex_lock(&c->mqtt_write_lock); /* serialize unsubscribe packet and send it */ if ((len = MQTTSerialize_unsubscribe(c->mqtt_write_buf, c->mqtt_write_buf_size, 0, packet_id, 1, &topic)) <= 0) goto exit; if ((rc = mqtt_send_packet(c, len, &timer)) != MQTT_SUCCESS_ERROR) goto exit; - /* create a message and record it */ - msg_handler = mqtt_msg_handler_create((const char*)topic_filter, QOS0, NULL); - if (NULL == msg_handler) - RETURN_ERROR(MQTT_MEM_NOT_ENOUGH_ERROR); + /* get a already subscribed message handler */ + msg_handler = mqtt_get_msg_handler(c, &topic); + if (NULL == msg_handler) { + rc = MQTT_MEM_NOT_ENOUGH_ERROR; + goto exit; + } rc = mqtt_ack_list_record(c, UNSUBACK, packet_id, len, msg_handler); @@ -1314,6 +1392,11 @@ int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg if ((NULL != msg->payload) && (0 == msg->payloadlen)) msg->payloadlen = strlen((char*)msg->payload); + if (msg->payloadlen > c->mqtt_write_buf_size) { + MQTT_LOG_E("publish payload len is is greater than client write buffer..."); + RETURN_ERROR(MQTT_BUFFER_TOO_SHORT_ERROR); + } + platform_mutex_lock(&c->mqtt_write_lock); if (QOS0 != msg->qos) { @@ -1334,7 +1417,7 @@ int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg goto exit; if (QOS0 != msg->qos) { - mqtt_set_publish_dup(c,1); /* may resend this data, set the udp flag in advance */ + mqtt_set_publish_dup(c,1); /* may resend this data, set the dup flag in advance */ if (QOS1 == msg->qos) { /* expect to receive PUBACK, otherwise data will be resent */ @@ -1348,12 +1431,15 @@ int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg exit: msg->payloadlen = 0; // clear - + platform_mutex_unlock(&c->mqtt_write_lock); if ((MQTT_ACK_HANDLER_NUM_TOO_MUCH_ERROR == rc) || (MQTT_MEM_NOT_ENOUGH_ERROR == rc)) { MQTT_LOG_W("%s:%d %s()... there is not enough memory space to record...", __FILE__, __LINE__, __FUNCTION__); + /*must realse the socket file descriptor zhaoshimin 20200629*/ + network_release(c->mqtt_network); + /* record too much retransmitted data, may be disconnected, need to reconnect */ mqtt_set_client_state(c, CLIENT_STATE_DISCONNECTED); } @@ -1391,7 +1477,7 @@ int mqtt_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t RETURN_ERROR(MQTT_NULL_VALUE_ERROR); if (NULL == c->mqtt_will_options) { - c->mqtt_will_options = platform_memory_alloc(sizeof(mqtt_will_options_t)); + c->mqtt_will_options = (mqtt_will_options_t *)platform_memory_alloc(sizeof(mqtt_will_options_t)); MQTT_ROBUSTNESS_CHECK(c->mqtt_will_options, MQTT_MEM_NOT_ENOUGH_ERROR); } diff --git a/components/connectivity/mqttclient/mqttclient/mqttclient.h b/components/connectivity/mqttclient/mqttclient/mqttclient.h index df66fcc7..31fd5f69 100644 --- a/components/connectivity/mqttclient/mqttclient/mqttclient.h +++ b/components/connectivity/mqttclient/mqttclient/mqttclient.h @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-09 21:31:25 - * @LastEditTime: 2020-06-16 16:57:40 + * @LastEditTime: 2020-10-17 14:16:58 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _MQTTCLIENT_H_ @@ -24,6 +24,10 @@ #include "mqtt_error.h" #include "mqtt_log.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef enum mqtt_qos { QOS0 = 0, QOS1 = 1, @@ -118,7 +122,6 @@ typedef struct mqtt_client { mqtt_list_t mqtt_ack_handler_list; network_t *mqtt_network; platform_thread_t *mqtt_thread; - platform_timer_t mqtt_reconnect_timer; platform_timer_t mqtt_last_sent; platform_timer_t mqtt_last_received; reconnect_handler_t mqtt_reconnect_handler; @@ -170,4 +173,8 @@ int mqtt_publish(mqtt_client_t* c, const char* topic_filter, mqtt_message_t* msg int mqtt_list_subscribe_topic(mqtt_client_t* c); int mqtt_set_will_options(mqtt_client_t* c, char *topic, mqtt_qos_t qos, uint8_t retained, char *message); +#ifdef __cplusplus +} +#endif + #endif /* _MQTTCLIENT_H_ */ diff --git a/components/connectivity/mqttclient/network/nettype_tcp.h b/components/connectivity/mqttclient/network/nettype_tcp.h index 502ae185..57661e9a 100644 --- a/components/connectivity/mqttclient/network/nettype_tcp.h +++ b/components/connectivity/mqttclient/network/nettype_tcp.h @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-15 13:39:00 - * @LastEditTime: 2020-05-24 15:49:46 + * @LastEditTime: 2020-10-17 14:17:10 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _NETTYPE_TCP_H_ @@ -12,9 +12,17 @@ #include "network.h" #include "mqtt_error.h" +#ifdef __cplusplus +extern "C" { +#endif + int nettype_tcp_read(network_t *n, unsigned char *buf, int len, int timeout); int nettype_tcp_write(network_t *n, unsigned char *buf, int len, int timeout); int nettype_tcp_connect(network_t* n); void nettype_tcp_disconnect(network_t* n); +#ifdef __cplusplus +} +#endif + #endif diff --git a/components/connectivity/mqttclient/network/nettype_tls.c b/components/connectivity/mqttclient/network/nettype_tls.c index f1381e49..1e407e86 100644 --- a/components/connectivity/mqttclient/network/nettype_tls.c +++ b/components/connectivity/mqttclient/network/nettype_tls.c @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2020-01-11 19:45:35 - * @LastEditTime: 2020-05-24 17:03:47 + * @LastEditTime: 2020-09-20 14:29:06 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #include "nettype_tls.h" @@ -207,7 +207,6 @@ int nettype_tls_write(network_t *n, unsigned char *buf, int len, int timeout) nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params; - platform_timer_init(&timer); platform_timer_cutdown(&timer, timeout); do { @@ -235,7 +234,6 @@ int nettype_tls_read(network_t *n, unsigned char *buf, int len, int timeout) nettype_tls_params_t *nettype_tls_params = (nettype_tls_params_t *) n->nettype_tls_params; - platform_timer_init(&timer); platform_timer_cutdown(&timer, timeout); do { diff --git a/components/connectivity/mqttclient/network/nettype_tls.h b/components/connectivity/mqttclient/network/nettype_tls.h index 2285197f..95fdf8e3 100644 --- a/components/connectivity/mqttclient/network/nettype_tls.h +++ b/components/connectivity/mqttclient/network/nettype_tls.h @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2020-01-11 19:45:44 - * @LastEditTime: 2020-05-24 17:03:13 + * @LastEditTime: 2020-10-17 14:14:11 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ @@ -16,6 +16,10 @@ #ifndef MQTT_NETWORK_TYPE_NO_TLS +#ifdef __cplusplus +extern "C" { +#endif + typedef struct nettype_tls_params { mbedtls_net_context socket_fd; /**< mbed TLS network context. */ mbedtls_entropy_context entropy; /**< mbed TLS entropy. */ @@ -36,4 +40,8 @@ void nettype_tls_disconnect(network_t* n); #endif /* MQTT_NETWORK_TYPE_NO_TLS */ +#ifdef __cplusplus +} +#endif + #endif diff --git a/components/connectivity/mqttclient/network/network.h b/components/connectivity/mqttclient/network/network.h index 11b11f9b..bae992ec 100644 --- a/components/connectivity/mqttclient/network/network.h +++ b/components/connectivity/mqttclient/network/network.h @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-09 21:31:02 - * @LastEditTime: 2020-05-21 01:09:29 + * @LastEditTime: 2020-10-17 14:14:41 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _NETWORK_H_ @@ -10,6 +10,10 @@ #include "mqtt_defconfig.h" +#ifdef __cplusplus +extern "C" { +#endif + #define NETWORK_CHANNEL_TCP 0 #define NETWORK_CHANNEL_TLS 1 @@ -36,4 +40,8 @@ int network_connect(network_t* n); void network_disconnect(network_t *n); void network_release(network_t* n); +#ifdef __cplusplus +} +#endif + #endif diff --git a/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.c b/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.c index e760e362..7b319c96 100644 --- a/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.c +++ b/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.c @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2020-01-10 23:45:59 - * @LastEditTime: 2020-04-25 17:54:44 + * @LastEditTime: 2020-06-18 20:13:02 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #include "platform_net_socket.h" diff --git a/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.h b/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.h index e6e082b8..b82c1ac3 100644 --- a/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.h +++ b/components/connectivity/mqttclient/platform/TencentOS-tiny/platform_net_socket.h @@ -2,7 +2,7 @@ * @Author: jiejie * @Github: https://github.com/jiejieTop * @Date: 2019-12-15 13:39:00 - * @LastEditTime: 2020-04-27 23:46:35 + * @LastEditTime: 2020-06-18 20:12:15 * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. */ #ifndef _PLATFORM_NET_SOCKET_H_ diff --git a/components/connectivity/mqttclient/test/test.c b/components/connectivity/mqttclient/test/test.c deleted file mode 100644 index 887d1117..00000000 --- a/components/connectivity/mqttclient/test/test.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * @Author: jiejie - * @Github: https://github.com/jiejieTop - * @Date: 2019-12-11 21:53:07 - * @LastEditTime: 2020-04-23 15:03:32 - * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. - */ -#include -#include -#include -#include -#include -#include "mqttclient.h" - -extern const char *test_ca_get(); - -mqtt_client_t client; -client_init_params_t init_params; - -static void topic1_handler(void* client, message_data_t* msg) -{ - (void) client; - LOG_I("-----------------------------------------------------------------------------------"); - LOG_I("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char*)msg->message->payload); - LOG_I("-----------------------------------------------------------------------------------"); -} - -void *mqtt_publish_thread(void *arg) -{ - char buf[100] = { 0 }; - mqtt_message_t msg; - memset(&msg, 0, sizeof(msg)); - sprintf(buf, "welcome to mqttclient, this is a publish test..."); - - sleep(2); - - mqtt_list_subscribe_topic(&client); - - msg.payload = (void *) buf; - - while(1) { - sprintf(buf, "welcome to mqttclient, this is a publish test, a rand number: %d ...", random_number()); - - msg.qos = 0; - mqtt_publish(&client, "topic1", &msg); - - msg.qos = 1; - mqtt_publish(&client, "topic2", &msg); - - msg.qos = 2; - mqtt_publish(&client, "topic3", &msg); - - sleep(4); - } -} - -int main(void) -{ - int res; - // pthread_t thread1; - pthread_t thread2; - - printf("\nwelcome to mqttclient test...\n"); - - log_init(); - - init_params.read_buf_size = 1024; - init_params.write_buf_size = 1024; - -#ifdef MQTT_NETWORK_TYPE_TLS - init_params.connect_params.network_params.network_ssl_params.ca_crt = test_ca_get(); - init_params.connect_params.network_params.port = "8883"; -#else - init_params.connect_params.network_params.port = "1883"; -#endif - init_params.connect_params.network_params.addr = "www.jiejie01.top"; //"47.95.164.112";//"jiejie01.top"; //"129.204.201.235"; //"192.168.1.101"; - - init_params.connect_params.user_name = random_string(10); // random_string(10); //"jiejietop-acer1"; - init_params.connect_params.password = random_string(10); //random_string(10); // "123456"; - init_params.connect_params.client_id = random_string(10); //random_string(10); // "clientid-acer1"; - init_params.connect_params.clean_session = 1; - - mqtt_init(&client, &init_params); - - mqtt_connect(&client); - - mqtt_subscribe(&client, "topic1", QOS0, topic1_handler); - mqtt_subscribe(&client, "topic2", QOS1, NULL); - mqtt_subscribe(&client, "topic3", QOS2, NULL); - - res = pthread_create(&thread2, NULL, mqtt_publish_thread, NULL); - if(res != 0) { - LOG_E("create mqtt publish thread fail"); - exit(res); - } - - while (1) { - sleep(100); - } -} diff --git a/components/connectivity/mqttclient/test/test_ca.c b/components/connectivity/mqttclient/test/test_ca.c deleted file mode 100644 index d102d75b..00000000 --- a/components/connectivity/mqttclient/test/test_ca.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * @Author: jiejie - * @Github: https://github.com/jiejieTop - * @Date: 2020-01-12 10:51:11 - * @LastEditTime: 2020-03-21 21:07:24 - * @Description: the code belongs to jiejie, please keep the author information and source code according to the license. - */ -static const char *test_ca_crt = { - "-----BEGIN CERTIFICATE-----\r\n" - "MIIFrTCCBJWgAwIBAgIQDApSGhCHMtFicAaXgcO0vjANBgkqhkiG9w0BAQsFADBy\r\n" - "MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg\r\n" - "SW5jLjEdMBsGA1UECxMURG9tYWluIFZhbGlkYXRlZCBTU0wxHTAbBgNVBAMTFFRy\r\n" - "dXN0QXNpYSBUTFMgUlNBIENBMB4XDTIwMDEyOTAwMDAwMFoXDTIxMDQyODEyMDAw\r\n" - "MFowGzEZMBcGA1UEAxMQd3d3LmppZWppZTAxLnRvcDCCASIwDQYJKoZIhvcNAQEB\r\n" - "BQADggEPADCCAQoCggEBAKIDMo45w085LaCMG1LWY5b8V94zDqdt+weVhKolgsLZ\r\n" - "htAQTDrafBx1sNJtOpa8ADeQkFbWOTEy3tgViOBvBr+8Qhl6vYsESJrg7DXeCVRm\r\n" - "04pk+cFrdWYRE70AUz8RXRuaWLv1Fu2L+qlymrnZB/WBJFnETINh6yzqY8FNETUV\r\n" - "EL08eE0LoXt/4b7iAJYEFRYTyBKjLpkr04e92SQIuL/l42j92lYNOjYfYOlpWZUC\r\n" - "cp4WHXEDd1YXdTMmXpfsU3VlYS3RTusOFsgXpLFET9xGRvtDSu5qw6rPGf/y/PhT\r\n" - "1LFB/xlL2E6Rpo/6VWuQ8A5rA+H3D1I/fIBB97orMYUCAwEAAaOCApQwggKQMB8G\r\n" - "A1UdIwQYMBaAFH/TmfOgRw4xAFZWIo63zJ7dygGKMB0GA1UdDgQWBBQyzyOTN1l5\r\n" - "Rg1Ih1tQ0TPYMqfw+jApBgNVHREEIjAgghB3d3cuamllamllMDEudG9wggxqaWVq\r\n" - "aWUwMS50b3AwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr\r\n" - "BgEFBQcDAjBMBgNVHSAERTBDMDcGCWCGSAGG/WwBAjAqMCgGCCsGAQUFBwIBFhxo\r\n" - "dHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECATCBkgYIKwYBBQUH\r\n" - "AQEEgYUwgYIwNAYIKwYBBQUHMAGGKGh0dHA6Ly9zdGF0dXNlLmRpZ2l0YWxjZXJ0\r\n" - "dmFsaWRhdGlvbi5jb20wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jYWNlcnRzLmRpZ2l0\r\n" - "YWxjZXJ0dmFsaWRhdGlvbi5jb20vVHJ1c3RBc2lhVExTUlNBQ0EuY3J0MAkGA1Ud\r\n" - "EwQCMAAwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdQB9PvL4j/+IVWgkwsDKnlKJ\r\n" - "eSvFDngJfy5ql2iZfiLw1wAAAW/wKSTgAAAEAwBGMEQCIGFq0FdvZfXf4lV20Am1\r\n" - "HRP6F7wxzkesK0r1566sNqvxAiBp5W3iTLWEgeJa/PfH5hX/d+K5CIyXScLa4qqa\r\n" - "MCLHwwB3AFzcQ5L+5qtFRLFemtRW5hA3+9X6R9yhc5SyXub2xw7KAAABb/ApJJIA\r\n" - "AAQDAEgwRgIhANEsjShyRf0GGpwJ6ZTQKBHo933rlSpaNIvor7cG8RBQAiEAkeDf\r\n" - "7+n+zyEGZUMOYI0E0R2chjPBJGvtw1yD12sxekowDQYJKoZIhvcNAQELBQADggEB\r\n" - "AIzaZ5X1So+xVe2JWkMfmJA8IQhdp9WghCDLRORcIggcY9BtYxFSBdusxIa1bhdt\r\n" - "rCY6RoepCwTrhV9PotwMgZtSOu8szHHRlqX8zNUhIh628yzPSTDDZ4xgeJvlGAkT\r\n" - "Zlv0XrezkDLRZkKN9R6KX1ccaPNbn9PD6SMtpHPbE7UEZYfrV3wAJhFzsyhp2JF4\r\n" - "KLLNPaeDgDM3Lu6tUm/bznDEyxi7/ZoR+7fSQAMF5Jo1ysKUAOC00I9Ne+7eSbTh\r\n" - "flV//8NBN+Z2ShCV0uFedf6ugDUMOuOUCtp0c7N+sM1IVE5MOhLRDAGRIUyi7/43\r\n" - "dJ0Okust1fXo4UTDGJtyp30=\r\n" - "-----END CERTIFICATE-----\r\n" - "-----BEGIN CERTIFICATE-----\r\n" - "MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh\r\n" - "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n" - "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\r\n" - "QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO\r\n" - "MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL\r\n" - "ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS\r\n" - "U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8\r\n" - "Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa\r\n" - "e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO\r\n" - "JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA\r\n" - "zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK\r\n" - "ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe\r\n" - "3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K\r\n" - "AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD\r\n" - "AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG\r\n" - "AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au\r\n" - "ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj\r\n" - "ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg\r\n" - "hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t\r\n" - "L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233\r\n" - "lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ\r\n" - "DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP\r\n" - "ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F\r\n" - "UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C\r\n" - "qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY\r\n" - "RmE=\r\n" - "-----END CERTIFICATE-----" -}; - -const char *test_ca_get() -{ - return test_ca_crt; -}