Zephyr os mqtt tls thingsboard : mqtt_connect fails with return -2

I am trying to connect to mqtt.thingsboard.cloud server with mqtt tls protocol but I encounter the following error :

00:00:18.056,000] <inf> net_mqtt_publisher_sample: Attempting to connect to broker at 23.20.176.222:

[00:00:18.056,000] <inf> net_mqtt_publisher_sample: Connecting to MQTT broker… Attempt 1

[00:00:18.058,000] <inf> dns_resolve: mqtt.thingsboard.cloud IPv4 address: 23.20.176.222

[00:00:18.058,000] <inf> dns_resolve: mqtt.thingsboard.cloud IPv4 address: 54.159.242.170

[00:00:18.058,000] <inf> dns_resolve: mqtt.thingsboard.cloud IPv4 address: 52.73.3.142

[00:00:18.058,000] <inf> dns_resolve: mqtt.thingsboard.cloud IPv4 address: 50.19.226.55

[00:00:18.058,000] <inf> dns_resolve: DNS resolving finished

[00:00:18.147,000] <inf> net_mqtt_publisher_sample: mqtt_connect: -22 <ERROR>

[00:00:18.147,000] <err> net_mqtt_publisher_sample: mqtt_connect failed: -22

[00:00:18.647,000] <inf> net_mqtt_publisher_sample: Attempting to connect to broker at 50.19.226.55:

[00:00:18.647,000] <inf> net_mqtt_publisher_sample: Connecting to MQTT broker… Attempt 2

[00:00:18.738,000] <inf> net_mqtt_publisher_sample: mqtt_connect: -22 <ERROR>

[00:00:18.738,000] <err> net_mqtt_publisher_sample: mqtt_connect failed: -22

[00:00:19.239,000] <inf> net_mqtt_publisher_sample: Attempting to connect to broker at 50.19.226.55:

[00:00:19.239,000] <inf> net_mqtt_publisher_sample: Connecting to MQTT broker… Attempt 3

[00:00:19.239,000] <inf> net_mqtt_publisher_sample: mqtt_connect: -2 <ERROR>

[00:00:19.239,000] <err> net_mqtt_publisher_sample: mqtt_connect failed: -2

My code run well without tls configuration but when i add the tls_init function, it returns “mqtt_connect failed: -2” :

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_mqtt_publisher_sample, LOG_LEVEL_DBG);

#include <zephyr/kernel.h>
#include <zephyr/net/socket.h>
#include <zephyr/net/mqtt.h>
#include <zephyr/random/random.h>
#include <zephyr/net/tls_credentials.h>
#include <zephyr/net/dns_resolve.h>


#include <string.h>
#include <errno.h>

#include "config.h"
#include "dns_resolve.h"
#include "credentials.h"

#if defined(CONFIG_USERSPACE)
#include <zephyr/app_memory/app_memdomain.h>
K_APPMEM_PARTITION_DEFINE(app_partition);
struct k_mem_domain app_domain;
#define APP_BMEM K_APP_BMEM(app_partition)
#define APP_DMEM K_APP_DMEM(app_partition)
#else
#define APP_BMEM
#define APP_DMEM
#endif

/* Buffers for MQTT client. */
static APP_BMEM uint8_t rx_buffer[APP_MQTT_BUFFER_SIZE];
static APP_BMEM uint8_t tx_buffer[APP_MQTT_BUFFER_SIZE];


/* The mqtt client struct */
static APP_BMEM struct mqtt_client client_ctx;

/* MQTT Broker details. */
static APP_BMEM struct sockaddr_storage broker;


static APP_BMEM struct zsock_pollfd fds[1];
static APP_BMEM int nfds;

static APP_BMEM bool connected;

  /* #define TLS_SNI_HOSTNAME "mqtt.thingsboard.cloud" */

#define APP_CA_CERT_TAG 1
#define APP_PRIVATE_KEY_TAG 2

// Tableau des tags de sécurité utilisés pour les sessions TLS
static const sec_tag_t m_sec_tags[] = {
    APP_CA_CERT_TAG,
    APP_PRIVATE_KEY_TAG,
};

