Help with TLS Socket Creation on Thingy53 - ENOMEM (Error 23)

I'm working on a Thingy53 project with Zephyr RTOS that requires TLS connections, but I'm encountering persistent "Failed to create TLS socket: 23" errors (ENOMEM - out of memory). I've implemented several memory optimizations and error handling strategies but still face issues with TLS socket creation.

  1. Initial Problem Identification

    • Thingy53 device experiencing ENOMEM errors during TLS socket creation
    • Memory allocation test function using undefined k_malloc_free_get
  2. Configuration Optimization

    • Consolidated duplicate definitions in prj.conf
    • Increased heap memory (CONFIG_HEAP_MEM_POOL_SIZE=180000)
    • Increased mbedTLS heap (CONFIG_MBEDTLS_HEAP_SIZE=80000)
    • Restored GPIO and WiFi management configurations
  3. TLS Cipher Configuration Issues

    • Identified problematic CONFIG_MBEDTLS_SSL_CIPHERSUITES configuration
    • Attempted various syntax fixes (removing quotes, escaping quotes)
    • Ultimately removed the problematic configuration to allow builds to proceed
  4. First Socket Implementation Approach

    • Tried incremental approach: TCP socket → Connect → TLS upgrade
    • Failed with ENOBUFS (error 109) when setting TLS_SEC_TAG_LIST
  5. Second Socket Implementation Approach

    • Created TLS socket directly using IPPROTO_TLS_1_2
    • Set all TLS options before connecting
    • Eliminated socket reconfiguration to allow proper resource allocation
  6. Memory Management Improvements

    • Implemented socket tracking system to prevent resource leaks
    • Added retry mechanism with increasing delays
    • Added specific ENOMEM error handling with resource cleanup
    • Improved TLS configuration sequence (hostname before security tags)
  7. Current Status

    • Despite improvements, still encountering ENOMEM (error 23)
    • Memory allocation test succeeds but TLS socket creation fails
    • Implemented more aggressive resource management with k_yield() and socket tracking
static int create_tls_socket(const char *hostname, struct sockaddr_in *server_addr)
{
    int sock;
    int ret;
    int retry_count = 0;
    const int retry_delay_ms = 1000;
    
    /* Check memory status before attempting socket creation */
    check_memory_status("before TLS socket creation");
    
    /* We'll try a different approach if the previous one keeps failing with ENOMEM */
    while (retry_count < MAX_SOCKET_RETRIES) {
        /* First, ensure any previous socket resources are fully released */
        k_sleep(K_MSEC(retry_delay_ms));
        k_yield();  /* Allow other threads to run and potentially free resources */
        
        /* Create TLS socket */
        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
        if (sock < 0) {
            if (errno == ENOMEM) {
                LOG_ERR("Failed to create TLS socket: Out of memory (ENOMEM)");
                /* Try to release memory by forcing a garbage collection */
                close_all_sockets();
                retry_count++;
                continue;
            } else {
                LOG_ERR("Failed to create TLS socket: %d", errno);
                retry_count++;
                continue;
            }
        }
        
        LOG_INF("TLS socket created successfully");
        track_socket(sock);
        
        /* Set TLS socket options */
        sec_tag_t sec_tag_list[] = {
            CA_CERT_TAG,
        };
        
        /* Set receive and send timeout to avoid blocking indefinitely */
        struct timeval timeout = {
            .tv_sec = 10,
            .tv_usec = 0,
        };
        
        ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        if (ret < 0) {
            LOG_ERR("Failed to set socket receive timeout: %d", errno);
            close(sock);
            untrack_socket(sock);
            retry_count++;
            continue;
        }
        
        // [Additional socket option settings omitted for brevity]
        
        /* All options set successfully */
        LOG_INF("TLS socket configured successfully");
        return sock;
    }
    
    LOG_ERR("Failed to create TLS socket after %d attempts", MAX_SOCKET_RETRIES);
    return -ENOMEM;
}

I'm tracking sockets and cleaning them up:
void track_socket(int sock)
{
// Track socket for potential cleanup
}

void untrack_socket(int sock)
{
// Remove socket from tracking
}

void close_all_sockets(void)
{
// Close all tracked sockets to free resources
}

I've made the following memory optimizations in prj.conf:

