mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-20 00:27:19 +08:00
feat(mqtt): add APIs for mqtt ssl functionality
internal: 2c667eef
This commit is contained in:
7
VERSION
7
VERSION
@ -11,11 +11,12 @@ gwen:
|
||||
wps: ff84a8b
|
||||
|
||||
gitlab:
|
||||
driver: 7bee5263
|
||||
espconn: 3a998034
|
||||
freertos: a9985a9c
|
||||
lwip: 1651e055
|
||||
driver: 7bee5263
|
||||
mbedtls: 1ac9f1f4
|
||||
ssl: eefb383a
|
||||
mqtt: 6c098065
|
||||
nopoll: 31f0ea07
|
||||
openssl: 1669353f
|
||||
nopoll: 31f0ea07
|
||||
ssl: eefb383a
|
@ -1,12 +1,168 @@
|
||||
# Paho MQTT demo
|
||||
# ESP8266 MQTT Client Demo
|
||||
|
||||
This example shows how to use the Eclipse Paho MQTT as an example of ESP8266 RTOS SDK. In this demo, the following functions can be realized: MQTT publish, subscribe and ping.
|
||||
## 1. Introduction
|
||||
|
||||
1. Config SSID and PASSWORD of the Wi-Fi AP to be connected in user_config.h
|
||||
This MQTT demo is based on the Eclipse Paho MQTT library, and demonstrates a working MQTT client actions(subscribe, publish, ping). Using this MQTT demo, you can connect to the MQTT broker, subscribe to a topic and publish messages to the predefined topic.
|
||||
|
||||
2. Config MQTT Broker to be connected in MQTTEcho.c
|
||||
Also, this demo will ping the MQTT broker in the defined interval if no sending or receiving action happens. And we add some APIs to realize the SSL functionality, these SSL APIs provide the one-way certification and two-way certification.
|
||||
|
||||
3. Export SDK_PATH and BIN_PATH, run gen_misc.sh to compile, then download and run the demo
|
||||
## 2. Configuration
|
||||
|
||||
4. MQTT client will connect with the MQTT Broker, subscribe to the topic "ESP8266/sample/sub", and will publish messages
|
||||
to the topic "ESP8266/sample/pub"
|
||||
Some basic configurations need to be done before starting this demo and are listed in the include/user_config.h.
|
||||
|
||||
* Wi-Fi SSID & Password
|
||||
* MQTT Broker Address(can be a domain name) & MQTT Port
|
||||
>Note: There is a publically accessible sandbox server for the Eclipse IoT projects available at iot.eclipse.org, please get some reference information from the website: https://iot.eclipse.org/getting-started
|
||||
|
||||
## 3. Description
|
||||
|
||||
### 3.1 MQTT-Normal
|
||||
|
||||
This section describes the mqtt informations and API for MQTT client without SSL functionality.
|
||||
|
||||
#### 3.1.1 MQTT Info
|
||||
|
||||
For this MQTT demo, mqtt-related informations are defined in the mqtt_client_thread(), and they are listed below.
|
||||
|
||||
* two buffers(i.e. sendbuf[80] & readbuf[80]) to store packets to be sent and received
|
||||
* MQTTVersion, ClientID, KeepAliveInterval, etc are defined using **MQTTPacket_connectData_initializer**
|
||||
* Command_timeout is defined as 30s, and you can use this value as default
|
||||
* The subscribe topic is defined as "ESP8266/sample/sub"
|
||||
* The subscribe message handler is "void messageArrived(MessageData* data)"
|
||||
* The publish topic is defined as "ESP8266/sample/pub"
|
||||
* The published message's QoS type is QoS2
|
||||
|
||||
These informarions are only defined as a demonstration, you can change them appropriately according to your own requirements.
|
||||
|
||||
#### 3.1.2 Major API
|
||||
|
||||
1.Platform-Related
|
||||
|
||||
* NetworkInit(): used to initialize **Network** structure, which includes read/write functions, etc.
|
||||
* NetworkConnect(): used to create socket and connect to the MQTT broker
|
||||
|
||||
2.MQTT-Related
|
||||
|
||||
* MQTTClientInit(): used to initialize **MQTTClient** structure, which includes MQTT client information
|
||||
* MQTTStartTask(): a task used to perform MQTT **keep alive**
|
||||
* MQTTConnect(): used to perform MQTT connect
|
||||
* MQTTSubscribe(): used to subscribe to a topic
|
||||
* MQTTPublish(): used to publish messages to a topic
|
||||
|
||||
### 3.2 MQTT-SSL
|
||||
|
||||
This section describes the mqtt informations and API for MQTT client with SSL functionality enabled.
|
||||
|
||||
#### 3.2.1 MQTT Info
|
||||
|
||||
The aforementioned informations in the **MQTT Info** section of **MQTT-Normal** are also used for MQTT-SSL. As for SSL functionality, some more information will be needed and are listed below in the "Added-Info" section.
|
||||
|
||||
1.Existed-Info
|
||||
|
||||
This section is the same with the **MQTT Info** section of **MQTT-Normal**.
|
||||
|
||||
2.Added-Info
|
||||
|
||||
* May need header files of CA (and client certificate & key) included in the include/ directory
|
||||
* May need length of the CA (and client certificate & key) files
|
||||
* Need a **ssl_ca_crt_key_t** structure initialized using the CA (and client certificate & key) files
|
||||
|
||||
#### 3.2.2 Major API
|
||||
|
||||
When SSL is enabled, the Platform-related API are different with **MQTT-Normal** section.
|
||||
|
||||
1.Platform-related
|
||||
|
||||
* NetworkInitSSL(): used to initialize **Network** structure, which includes SSL read/write functions, etc.
|
||||
* NetworkConnectSSL(): used to create socket and connect to the MQTT broker with SSL enabled
|
||||
|
||||
2.MQTT-Related
|
||||
|
||||
This section is the same with the "MQTT-Related" section of "MQTT-Normal".
|
||||
|
||||
#### 3.2.3 SSL Special
|
||||
|
||||
For SSL functionality, three certification ways may be used: no certification, one-way certification and two-way certification. The specific configurations for each of them are described below:
|
||||
|
||||
1.No Certification
|
||||
|
||||
* No CA file and client certificate & key files need to be included
|
||||
* Define a **ssl_ca_crt_key_t** structure
|
||||
* Set the **cacrt**, **cert** and **key** parameters within the structure to be **NULL**
|
||||
* Recommend to set the **verify_mode** parameter to **SSL_VERIFY_NONE**
|
||||
* Set the **method** parameter to **TLSv1_1_client_method()** or **TLSv1_2_client_method()**
|
||||
* Set the **frag_len** parameter with a value between **2048** and **8192**
|
||||
|
||||
2.One-way Certification
|
||||
|
||||
* CA file shall be included, also length of the CA file shall be provided
|
||||
* Define a **ssl_ca_crt_key_t** structure
|
||||
* Set the **cacrt** parameter within the structure to the array in the CA file
|
||||
* Set the **cacrt_len** parameter to length of the CA file
|
||||
* Set the **verify_mode** parameter to **SSL_VERIFY_PEER**
|
||||
* Set the **method** parameter to **TLSv1_1_client_method()** or **TLSv1_2_client_method()**
|
||||
* Set the **frag_len** parameter with a value between **2048** and **8192**
|
||||
|
||||
3.Two-way Certification
|
||||
|
||||
* CA file and client certificate & key files shall be included
|
||||
* Also length of the CA file and client certificate & key files shall be provided
|
||||
* Define a **ssl_ca_crt_key_t** structure
|
||||
* Set the **cacrt** parameter within the structure to the array in the CA file
|
||||
* Set the **cacrt_len** parameter to length of the CA file
|
||||
* Set the **cert** parameter within the structure to the array in the client certificate file
|
||||
* Set the **cert_len** parameter to length of the client certificate file
|
||||
* Set the **key** parameter within the structure to the array in the client key file
|
||||
* Set the **key_len** parameter to length of the client key file
|
||||
* Set the **verify_mode** parameter to **SSL_VERIFY_PEER**
|
||||
* Set the **method** parameter to **TLSv1_1_client_method()** or **TLSv1_2_client_method()**
|
||||
* Set the **frag_len** parameter with a value between **2048** and **8192**
|
||||
|
||||
>Note: two-way certification is decided by the SSL Server side, so on the client side we just provide all the files needed by the two-way certification.
|
||||
|
||||
#### 3.2.4 SSL Demo
|
||||
|
||||
The following shows a simple demo of the MQTT client SSL functionality, and only the different places compared with MQTT-Normal demo are displayed. The names of CA file, client certificate & key files are just a demonstration, changing these properly according to your own files.
|
||||
|
||||
```c
|
||||
#include "openssl/ssl.h"
|
||||
#include "CA.h"
|
||||
#include "cert.h"
|
||||
#include "key.h"
|
||||
|
||||
ssl_ca_crt_key_t ssl_cck;
|
||||
|
||||
#define SSL_CA_CERT_KEY_INIT(s,a,b,c,d,e,f) ((ssl_ca_crt_key_t *)s)->cacrt = a;\
|
||||
((ssl_ca_crt_key_t *)s)->cacrt_len = b;\
|
||||
((ssl_ca_crt_key_t *)s)->cert = c;\
|
||||
((ssl_ca_crt_key_t *)s)->cert_len = d;\
|
||||
((ssl_ca_crt_key_t *)s)->key = e;\
|
||||
((ssl_ca_crt_key_t *)s)->key_len = f;
|
||||
|
||||
static void mqtt_client_thread(void *pvParameters)
|
||||
{
|
||||
......
|
||||
NetworkInitSSL(&network);
|
||||
......
|
||||
SSL_CA_CERT_KEY_INIT(&ssl_cck, ca_crt, ca_crt_len, client_crt, client_crt_len, client_key, client_key_len);
|
||||
|
||||
if ((rc = NetworkConnectSSL(&network, address, MQTT_PORT, &ssl_cck, TLSv1_1_client_method(), SSL_VERIFY_NONE, 8192)) != 1) {
|
||||
printf("Return code from network connect ssl is %d\n", rc);
|
||||
}
|
||||
......
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Compiling & Execution
|
||||
|
||||
Once all the aforementioned works are done, we can compile and download the MQTT client (SSL) demo, and a few more steps will be needed.
|
||||
|
||||
* Export SDK_PATH & BIN_PATH, and run gen_misc.sh to compile and generate binary files
|
||||
* Download the binary files to flash and run, also you can use UART console to watch the output log
|
||||
|
||||
All these being done, the MQTT client demo will:
|
||||
|
||||
* Connect to the MQTT Broker
|
||||
* Subscribe to the topic "ESP8266/sample/sub"
|
||||
* Publish messages to the topic "ESP8266/sample/pub" every 1 seconds
|
||||
* MQTT keep alive interval is 60s, so if no sending and receiving actions happended during this interval, ping request will be sent and ping response is expected to be received.
|
@ -25,8 +25,11 @@
|
||||
#ifndef __USER_CONFIG_H__
|
||||
#define __USER_CONFIG_H__
|
||||
|
||||
#define SSID "TEST001"
|
||||
#define PASSWORD "1234567890"
|
||||
#define SSID "espressif" /* Wi-Fi SSID */
|
||||
#define PASSWORD "1234567890" /* Wi-Fi Password */
|
||||
|
||||
#define MQTT_BROKER "iot.eclipse.org" /* MQTT Broker Address*/
|
||||
#define MQTT_PORT 1883 /* MQTT Port*/
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,106 +1,118 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "mqtt/MQTTClient.h"
|
||||
|
||||
#define MQTT_CLIENT_THREAD_NAME "mqtt_client_thread"
|
||||
#define MQTT_CLIENT_THREAD_STACK_WORDS 2048
|
||||
#define MQTT_CLIENT_THREAD_PRIO 8
|
||||
LOCAL xTaskHandle mqttc_client_handle;
|
||||
|
||||
#define MQTT_BROKER "192.168.1.100" /* Address of the MQTT Broker to be connected*/
|
||||
|
||||
void messageArrived(MessageData* data)
|
||||
{
|
||||
printf("Message arrived: %s\n", data->message->payload);
|
||||
}
|
||||
|
||||
static void mqtt_client_thread(void *pvParameters)
|
||||
{
|
||||
printf("mqtt client thread starts\n");
|
||||
MQTTClient client;
|
||||
Network network;
|
||||
unsigned char sendbuf[80], readbuf[80] = {0};
|
||||
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 = MQTT_BROKER;
|
||||
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);
|
||||
else
|
||||
printf("Use MQTTStartTask\n");
|
||||
#endif
|
||||
|
||||
connectData.MQTTVersion = 3;
|
||||
connectData.clientID.cstring = "ESP8266_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, "ESP8266/sample/sub", 2, messageArrived)) != 0)
|
||||
printf("Return code from MQTT subscribe is %d\n", rc);
|
||||
else
|
||||
printf("MQTT subscribe to topic \"ESP8266/sample/sub\"\n");
|
||||
|
||||
while (++count) {
|
||||
MQTTMessage message;
|
||||
char payload[30];
|
||||
|
||||
message.qos = QOS2;
|
||||
message.retained = 0;
|
||||
message.payload = payload;
|
||||
sprintf(payload, "message number %d", count);
|
||||
message.payloadlen = strlen(payload);
|
||||
|
||||
if ((rc = MQTTPublish(&client, "ESP8266/sample/pub", &message)) != 0)
|
||||
printf("Return code from MQTT publish is %d\n", rc);
|
||||
else
|
||||
printf("MQTT publish topic \"ESP8266/sample/pub\", message number is %d\n", count);
|
||||
|
||||
vTaskDelay(100000 / portTICK_RATE_MS); //send every 100 seconds
|
||||
}
|
||||
|
||||
printf("mqtt_client_thread going to be deleted\n");
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void user_conn_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = xTaskCreate(mqtt_client_thread,
|
||||
MQTT_CLIENT_THREAD_NAME,
|
||||
MQTT_CLIENT_THREAD_STACK_WORDS,
|
||||
NULL,
|
||||
MQTT_CLIENT_THREAD_PRIO,
|
||||
&mqttc_client_handle);
|
||||
if (ret != pdPASS) {
|
||||
printf("mqtt create client thread %s failed\n", MQTT_CLIENT_THREAD_NAME);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "mqtt/MQTTClient.h"
|
||||
|
||||
#include "user_config.h"
|
||||
|
||||
#define MQTT_CLIENT_THREAD_NAME "mqtt_client_thread"
|
||||
#define MQTT_CLIENT_THREAD_STACK_WORDS 2048
|
||||
#define MQTT_CLIENT_THREAD_PRIO 8
|
||||
|
||||
LOCAL xTaskHandle mqttc_client_handle;
|
||||
|
||||
static void messageArrived(MessageData* data)
|
||||
{
|
||||
printf("Message arrived: %s\n", data->message->payload);
|
||||
}
|
||||
|
||||
static void mqtt_client_thread(void* pvParameters)
|
||||
{
|
||||
printf("mqtt client thread starts\n");
|
||||
MQTTClient client;
|
||||
Network network;
|
||||
unsigned char sendbuf[80], readbuf[80] = {0};
|
||||
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 = MQTT_BROKER;
|
||||
|
||||
if ((rc = NetworkConnect(&network, address, MQTT_PORT)) != 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);
|
||||
} else {
|
||||
printf("Use MQTTStartTask\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
connectData.MQTTVersion = 3;
|
||||
connectData.clientID.cstring = "ESP8266_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, "ESP8266/sample/sub", 2, messageArrived)) != 0) {
|
||||
printf("Return code from MQTT subscribe is %d\n", rc);
|
||||
} else {
|
||||
printf("MQTT subscribe to topic \"ESP8266/sample/sub\"\n");
|
||||
}
|
||||
|
||||
while (++count) {
|
||||
MQTTMessage message;
|
||||
char payload[30];
|
||||
|
||||
message.qos = QOS2;
|
||||
message.retained = 0;
|
||||
message.payload = payload;
|
||||
sprintf(payload, "message number %d", count);
|
||||
message.payloadlen = strlen(payload);
|
||||
|
||||
if ((rc = MQTTPublish(&client, "ESP8266/sample/pub", &message)) != 0) {
|
||||
printf("Return code from MQTT publish is %d\n", rc);
|
||||
} else {
|
||||
printf("MQTT publish topic \"ESP8266/sample/pub\", message number is %d\n", count);
|
||||
}
|
||||
|
||||
vTaskDelay(1000 / portTICK_RATE_MS); //send every 1 seconds
|
||||
}
|
||||
|
||||
printf("mqtt_client_thread going to be deleted\n");
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void user_conn_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = xTaskCreate(mqtt_client_thread,
|
||||
MQTT_CLIENT_THREAD_NAME,
|
||||
MQTT_CLIENT_THREAD_STACK_WORDS,
|
||||
NULL,
|
||||
MQTT_CLIENT_THREAD_PRIO,
|
||||
&mqttc_client_handle);
|
||||
|
||||
if (ret != pdPASS) {
|
||||
printf("mqtt create client thread %s failed\n", MQTT_CLIENT_THREAD_NAME);
|
||||
}
|
||||
}
|
||||
|
@ -21,20 +21,24 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
typedef struct Timer
|
||||
{
|
||||
portTickType xTicksToWait;
|
||||
xTimeOutType xTimeOut;
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
typedef struct Timer {
|
||||
portTickType xTicksToWait;
|
||||
xTimeOutType xTimeOut;
|
||||
} Timer;
|
||||
|
||||
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*);
|
||||
struct Network {
|
||||
int my_socket;
|
||||
int (*mqttread)(Network*, unsigned char*, unsigned int, unsigned int);
|
||||
int (*mqttwrite)(Network*, unsigned char*, unsigned int, unsigned int);
|
||||
void (*disconnect)(Network*);
|
||||
|
||||
int read_count;
|
||||
SSL_CTX* ctx;
|
||||
SSL* ssl;
|
||||
};
|
||||
|
||||
void TimerInit(Timer*);
|
||||
@ -43,28 +47,73 @@ void TimerCountdownMS(Timer*, unsigned int);
|
||||
void TimerCountdown(Timer*, unsigned int);
|
||||
int TimerLeftMS(Timer*);
|
||||
|
||||
typedef struct Mutex
|
||||
{
|
||||
xSemaphoreHandle sem;
|
||||
typedef struct Mutex {
|
||||
xSemaphoreHandle sem;
|
||||
} Mutex;
|
||||
|
||||
void MutexInit(Mutex*);
|
||||
int MutexLock(Mutex*);
|
||||
int MutexUnlock(Mutex*);
|
||||
|
||||
typedef struct Thread
|
||||
{
|
||||
xTaskHandle task;
|
||||
typedef struct Thread {
|
||||
xTaskHandle task;
|
||||
} Thread;
|
||||
|
||||
int ThreadStart(Thread*, void (*fn)(void*), void* arg);
|
||||
|
||||
int esp_read(Network*, unsigned char*, int, int);
|
||||
int esp_write(Network*, unsigned char*, int, int);
|
||||
void esp_disconnect(Network*);
|
||||
|
||||
/**
|
||||
* @brief Initialize the network structure
|
||||
*
|
||||
* @param m - network structure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void NetworkInit(Network*);
|
||||
int NetworkConnect(Network*, char*, int);
|
||||
|
||||
/**
|
||||
* @brief connect with mqtt broker
|
||||
*
|
||||
* @param n - mqtt network struct
|
||||
* @param addr - mqtt broker address
|
||||
* @param port - mqtt broker port
|
||||
*
|
||||
* @return connect status
|
||||
*/
|
||||
int NetworkConnect(Network* n, char* addr, int port);
|
||||
|
||||
typedef struct ssl_ca_crt_key {
|
||||
unsigned char* cacrt;
|
||||
unsigned int cacrt_len;
|
||||
unsigned char* cert;
|
||||
unsigned int cert_len;
|
||||
unsigned char* key;
|
||||
unsigned int key_len;
|
||||
} ssl_ca_crt_key_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the network structure for SSL connection
|
||||
*
|
||||
* @param m - network structure
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void NetworkInitSSL(Network* n);
|
||||
|
||||
/**
|
||||
* @brief Use SSL to connect with mqtt broker
|
||||
*
|
||||
* @param n - mqtt network struct
|
||||
* @param addr - mqtt broker address
|
||||
* @param port - mqtt broker port
|
||||
* @param ssl_cck - client CA, certificate and private key
|
||||
* @param method - SSL context client method
|
||||
* @param verify_mode - SSL verifying mode
|
||||
* @param frag_len - SSL read buffer length
|
||||
*
|
||||
* @return connect status
|
||||
*/
|
||||
int NetworkConnectSSL(Network* n, char* addr, int port, ssl_ca_crt_key_t* ssl_cck, const SSL_METHOD* method, int verify_mode, unsigned int frag_len);
|
||||
|
||||
/*int NetworkConnectTLS(Network*, char*, int, SlSockSecureFiles_t*, unsigned char, unsigned int, char);*/
|
||||
|
||||
#endif
|
||||
|
BIN
lib/libmqtt.a
BIN
lib/libmqtt.a
Binary file not shown.
308
third_party/mqtt/platform/MQTTFreeRTOS.c
vendored
308
third_party/mqtt/platform/MQTTFreeRTOS.c
vendored
@ -15,8 +15,9 @@
|
||||
* Ian Craggs - convert to FreeRTOS
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTFreeRTOS.h"
|
||||
#include "lwip/netdb.h"
|
||||
#include "openssl/ssl.h"
|
||||
#include "MQTTFreeRTOS.h"
|
||||
|
||||
int ThreadStart(Thread* thread, void (*fn)(void*), void* arg)
|
||||
{
|
||||
@ -25,11 +26,11 @@ int ThreadStart(Thread* thread, void (*fn)(void*), void* arg)
|
||||
unsigned portBASE_TYPE 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. */
|
||||
"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;
|
||||
}
|
||||
@ -40,17 +41,18 @@ void MutexInit(Mutex* mutex)
|
||||
mutex->sem = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
|
||||
int MutexLock(Mutex* mutex)
|
||||
{
|
||||
return xSemaphoreTake(mutex->sem, portMAX_DELAY);
|
||||
}
|
||||
|
||||
|
||||
int MutexUnlock(Mutex* mutex)
|
||||
{
|
||||
return xSemaphoreGive(mutex->sem);
|
||||
}
|
||||
|
||||
|
||||
void TimerCountdownMS(Timer* timer, unsigned int timeout_ms)
|
||||
{
|
||||
timer->xTicksToWait = timeout_ms / portTICK_RATE_MS; /* convert milliseconds to ticks */
|
||||
@ -58,13 +60,13 @@ void TimerCountdownMS(Timer* timer, unsigned int timeout_ms)
|
||||
}
|
||||
|
||||
|
||||
void TimerCountdown(Timer* timer, unsigned int timeout)
|
||||
void TimerCountdown(Timer* timer, unsigned int timeout)
|
||||
{
|
||||
TimerCountdownMS(timer, timeout * 1000);
|
||||
}
|
||||
|
||||
|
||||
int TimerLeftMS(Timer* timer)
|
||||
int TimerLeftMS(Timer* timer)
|
||||
{
|
||||
xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait); /* updates xTicksToWait to the number left */
|
||||
return (timer->xTicksToWait < 0) ? 0 : (timer->xTicksToWait * portTICK_RATE_MS);
|
||||
@ -84,7 +86,7 @@ void TimerInit(Timer* timer)
|
||||
}
|
||||
|
||||
|
||||
int esp_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
|
||||
static int esp_read(Network* n, unsigned char* buffer, unsigned int len, unsigned int timeout_ms)
|
||||
{
|
||||
portTickType xTicksToWait = timeout_ms / portTICK_RATE_MS; /* convert milliseconds to ticks */
|
||||
xTimeOutType xTimeOut;
|
||||
@ -102,10 +104,12 @@ int esp_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
|
||||
timeout.tv_usec = timeout_ms * 1000;
|
||||
|
||||
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
|
||||
|
||||
if (select(n->my_socket + 1, &fdset, NULL, NULL, &timeout) > 0) {
|
||||
if (FD_ISSET(n->my_socket, &fdset)) {
|
||||
do {
|
||||
rc = recv(n->my_socket, buffer + recvLen, len - recvLen, MSG_DONTWAIT);
|
||||
|
||||
if (rc > 0) {
|
||||
recvLen += rc;
|
||||
} else if (rc < 0) {
|
||||
@ -115,11 +119,12 @@ int esp_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
|
||||
} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return recvLen;
|
||||
}
|
||||
|
||||
|
||||
int esp_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
|
||||
static int esp_write(Network* n, unsigned char* buffer, unsigned int len, unsigned int timeout_ms)
|
||||
{
|
||||
portTickType xTicksToWait = timeout_ms / portTICK_RATE_MS; /* convert milliseconds to ticks */
|
||||
xTimeOutType xTimeOut;
|
||||
@ -138,12 +143,15 @@ int esp_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
|
||||
timeout.tv_usec = timeout_ms * 1000;
|
||||
|
||||
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
|
||||
|
||||
do {
|
||||
readysock = select(n->my_socket + 1, NULL, &fdset, NULL, &timeout);
|
||||
} while (readysock <= 0);
|
||||
|
||||
if (FD_ISSET(n->my_socket, &fdset)) {
|
||||
do {
|
||||
rc = send(n->my_socket, buffer + sentLen, len - sentLen, MSG_DONTWAIT);
|
||||
|
||||
if (rc > 0) {
|
||||
sentLen += rc;
|
||||
} else if (rc < 0) {
|
||||
@ -157,7 +165,7 @@ int esp_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
|
||||
}
|
||||
|
||||
|
||||
void esp_disconnect(Network* n)
|
||||
static void esp_disconnect(Network* n)
|
||||
{
|
||||
close(n->my_socket);
|
||||
}
|
||||
@ -176,20 +184,21 @@ int NetworkConnect(Network* n, char* addr, int port)
|
||||
{
|
||||
struct sockaddr_in sAddr;
|
||||
int retVal = -1;
|
||||
struct hostent *ipAddress;
|
||||
struct hostent* ipAddress;
|
||||
|
||||
if ((ipAddress = gethostbyname(addr)) == 0)
|
||||
if ((ipAddress = gethostbyname(addr)) == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sAddr.sin_family = AF_INET;
|
||||
sAddr.sin_addr.s_addr = ((struct in_addr*)(ipAddress->h_addr))->s_addr;
|
||||
sAddr.sin_port = htons(port);
|
||||
|
||||
if ((n->my_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
if ((n->my_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0)
|
||||
{
|
||||
if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0) {
|
||||
close(n->my_socket);
|
||||
goto exit;
|
||||
}
|
||||
@ -199,64 +208,239 @@ exit:
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int NetworkConnectTLS(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify)
|
||||
static int esp_ssl_read(Network* n, unsigned char* buffer, unsigned int len, unsigned int timeout_ms)
|
||||
{
|
||||
SlSockAddrIn_t sAddr;
|
||||
int addrSize;
|
||||
int retVal;
|
||||
unsigned long ipAddress;
|
||||
portTickType xTicksToWait = timeout_ms / portTICK_RATE_MS; /* convert milliseconds to ticks */
|
||||
xTimeOutType xTimeOut;
|
||||
int recvLen = 0;
|
||||
int rc = 0;
|
||||
static unsigned char* read_buffer;
|
||||
|
||||
retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET);
|
||||
if (retVal < 0) {
|
||||
return -1;
|
||||
struct timeval timeout;
|
||||
fd_set readset;
|
||||
fd_set errset;
|
||||
|
||||
FD_ZERO(&readset);
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(n->my_socket, &readset);
|
||||
FD_SET(n->my_socket, &errset);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = timeout_ms * 1000;
|
||||
|
||||
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
|
||||
|
||||
if (!n->read_count) { /* read mqtt packet for the first time */
|
||||
if (select(n->my_socket + 1, &readset, NULL, &errset, &timeout) > 0) {
|
||||
if (FD_ISSET(n->my_socket, &errset)) {
|
||||
return recvLen;
|
||||
} else if (FD_ISSET(n->my_socket, &readset)) {
|
||||
read_buffer = buffer;
|
||||
len = 2; /* len: msg_type(1 octet) + msg_len(1 octet) */
|
||||
|
||||
do {
|
||||
rc = SSL_read(n->ssl, read_buffer, len);
|
||||
|
||||
if (rc > 0) {
|
||||
recvLen += rc;
|
||||
} else if (rc < 0) {
|
||||
recvLen = rc;
|
||||
return recvLen;
|
||||
}
|
||||
} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
|
||||
|
||||
recvLen = 0;
|
||||
len = *(read_buffer + 1); /* len: remaining msg */
|
||||
|
||||
if (len > 0) {
|
||||
do {
|
||||
rc = SSL_read(n->ssl, read_buffer + 2, len);
|
||||
|
||||
if (rc > 0) {
|
||||
recvLen += rc;
|
||||
} else if (rc < 0) {
|
||||
recvLen = rc;
|
||||
return recvLen;
|
||||
}
|
||||
} while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
|
||||
}
|
||||
|
||||
n->read_count++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (n->read_count == 1) { /* read same mqtt packet for the second time */
|
||||
if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdTRUE) {
|
||||
n->read_count = 0;
|
||||
read_buffer[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n->read_count++;
|
||||
*buffer = *(read_buffer + 1);
|
||||
return 1;
|
||||
} else if (n->read_count == 2) { /* read same mqtt packet for the third time */
|
||||
n->read_count = 0;
|
||||
|
||||
if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdTRUE) {
|
||||
read_buffer[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer, read_buffer + 2, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
return recvLen;
|
||||
}
|
||||
|
||||
|
||||
static int esp_ssl_write(Network* n, unsigned char* buffer, unsigned int len, unsigned int timeout_ms)
|
||||
{
|
||||
portTickType xTicksToWait = timeout_ms / portTICK_RATE_MS; /* convert milliseconds to ticks */
|
||||
xTimeOutType xTimeOut;
|
||||
int sentLen = 0;
|
||||
int rc = 0;
|
||||
int readysock;
|
||||
|
||||
struct timeval timeout;
|
||||
fd_set writeset;
|
||||
fd_set errset;
|
||||
|
||||
FD_ZERO(&writeset);
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(n->my_socket, &writeset);
|
||||
FD_SET(n->my_socket, &errset);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = timeout_ms * 1000;
|
||||
|
||||
vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */
|
||||
|
||||
do {
|
||||
readysock = select(n->my_socket + 1, NULL, &writeset, &errset, &timeout);
|
||||
} while (readysock <= 0);
|
||||
|
||||
if (FD_ISSET(n->my_socket, &errset)) {
|
||||
return sentLen;
|
||||
} else if (FD_ISSET(n->my_socket, &writeset)) {
|
||||
do {
|
||||
rc = SSL_write(n->ssl, buffer + sentLen, len - sentLen);
|
||||
|
||||
if (rc > 0) {
|
||||
sentLen += rc;
|
||||
} else if (rc < 0) {
|
||||
sentLen = rc;
|
||||
break;
|
||||
}
|
||||
} while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);
|
||||
}
|
||||
|
||||
return sentLen;
|
||||
}
|
||||
|
||||
|
||||
static void esp_ssl_disconnect(Network* n)
|
||||
{
|
||||
close(n->my_socket);
|
||||
SSL_free(n->ssl);
|
||||
SSL_CTX_free(n->ctx);
|
||||
n->read_count = 0;
|
||||
}
|
||||
|
||||
|
||||
void NetworkInitSSL(Network* n)
|
||||
{
|
||||
n->my_socket = 0;
|
||||
n->mqttread = esp_ssl_read;
|
||||
n->mqttwrite = esp_ssl_write;
|
||||
n->disconnect = esp_ssl_disconnect;
|
||||
n->read_count = 0;
|
||||
n->ctx = NULL;
|
||||
n->ssl = NULL;
|
||||
}
|
||||
|
||||
|
||||
int NetworkConnectSSL(Network* n, char* addr, int port, ssl_ca_crt_key_t* ssl_cck, const SSL_METHOD* method, int verify_mode, size_t frag_len)
|
||||
{
|
||||
struct sockaddr_in sAddr;
|
||||
int retVal = -1;
|
||||
struct hostent* ipAddress;
|
||||
|
||||
if ((ipAddress = gethostbyname(addr)) == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
n->ctx = SSL_CTX_new(method);
|
||||
|
||||
if (!n->ctx) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ssl_cck->cacrt) {
|
||||
X509* cacrt = d2i_X509(NULL, ssl_cck->cacrt, ssl_cck->cacrt_len);
|
||||
|
||||
if (!cacrt) {
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
SSL_CTX_add_client_CA(n->ctx, cacrt);
|
||||
}
|
||||
|
||||
if (ssl_cck->cert && ssl_cck->key) {
|
||||
retVal = SSL_CTX_use_certificate_ASN1(n->ctx, ssl_cck->cert_len, ssl_cck->cert);
|
||||
|
||||
if (!retVal) {
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
retVal = SSL_CTX_use_PrivateKey_ASN1(0, n->ctx, ssl_cck->key, ssl_cck->key_len);
|
||||
|
||||
if (!retVal) {
|
||||
goto exit1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl_cck->cacrt) {
|
||||
SSL_CTX_set_verify(n->ctx, verify_mode, NULL);
|
||||
} else {
|
||||
SSL_CTX_set_verify(n->ctx, SSL_VERIFY_NONE, NULL);
|
||||
}
|
||||
|
||||
SSL_CTX_set_default_read_buffer_len(n->ctx, frag_len);
|
||||
|
||||
sAddr.sin_family = AF_INET;
|
||||
sAddr.sin_port = sl_Htons((unsigned short)port);
|
||||
sAddr.sin_addr.s_addr = sl_Htonl(ipAddress);
|
||||
sAddr.sin_addr.s_addr = ((struct in_addr*)(ipAddress->h_addr))->s_addr;
|
||||
sAddr.sin_port = htons(port);
|
||||
|
||||
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;
|
||||
if ((n->my_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
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;
|
||||
if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0) {
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
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;
|
||||
n->ssl = SSL_new(n->ctx);
|
||||
|
||||
if (!n->ssl) {
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
SSL_set_fd(n->ssl, n->my_socket);
|
||||
|
||||
if ((retVal = SSL_connect(n->ssl)) <= 0) {
|
||||
goto exit3;
|
||||
} else {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
exit3:
|
||||
SSL_free(n->ssl);
|
||||
exit2:
|
||||
close(n->my_socket);
|
||||
exit1:
|
||||
SSL_CTX_free(n->ctx);
|
||||
exit:
|
||||
return retVal;
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user