static int tls_init()
{
    int err;
    LOG_INF("Setting up credentials...");

    // Ajouter le certificat CA
    err = tls_credential_add(APP_CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
                             ca_cert, strlen(ca_cert));
    if (err < 0) {
        LOG_ERR("Failed to register CA certificate: %d", err);
        return err;
    }

    // Ajouter le certificat serveur
    err = tls_credential_add(APP_PRIVATE_KEY_TAG, TLS_CREDENTIAL_SERVER_CERTIFICATE,
                             client_cert, strlen(client_cert));
    if (err < 0) {
        LOG_ERR("Failed to add device certificate: %d", err);
        return err;
    }

    // Ajouter la clé privée du serveur
    err = tls_credential_add(APP_PRIVATE_KEY_TAG, TLS_CREDENTIAL_PRIVATE_KEY,
                             client_key, strlen(client_key));
    if (err < 0) {
        LOG_ERR("Failed to add device private key: %d", err);
        return err;
    }

    LOG_INF("Credentials setup successfully");
    return 0;
}


static void prepare_fds(struct mqtt_client *client)
{
    if (client->transport.type == MQTT_TRANSPORT_SECURE) {
        fds[0].fd = client->transport.tls.sock;
    }

    fds[0].events = ZSOCK_POLLIN;
    nfds = 1;
}

static void clear_fds(void)
{
    nfds = 0;
}

static int wait(int timeout)
{
    int ret = 0;

    if (nfds > 0) {
        ret = zsock_poll(fds, nfds, timeout);
        if (ret < 0) {
            LOG_ERR("poll error: %d", errno);
        }
    }

    return ret;
}

void mqtt_evt_handler(struct mqtt_client *const client,
              const struct mqtt_evt *evt)
{
    int err;

    switch (evt->type) {
    case MQTT_EVT_CONNACK:
        if (evt->result != 0) {
            LOG_ERR("MQTT connect failed %d", evt->result);
            break;
        }

        connected = true;
        LOG_INF("MQTT client connected!");

        break;

    case MQTT_EVT_DISCONNECT:
        LOG_INF("MQTT client disconnected %d", evt->result);

        connected = false;
        clear_fds();

        break;

    case MQTT_EVT_PUBACK:
        if (evt->result != 0) {
            LOG_ERR("MQTT PUBACK error %d", evt->result);
            break;
        }

        LOG_INF("PUBACK packet id: %u", evt->param.puback.message_id);

        break;

    case MQTT_EVT_PUBREC:
        if (evt->result != 0) {
            LOG_ERR("MQTT PUBREC error %d", evt->result);
            break;
        }

        LOG_INF("PUBREC packet id: %u", evt->param.pubrec.message_id);

        const struct mqtt_pubrel_param rel_param = {
            .message_id = evt->param.pubrec.message_id
        };

        err = mqtt_publish_qos2_release(client, &rel_param);
        if (err != 0) {
            LOG_ERR("Failed to send MQTT PUBREL: %d", err);
        }

        break;

    case MQTT_EVT_PUBCOMP:
        if (evt->result != 0) {
            LOG_ERR("MQTT PUBCOMP error %d", evt->result);
            break;
        }

        LOG_INF("PUBCOMP packet id: %u",
            evt->param.pubcomp.message_id);

        break;

    case MQTT_EVT_PINGRESP:
        LOG_INF("PINGRESP packet");
        break;

    default:
        break;
    }
}

static char *get_mqtt_payload(enum mqtt_qos qos)
{
    static APP_BMEM char payload[50];
    
    int temperature = (uint8_t)sys_rand32_get() % 100; 
    snprintk(payload, sizeof(payload), "{"temperature": %d}", temperature);

    return payload;
}

static char *get_mqtt_topic(void)
{
    return "v1/devices/me/telemetry";
}