Increase heap memory pool size

CONFIG_HEAP_MEM_POOL_SIZE=200000
CONFIG_HEAP_MEM_POOL_IGNORE_MIN=y

TLS Configuration

CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=85000
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1536

Reduce TLS resource usage

CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2
CONFIG_NET_SOCKETS_TLS_MAX_CREDENTIALS=2
CONFIG_NET_CONTEXT_MAX_CONN=4

Are there additional memory optimizations I should be making for TLS on constrained devices like the Thingy53?
Could there be any memory leaks or resource allocation issues that I'm missing in my implementation?
Are there specific mbedTLS configurations I should be adjusting to reduce memory usage further?
Is there a way to debug exactly what's happening during TLS socket creation that's causing the ENOMEM error?
Should I be implementing a different approach for TLS on this device?

Parents
  • ```c

    /*
    * Copyright (c) 2022 Nordic Semiconductor ASA
    *
    * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    */

    /** @file
    * @brief WiFi station sample
    */

    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(sta, CONFIG_LOG_DEFAULT_LEVEL);

    #include <zephyr/kernel.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <zephyr/shell/shell.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/init.h>

    #include <zephyr/net/net_if.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/net_event.h>
    #include <zephyr/drivers/gpio.h>

    #include <net/wifi_mgmt_ext.h>
    #include <net/wifi_ready.h>

    /* HTTP client includes */
    #include <zephyr/net/socket.h>
    #include <zephyr/net/http/client.h>
    #include <zephyr/net/dns_resolve.h>

    /* TLS credential includes */
    #include <zephyr/net/tls_credentials.h>
    #include <zephyr/fs/fs.h>

    #if defined(CONFIG_BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP) || \
    defined(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP)
    #include <zephyr/drivers/wifi/nrf_wifi/bus/qspi_if.h>
    #endif

    #include "net_private.h"
    #include "ca_certificate.h"

    #define WIFI_SHELL_MODULE "wifi"

    #define WIFI_SHELL_MGMT_EVENTS (NET_EVENT_WIFI_CONNECT_RESULT | \
    NET_EVENT_WIFI_DISCONNECT_RESULT)

    #define MAX_SSID_LEN 32
    #define STATUS_POLLING_MS 300

    /* 1000 msec = 1 sec */
    #define LED_SLEEP_TIME_MS 100

    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    /*
    * A build error on this line means your board is unsupported.
    * See the sample documentation for information on how to fix this.
    */
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

    static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
    static struct net_mgmt_event_callback net_shell_mgmt_cb;

    #ifdef CONFIG_WIFI_READY_LIB
    static K_SEM_DEFINE(wifi_ready_state_changed_sem, 0, 1);
    static bool wifi_ready_status;
    #endif /* CONFIG_WIFI_READY_LIB */

    static struct {
    const struct shell *sh;
    union {
    struct {
    uint8_t connected : 1;
    uint8_t connect_result : 1;
    uint8_t disconnect_requested : 1;
    uint8_t _unused : 5;
    };
    uint8_t all;
    };
    } context;

    /* HTTP client defines */
    #define HTTP_PORT 80
    #define HTTPS_PORT 443
    #define MAX_RECV_BUF_LEN 512
    #define MAX_SOCKET_RETRIES 3 /* Maximum number of socket creation retries */

    /* TLS certificate defines */
    #define CA_CERT_TAG 1

    /* Socket tracking for debugging */
    static int active_sockets = 0;

    /* HTTP client variables */
    static uint8_t recv_buf_ipv4[MAX_RECV_BUF_LEN];
    static int sock4 = -1;
    static struct sockaddr_in addr4;

    /* Function declarations */
    static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb);
    static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb);
    static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
    uint32_t mgmt_event, struct net_if *iface);
    static int connect_to_server(const char *server, uint16_t port);
    static void disconnect_from_server(int sock);
    static int perform_http_get(int sock, const char *server, const char *path);
    static int get_azure_auth_token(void);
    static int test_http_connection(void);
    static int start_app(void);

    /* Forward declarations */
    void net_mgmt_callback_init(void);

    void toggle_led(void)
    {
    int ret;

    if (!device_is_ready(led.port)) {
    LOG_ERR("LED device is not ready");
    return;
    }

    ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    if (ret < 0) {
    LOG_ERR("Error %d: failed to configure LED pin", ret);
    return;
    }

    while (1) {
    if (context.connected) {
    gpio_pin_toggle_dt(&led);
    k_msleep(LED_SLEEP_TIME_MS);
    } else {
    gpio_pin_set_dt(&led, 0);
    k_msleep(LED_SLEEP_TIME_MS);
    }
    }
    }

    K_THREAD_DEFINE(led_thread_id, 1024, toggle_led, NULL, NULL, NULL,
    7, 0, 0);

    static int cmd_wifi_status(void)
    {
    struct net_if *iface = net_if_get_default();
    struct wifi_iface_status status = { 0 };

    if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
    sizeof(struct wifi_iface_status))) {
    LOG_INF("Status request failed");

    return -ENOEXEC;
    }

    LOG_INF("==================");
    LOG_INF("State: %s", wifi_state_txt(status.state));

    if (status.state >= WIFI_STATE_ASSOCIATED) {
    uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];

    LOG_INF("Interface Mode: %s",
    wifi_mode_txt(status.iface_mode));
    LOG_INF("Link Mode: %s",
    wifi_link_mode_txt(status.link_mode));
    LOG_INF("SSID: %.32s", status.ssid);
    LOG_INF("BSSID: %s",
    net_sprint_ll_addr_buf(
    status.bssid, WIFI_MAC_ADDR_LEN,
    mac_string_buf, sizeof(mac_string_buf)));
    LOG_INF("Band: %s", wifi_band_txt(status.band));
    LOG_INF("Channel: %d", status.channel);
    LOG_INF("Security: %s", wifi_security_txt(status.security));
    LOG_INF("MFP: %s", wifi_mfp_txt(status.mfp));
    LOG_INF("RSSI: %d", status.rssi);
    }
    return 0;
    }

    static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb)
    {
    const struct wifi_status *status =
    (const struct wifi_status *) cb->info;

    if (context.connected) {
    return;
    }

    if (status->status) {
    LOG_ERR("Connection failed (%d)", status->status);
    } else {
    LOG_INF("Connected");
    context.connected = true;
    }

    context.connect_result = true;
    }

    static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb)
    {
    const struct wifi_status *status =
    (const struct wifi_status *) cb->info;

    if (!context.connected) {
    return;
    }

    if (context.disconnect_requested) {
    LOG_INF("Disconnection request %s (%d)",
    status->status ? "failed" : "done",
    status->status);
    context.disconnect_requested = false;
    } else {
    LOG_INF("Received Disconnected");
    context.connected = false;
    }

    cmd_wifi_status();
    }

    static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
    uint32_t mgmt_event, struct net_if *iface)
    {
    switch (mgmt_event) {
    case NET_EVENT_WIFI_CONNECT_RESULT:
    handle_wifi_connect_result(cb);
    break;
    case NET_EVENT_WIFI_DISCONNECT_RESULT:
    handle_wifi_disconnect_result(cb);
    break;
    default:
    break;
    }
    }

    static void print_dhcp_ip(struct net_mgmt_event_callback *cb)
    {
    /* Get DHCP info from struct net_if_dhcpv4 and print */
    const struct net_if_dhcpv4 *dhcpv4 = cb->info;
    const struct in_addr *addr = &dhcpv4->requested_ip;
    char dhcp_info[128];

    net_addr_ntop(AF_INET, addr, dhcp_info, sizeof(dhcp_info));

    LOG_INF("DHCP IP address: %s", dhcp_info);
    }
    static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb,
    uint32_t mgmt_event, struct net_if *iface)
    {
    switch (mgmt_event) {
    case NET_EVENT_IPV4_DHCP_BOUND:
    print_dhcp_ip(cb);
    break;
    default:
    break;
    }
    }

    static int wifi_connect(void)
    {
    struct net_if *iface = net_if_get_first_wifi();

    context.connected = false;
    context.connect_result = false;

    if (net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, NULL, 0)) {
    LOG_ERR("Connection request failed");

    return -ENOEXEC;
    }

    LOG_INF("Connection requested");

    return 0;
    }

    int bytes_from_str(const char *str, uint8_t *bytes, size_t bytes_len)
    {
    size_t i;
    char byte_str[3];

    if (strlen(str) != bytes_len * 2) {
    LOG_ERR("Invalid string length: %zu (expected: %d)\n",
    strlen(str), bytes_len * 2);
    return -EINVAL;
    }

    for (i = 0; i < bytes_len; i++) {
    memcpy(byte_str, str + i * 2, 2);
    byte_str[2] = '\0';
    bytes[i] = strtol(byte_str, NULL, 16);
    }

    return 0;
    }

    /* HTTP client implementation */
    static int connect_to_server(const char *server, uint16_t port)
    {
    int sock;
    struct addrinfo *result;
    struct addrinfo hints = {
    .ai_family = AF_INET,
    .ai_socktype = SOCK_STREAM
    };

    /* Check if WiFi is connected before attempting to connect */
    if (!context.connected) {
    LOG_ERR("WiFi not connected. Cannot connect to server.");
    return -ENOTCONN;
    }

    LOG_INF("Resolving address for %s", server);
    int err = getaddrinfo(server, NULL, &hints, &result);
    if (err) {
    LOG_ERR("getaddrinfo() failed, err: %d", err);
    return -EIO;
    }

    if (result == NULL) {
    LOG_ERR("Error: Address not found");
    return -ENOENT;
    }

    /* Create socket */
    if (port == HTTPS_PORT) {
    /* Create TLS socket for HTTPS */
    LOG_INF("Creating TLS socket for HTTPS connection (current active sockets: %d)", active_sockets);

    /* Delete any existing credentials with the same tag first */
    err = tls_credential_delete(CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE);
    LOG_INF("Deleted existing TLS credentials: %s", err < 0 ? "Failed" : "Success");

    /* Add CA certificate to TLS credentials before creating socket */
    LOG_INF("Adding embedded certificate to TLS credentials (size: %d bytes)", sizeof(azure_ca_certificate));
    err = tls_credential_add(CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
    azure_ca_certificate, sizeof(azure_ca_certificate));
    if (err < 0) {
    LOG_ERR("Failed to add embedded CA certificate: %d", err);
    freeaddrinfo(result);
    return err;
    }
    LOG_INF("Embedded CA certificate added to TLS credentials");

    /* Retry socket creation a few times if it fails */
    int retry_count = 0;
    while (retry_count < MAX_SOCKET_RETRIES) {
    /* Now create the TLS socket after credentials are set up */
    sock = socket(result->ai_family, SOCK_STREAM, IPPROTO_TLS_1_2);
    if (sock >= 0) {
    /* Socket created successfully */
    active_sockets++;
    break;
    }

    LOG_ERR("Failed to create TLS socket, err: %d (%s), retry %d/%d",
    errno, strerror(errno), retry_count + 1, MAX_SOCKET_RETRIES);

    /* If we're out of file descriptors, try to clean up and wait */
    if (errno == ENFILE || errno == EMFILE) {
    /* Clean up TLS credentials */
    tls_credential_delete(CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE);
    LOG_INF("Waiting for resources to be freed...");
    k_sleep(K_SECONDS(1));
    }

    retry_count++;
    }

    if (sock < 0) {
    LOG_ERR("Failed to create TLS socket after %d retries", MAX_SOCKET_RETRIES);
    /* Clean up TLS credentials if socket creation fails */
    tls_credential_delete(CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE);
    freeaddrinfo(result);
    return -errno;
    }

    LOG_INF("TLS Socket created successfully with fd: %d (active sockets: %d)", sock, active_sockets);

    /* TLS configuration */
    sec_tag_t sec_tag_list[] = { CA_CERT_TAG };
    int verify = TLS_PEER_VERIFY_REQUIRED;

    /* Set TLS security tag list */
    LOG_INF("Setting TLS security tag list");
    err = setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_list, sizeof(sec_tag_list));
    if (err < 0) {
    LOG_ERR("Failed to set TLS_SEC_TAG_LIST, err %d (%s)", errno, strerror(errno));
    close(sock);
    freeaddrinfo(result);
    return -errno;
    }
    LOG_INF("TLS security tag list set successfully");

    /* Set TLS peer verification to required */
    LOG_INF("Setting TLS peer verification to required");
    err = setsockopt(sock, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify));
    if (err < 0) {
    LOG_ERR("Failed to set TLS_PEER_VERIFY, err %d (%s)", errno, strerror(errno));
    close(sock);
    freeaddrinfo(result);
    return -errno;
    }
    LOG_INF("TLS peer verification set to required");

    /* Set TLS hostname for verification */
    LOG_INF("Setting TLS hostname to: %s", server);
    err = setsockopt(sock, SOL_TLS, TLS_HOSTNAME, server, strlen(server) + 1);
    if (err < 0) {
    LOG_ERR("Failed to set TLS_HOSTNAME option: %d (%s)", errno, strerror(errno));
    close(sock);
    freeaddrinfo(result);
    return -errno;
    }
    LOG_INF("TLS hostname set successfully");
    } else {
    /* Create regular TCP socket for HTTP */
    LOG_INF("Creating regular TCP socket for HTTP connection");
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
    LOG_ERR("Failed to create socket, err: %d (%s)", errno, strerror(errno));
    freeaddrinfo(result);
    return -errno;
    }
    }

    /* Set up address struct */
    memcpy(&addr4, result->ai_addr, sizeof(struct sockaddr_in));
    addr4.sin_port = htons(port);

    char ip_str[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &addr4.sin_addr, ip_str, sizeof(ip_str));
    LOG_INF("Connecting to server at %s:%d", ip_str, port);

    freeaddrinfo(result);

    /* Connect to server */
    err = connect(sock, (struct sockaddr *)&addr4, sizeof(addr4));
    if (err < 0) {
    LOG_ERR("Failed to connect to server, err: %d (%s)", errno, strerror(errno));
    close(sock);
    return -errno;
    }

    if (port == HTTPS_PORT) {
    LOG_INF("Connected to server over HTTPS (socket fd: %d)", sock);

    /* Verify TLS connection was established successfully */
    int verify_result = 0;
    socklen_t verify_size = sizeof(verify_result);
    err = getsockopt(sock, SOL_TLS, TLS_PEER_VERIFY, &verify_result, &verify_size);

    if (err < 0) {
    LOG_ERR("Failed to get TLS verification result: %d (%s)", errno, strerror(errno));
    } else if (verify_result != 0) {
    LOG_ERR("TLS certificate verification failed: %d", verify_result);
    close(sock);
    return -EACCES;
    } else {
    LOG_INF("TLS certificate verification succeeded");
    }
    } else {
    LOG_INF("Connected to server over HTTP (socket fd: %d)", sock);
    }

    return sock;
    }

    static void disconnect_from_server(int sock)
    {
    if (sock > 0) {
    LOG_INF("Closing socket fd: %d (active sockets: %d)", sock, active_sockets);
    (void)close(sock);
    active_sockets--;
    LOG_INF("Socket closed. Active sockets remaining: %d", active_sockets);
    }
    }

    static int perform_http_get(int sock, const char *server, const char *path)
    {
    int sent;
    int total_sent = 0;
    int received;
    char request[256];
    int request_len;

    /* Format HTTP GET request */
    request_len = snprintf(request, sizeof(request),
    "GET %s HTTP/1.1\r\n"
    "Host: %s\r\n"
    "Connection: close\r\n"
    "\r\n",
    path, server);

    if (request_len <= 0) {
    LOG_ERR("Failed to create HTTP request");
    return -EINVAL;
    }

    /* Send HTTP request */
    do {
    sent = send(sock, &request[total_sent], request_len - total_sent, 0);
    if (sent < 0) {
    LOG_ERR("Failed to send HTTP request, err: %d", errno);
    return -errno;
    }
    total_sent += sent;
    } while (total_sent < request_len);

    LOG_INF("HTTP request sent: %d bytes", total_sent);

    /* Receive HTTP response */
    LOG_INF("HTTP response:");
    do {
    received = recv(sock, recv_buf_ipv4, sizeof(recv_buf_ipv4) - 1, 0);
    if (received < 0) {
    LOG_ERR("Failed to receive HTTP response, err: %d", errno);
    return -errno;
    }
    if (received > 0) {
    /* Null-terminate the received data for printing */
    recv_buf_ipv4[received] = 0;
    LOG_INF("%s", recv_buf_ipv4);
    }
    } while (received > 0);

    return 0;
    }

    static int test_http_connection(void)
    {
    int ret;
    const char *server = "httpbin.org";
    const char *path = "/get";

    LOG_INF("Connecting to %s...", server);

    /* Connect to server */
    sock4 = connect_to_server(server, HTTP_PORT);
    if (sock4 < 0) {
    LOG_ERR("Failed to connect to server: %d", sock4);
    return sock4;
    }

    LOG_INF("Connected to %s", server);

    /* Perform HTTP GET request */
    ret = perform_http_get(sock4, server, path);
    if (ret < 0) {
    LOG_ERR("Failed to perform HTTP GET request: %d", ret);
    disconnect_from_server(sock4);
    return ret;
    }

    /* Disconnect from server */
    disconnect_from_server(sock4);
    sock4 = -1;

    LOG_INF("HTTP test completed successfully");
    return 0;
    }

    /* Define Microsoft Speech API key */
    #define MS_SPEECH_KEY "5Mkszj3yFl2vmbRDchDUHDAOMiZAYmzaLzA508JrnpRYYKBsv4nqJQQJ99BCAC5RqLJXJ3w3AAAYACOGVfQg"

    /* Function to get Microsoft Speech API authentication token */
    static int get_azure_auth_token(void)
    {
    int sock;
    const char *server = "westeurope.api.cognitive.microsoft.com";
    const char *path = "/sts/v1.0/issuetoken"; /* Actual token endpoint */
    char request[512];
    int request_len;
    int sent;
    int total_sent = 0;
    int received;
    char recv_buf[512];

    LOG_INF("Getting Azure authentication token...");

    /* Check if WiFi is connected before attempting to connect */
    if (!context.connected) {
    LOG_ERR("WiFi not connected. Cannot connect to Azure server.");
    return -ENOTCONN;
    }

    /* Connect to Azure server using HTTPS for secure connection */
    sock = connect_to_server(server, HTTPS_PORT);
    if (sock < 0) {
    LOG_ERR("Failed to connect to Azure server: %d", sock);
    return sock;
    }

    LOG_INF("Connected to Azure server, socket fd: %d", sock);

    /* Format HTTP POST request with API key */
    request_len = snprintf(request, sizeof(request),
    "POST %s HTTP/1.1\r\n"
    "Host: %s\r\n"
    "Ocp-Apim-Subscription-Key: %s\r\n"
    "Content-Length: 0\r\n"
    "Connection: close\r\n"
    "\r\n",
    path, server, MS_SPEECH_KEY);

    /* Send the request */
    do {
    sent = send(sock, &request[total_sent], request_len - total_sent, 0);
    if (sent < 0) {
    LOG_ERR("Failed to send HTTP request, err: %d", errno);
    disconnect_from_server(sock);
    return -errno;
    }
    total_sent += sent;
    } while (total_sent < request_len);

    LOG_INF("Azure authentication request sent: %d bytes", total_sent);

    /* Receive the response */
    LOG_INF("Azure authentication response:");
    do {
    received = recv(sock, recv_buf, sizeof(recv_buf) - 1, 0);
    if (received < 0) {
    LOG_ERR("Failed to receive HTTP response, err: %d", errno);
    disconnect_from_server(sock);
    return -errno;
    }
    if (received > 0) {
    /* Null-terminate the received data for printing */
    recv_buf[received] = 0;
    LOG_INF("%s", recv_buf);
    }
    } while (received > 0);

    disconnect_from_server(sock);

    LOG_INF("Azure authentication token retrieval completed");
    return 0;
    }

    int start_app(void)
    {
    int ret;
    #if defined(CONFIG_BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP) || \
    defined(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP)
    /* Initialize the bus */
    ret = nrf_wifi_init_qspi();
    if (ret) {
    LOG_ERR("nrf_wifi_init_qspi() failed with %d", ret);
    return ret;
    }
    #endif /* CONFIG_BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP */

    /* Initialize net_mgmt callbacks */
    net_mgmt_callback_init();

    /* Connect to WiFi network */
    ret = wifi_connect();
    if (ret) {
    LOG_ERR("wifi_connect() failed with %d", ret);
    return ret;
    }

    /* Wait for connection to complete */
    LOG_INF("Waiting for WiFi connection...");
    int timeout_counter = 0;
    const int max_timeout = 30; // 30 seconds timeout

    while (!context.connected && timeout_counter < max_timeout) {
    k_sleep(K_MSEC(1000));
    timeout_counter++;
    LOG_INF("Waiting for WiFi connection... %d/%d", timeout_counter, max_timeout);
    }

    if (!context.connected) {
    LOG_ERR("WiFi connection timed out after %d seconds", max_timeout);
    return -ETIMEDOUT;
    }

    /* Wait a bit more to ensure DHCP is completed */
    LOG_INF("WiFi connected, waiting for DHCP...");
    k_sleep(K_SECONDS(3));

    /* Check WiFi status */
    cmd_wifi_status();

    /* Test HTTP connection */
    LOG_INF("Testing HTTP connection...");
    ret = test_http_connection();
    if (ret) {
    LOG_ERR("HTTP connection test failed: %d", ret);
    } else {
    LOG_INF("HTTP test completed successfully");
    }

    /* Allow some time for resources to be freed */
    LOG_INF("Waiting for resources to be freed before Azure test...");
    k_sleep(K_SECONDS(5));

    /* Test Azure authentication */
    LOG_INF("Getting Azure authentication token...");
    ret = get_azure_auth_token();
    if (ret) {
    LOG_ERR("Azure authentication failed: %d", ret);
    } else {
    LOG_INF("Azure authentication completed successfully");
    }

    return 0;
    }

    #ifdef CONFIG_WIFI_READY_LIB
    void start_wifi_thread(void);
    #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
    K_THREAD_DEFINE(start_wifi_thread_id, CONFIG_STA_SAMPLE_START_WIFI_THREAD_STACK_SIZE,
    start_wifi_thread, NULL, NULL, NULL,
    THREAD_PRIORITY, 0, -1);

    void start_wifi_thread(void)
    {
    start_app();
    }

    void wifi_ready_cb(bool wifi_ready)
    {
    LOG_DBG("Is Wi-Fi ready?: %s", wifi_ready ? "yes" : "no");
    wifi_ready_status = wifi_ready;
    k_sem_give(&wifi_ready_state_changed_sem);
    }
    #endif /* CONFIG_WIFI_READY_LIB */

    void net_mgmt_callback_init(void)
    {
    memset(&context, 0, sizeof(context));

    net_mgmt_init_event_callback(&wifi_shell_mgmt_cb,
    wifi_mgmt_event_handler,
    WIFI_SHELL_MGMT_EVENTS);

    net_mgmt_add_event_callback(&wifi_shell_mgmt_cb);

    net_mgmt_init_event_callback(&net_shell_mgmt_cb,
    net_mgmt_event_handler,
    NET_EVENT_IPV4_DHCP_BOUND);

    net_mgmt_add_event_callback(&net_shell_mgmt_cb);

    LOG_INF("Starting %s with CPU frequency: %d MHz", CONFIG_BOARD, SystemCoreClock/MHZ(1));
    k_sleep(K_SECONDS(1));
    }

    #ifdef CONFIG_WIFI_READY_LIB
    static int register_wifi_ready(void)
    {
    int ret = 0;
    wifi_ready_callback_t cb;
    struct net_if *iface = net_if_get_first_wifi();

    if (!iface) {
    LOG_ERR("Failed to get Wi-Fi interface");
    return -1;
    }

    cb.wifi_ready_cb = wifi_ready_cb;

    LOG_DBG("Registering Wi-Fi ready callbacks");
    ret = register_wifi_ready_callback(cb, iface);
    if (ret) {
    LOG_ERR("Failed to register Wi-Fi ready callbacks %s", strerror(ret));
    return ret;
    }

    return ret;
    }
    #endif /* CONFIG_WIFI_READY_LIB */

    int main(void)
    {
    int ret = 0;

    net_mgmt_callback_init();

    #ifdef CONFIG_WIFI_READY_LIB
    ret = register_wifi_ready();
    if (ret) {
    return ret;
    }
    k_thread_start(start_wifi_thread_id);
    #else
    start_app();
    #endif /* CONFIG_WIFI_READY_LIB */
    return ret;
    }

    ```

  • Maybe too much sockets, I am not sure but I need help to optimize it.

Reply Children
No Data
Related