static int publish(struct mqtt_client *client, enum mqtt_qos qos)
{
    struct mqtt_publish_param param;

    param.message.topic.qos = qos;
    param.message.topic.topic.utf8 = (uint8_t *)get_mqtt_topic();
    param.message.topic.topic.size =
            strlen(param.message.topic.topic.utf8);
    param.message.payload.data = get_mqtt_payload(qos);
    param.message.payload.len =
            strlen(param.message.payload.data);
    param.message_id = sys_rand32_get();
    param.dup_flag = 0U;
    param.retain_flag = 0U;

    return mqtt_publish(client, &param);
}

#define RC_STR(rc) ((rc) == 0 ? "OK" : "ERROR")

#define PRINT_RESULT(func, rc) 
    LOG_INF("%s: %d <%s>", (func), rc, RC_STR(rc))

static void broker_init(void)
{
    struct sockaddr_in *broker4 = (struct sockaddr_in *)&broker;

    broker4->sin_family = AF_INET;
    broker4->sin_port = htons(SERVER_PORT);
    zsock_inet_pton(AF_INET, resolved_ip, &broker4->sin_addr);
}

static void client_init(struct mqtt_client *client)
{
    mqtt_client_init(client);

    broker_init();

    /* MQTT client configuration */
    client->broker = &broker;
    client->evt_cb = mqtt_evt_handler;
    client->client_id.utf8 = (uint8_t *)MQTT_CLIENTID;
    client->client_id.size = strlen(MQTT_CLIENTID);
    client->user_name = NULL;
    client->password = NULL;

    client->protocol_version = MQTT_VERSION_3_1_1;

    LOG_INF("Attempting to connect to broker at %s:", resolved_ip);
    
    /* MQTT buffers configuration */
    client->rx_buf = rx_buffer;
    client->rx_buf_size = sizeof(rx_buffer);
    client->tx_buf = tx_buffer;
    client->tx_buf_size = sizeof(tx_buffer);

    /* MQTT transport configuration */
    client->transport.type = MQTT_TRANSPORT_SECURE;
    struct mqtt_sec_config *tls_config = &client->transport.tls.config;

    tls_config->peer_verify = TLS_PEER_VERIFY_REQUIRED;
    tls_config->cipher_list = NULL;
    tls_config->sec_tag_list = m_sec_tags;
    tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags);
    tls_config->hostname = SERVER_ADDR;
    tls_config->cert_nocopy = TLS_CERT_NOCOPY_OPTIONAL;

 }

/* In this routine we block until the connected variable is 1 */
static int try_to_connect(struct mqtt_client *client)
{
    int rc, i = 0;

    rc = do_ipv4_lookup();
    if (rc != 0) {
        LOG_ERR("DNS lookup failed: %d", rc);
        return rc;
    }

    while (i++ < APP_CONNECT_TRIES && !connected) {

        client_init(client);

        LOG_INF("Connecting to MQTT broker... Attempt %d", i);

        rc = mqtt_connect(client);
        PRINT_RESULT("mqtt_connect", rc);
        if (rc != 0) {
            LOG_ERR("mqtt_connect failed: %d", rc);
            k_sleep(K_MSEC(APP_SLEEP_MSECS));
            continue;
        }

        prepare_fds(client);

        if (wait(APP_CONNECT_TIMEOUT_MS)) {
            mqtt_input(client);
        }

        if (!connected) {
            mqtt_abort(client);
        }
    }

    if (connected) {
        return 0;
    }

    return -EINVAL;
}

static int process_mqtt_and_sleep(struct mqtt_client *client, int timeout)
{
    int64_t remaining = timeout;
    int64_t start_time = k_uptime_get();
    int rc;

    while (remaining > 0 && connected) {
        if (wait(remaining)) {
            rc = mqtt_input(client);
            if (rc != 0) {
                PRINT_RESULT("mqtt_input", rc);
                return rc;
            }
        }

        rc = mqtt_live(client);
        if (rc != 0 && rc != -EAGAIN) {
            PRINT_RESULT("mqtt_live", rc);
            return rc;
        } else if (rc == 0) {
            rc = mqtt_input(client);
            if (rc != 0) {
                PRINT_RESULT("mqtt_input", rc);
                return rc;
            }
        }

        remaining = timeout + start_time - k_uptime_get();
    }

    return 0;
}

#define SUCCESS_OR_EXIT(rc) { if (rc != 0) { return 1; } }
#define SUCCESS_OR_BREAK(rc) { if (rc != 0) { break; } }

static int publisher(void)
{
    int i, rc, r = 0;

    LOG_INF("attempting to connect: ");
    rc = try_to_connect(&client_ctx);
    PRINT_RESULT("try_to_connect", rc);
    SUCCESS_OR_EXIT(rc);

    i = 0;
    while (i++ < CONFIG_NET_SAMPLE_APP_MAX_ITERATIONS && connected) {
        r = -1;

        rc = mqtt_ping(&client_ctx);
        PRINT_RESULT("mqtt_ping", rc);
        SUCCESS_OR_BREAK(rc);

        rc = process_mqtt_and_sleep(&client_ctx, APP_SLEEP_MSECS);
        SUCCESS_OR_BREAK(rc);

        rc = publish(&client_ctx, MQTT_QOS_0_AT_MOST_ONCE);
        PRINT_RESULT("mqtt_publish", rc);
        SUCCESS_OR_BREAK(rc);

        rc = process_mqtt_and_sleep(&client_ctx, APP_SLEEP_MSECS);
        SUCCESS_OR_BREAK(rc);

        rc = publish(&client_ctx, MQTT_QOS_1_AT_LEAST_ONCE);
        PRINT_RESULT("mqtt_publish", rc);
        SUCCESS_OR_BREAK(rc);

        rc = process_mqtt_and_sleep(&client_ctx, APP_SLEEP_MSECS);
        SUCCESS_OR_BREAK(rc);

        rc = publish(&client_ctx, MQTT_QOS_2_EXACTLY_ONCE);
        PRINT_RESULT("mqtt_publish", rc);
        SUCCESS_OR_BREAK(rc);

        rc = process_mqtt_and_sleep(&client_ctx, APP_SLEEP_MSECS);
        SUCCESS_OR_BREAK(rc);

        r = 0;
    }

    rc = mqtt_disconnect(&client_ctx);
    PRINT_RESULT("mqtt_disconnect", rc);

    LOG_INF("Bye!");

    return r;
}

static int start_app(void)
{
    int r = 0, i = 0;

    while (!CONFIG_NET_SAMPLE_APP_MAX_CONNECTIONS ||
           i++ < CONFIG_NET_SAMPLE_APP_MAX_CONNECTIONS) {
        r = publisher();

        if (!CONFIG_NET_SAMPLE_APP_MAX_CONNECTIONS) {
            k_sleep(K_MSEC(5000));
        }
    }

    return r;
}

#if defined(CONFIG_USERSPACE)
#define STACK_SIZE 2048

#if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
#else
#define THREAD_PRIORITY K_PRIO_PREEMPT(8)
#endif

K_THREAD_DEFINE(app_thread, STACK_SIZE,
        start_app, NULL, NULL, NULL,
        THREAD_PRIORITY, K_USER, -1);

static K_HEAP_DEFINE(app_mem_pool, 1024 * 2);
#endif

int main(void)
{
    int rc;

    rc = tls_init();
    PRINT_RESULT("tls_init", rc);

#if defined(CONFIG_USERSPACE)
    int ret;

    struct k_mem_partition *parts[] = {
#if Z_LIBC_PARTITION_EXISTS
        &z_libc_partition,
#endif
        &app_partition
    };

    ret = k_mem_domain_init(&app_domain, ARRAY_SIZE(parts), parts);
    __ASSERT(ret == 0, "k_mem_domain_init() failed %d", ret);
    ARG_UNUSED(ret);

    k_mem_domain_add_thread(&app_domain, app_thread);
    k_thread_heap_assign(app_thread, &app_mem_pool);

    k_thread_start(app_thread);
    k_thread_join(app_thread, K_FOREVER);
#else
    exit(start_app());
#endif
    return 0;
}

and prj.conf :

CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_TCP=y
CONFIG_NET_LOG=y

CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2

CONFIG_PRINTK=y
CONFIG_STDOUT_CONSOLE=y

# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable IPv4 support
CONFIG_NET_IPV4=y

# Enable the DNS resolver
CONFIG_DNS_RESOLVER=y

CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="mqtt.thingsboard.cloud"


# Enable the MQTT Lib
CONFIG_MQTT_LIB=y

CONFIG_NET_CONFIG_SETTINGS=y


CONFIG_MAIN_STACK_SIZE=2048

CONFIG_NET_DHCPV4=y

# For IPv6
CONFIG_NET_BUF_DATA_SIZE=256

CONFIG_NET_SHELL=y

CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y

# TLS configuration
CONFIG_MQTT_LIB_TLS=y
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_ENABLE_HEAP=y

CONFIG_TLS_CREDENTIAL_FILENAMES=y

CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y

/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(dns_resolve, LOG_LEVEL_DBG);

#include "dns_resolve.h"
#include "config.h"

#define DNS_TIMEOUT (2 * MSEC_PER_SEC)

char resolved_ip[NET_IPV4_ADDR_LEN]; // Global variable to store the resolved IP address

void dns_result_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data) {
    char hr_addr[NET_IPV4_ADDR_LEN];
    char *hr_family;
    void *addr;

    switch (status) {
        case DNS_EAI_CANCELED:
            LOG_INF("DNS query was canceled");
            return;
        case DNS_EAI_FAIL:
            LOG_INF("DNS resolve failed");
            return;
        case DNS_EAI_NODATA:
            LOG_INF("Cannot resolve address");
            return;
        case DNS_EAI_ALLDONE:
            LOG_INF("DNS resolving finished");
            return;
        case DNS_EAI_INPROGRESS:
            break;
        default:
            LOG_INF("DNS resolving error (%d)", status);
            return;
    }

    if (!info) {
        return;
    }

    if (info->ai_family == AF_INET) {
        hr_family = "IPv4";
        addr = &net_sin(&info->ai_addr)->sin_addr;
    } else {
        LOG_ERR("Invalid IP address family %d", info->ai_family);
        return;
    }

    net_addr_ntop(info->ai_family, addr, hr_addr, sizeof(hr_addr));
    LOG_INF("%s %s address: %s", user_data ? (char *)user_data : "<null>",
            hr_family, hr_addr);
    strncpy(resolved_ip, hr_addr, sizeof(resolved_ip) - 1);
    resolved_ip[sizeof(resolved_ip) - 1] = '';
}

int do_ipv4_lookup(void) {
    static const char *query = SERVER_ADDR;
    static uint16_t dns_id;
    int ret;

    ret = dns_get_addr_info(query, DNS_QUERY_TYPE_A, &dns_id, dns_result_cb, (void *)query, DNS_TIMEOUT);
    if (ret < 0) {
        LOG_ERR("Cannot resolve IPv4 address (%d)", ret);
        return ret;
    }

    LOG_DBG("DNS id %u", dns_id);
    return 0;
}
#ifndef DNS_RESOLVE_H
#define DNS_RESOLVE_H

#include <zephyr/net/socket.h>
#include <zephyr/net/dns_resolve.h>

extern char resolved_ip[NET_IPV4_ADDR_LEN];

void dns_result_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data);
int do_ipv4_lookup(void);

#endif // DNS_RESOLVE_H

and this i how the certificate.h is implemented

// credentials.h
static const char ca_cert[] = 
    "-----BEGIN CERTIFICATE-----n"
    "MIIDdTCCAl2gAwIBAgIJ..."
    "-----END CERTIFICATE-----n";

static const char client_cert[] = 
    "-----BEGIN CERTIFICATE-----n"
    "MIIEqDCCA5CgAwIBAgIBA..."
    "-----END CERTIFICATE-----n";

static const char client_key[] = 
    "-----BEGIN PRIVATE KEY-----n"
    "MIIJKQIBAAKCAgEA7..."
    "-----END PRIVATE KEY-----n";

i try different tags

New contributor

Hally_BDX is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật