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?

  • The error is actually too many files open, but if I close some sockets the wifi doesnt work, if i open then i get the error.

  • ```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.

  • Hi

    Is there a reason you've reduced the CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS all the way to 2 here? And how many TLS sockets is your application trying to create here? Since you initially refer to the ENOMEM error, it seems like you're already within what the memory can handle now, but instead have restrained the TLS socket numbers too much. Please try increasing these configs:
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=2
    CONFIG_NET_SOCKETS_TLS_MAX_CREDENTIALS=2
    CONFIG_NET_CONTEXT_MAX_CONN=4

    As well as possibly CONFIG_POSIX_MAX_FDS.

    It's also important that you properly close unused sockets when you're done with them to free up resources. The MBEDTLS_HEAP_SIZE seem more than sufficient, but I'll need more information on what exactly the application is supposed to do here to know more about exact numbers for your configs here.

    Best regards,

    Simon

  • I am trying to connect to Azure's text to speech API using Thingy53. I changed the code:
    ```c

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/net/socket.h>
    #include <zephyr/net/net_mgmt.h>
    #include <zephyr/net/net_event.h>
    #include <zephyr/net/net_if.h>
    #include <zephyr/net/wifi_mgmt.h>
    #include <zephyr/net/tls_credentials.h>
    #include <zephyr/net/dns_resolve.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/logging/log.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>

    /* Define Zephyr socket control flags */
    #ifndef ZSOCK_FCNTL_OPTS
    #define ZSOCK_F_GETFL 3
    #define ZSOCK_F_SETFL 4
    #define ZSOCK_O_NONBLOCK 0x800
    #else
    #define ZSOCK_F_GETFL F_GETFL
    #define ZSOCK_F_SETFL F_SETFL
    #define ZSOCK_O_NONBLOCK O_NONBLOCK
    #endif

    /* Debug level control - Only keep Azure and WiFi connection debug as requested */
    #define DEBUG_AZURE 1  /* Set to 1 to enable Azure debug, 0 to disable */
    #define DEBUG_WIFI_CONN 0  /* Set to 0 to disable WiFi connection debug */
    #define DEBUG_GENERAL 0  /* Set to 1 to enable general debug, 0 to disable */

    LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL);

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

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

    #include <zephyr/drivers/gpio.h>

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

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

    /* TLS credential includes */
    #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 5  /* Maximum number of socket creation retries */
    #define MAX_WIFI_RECONNECT_ATTEMPTS 3
    #define WIFI_RECONNECT_DELAY_MS 5000
    #define SOCKET_CONNECT_TIMEOUT_SEC 15  /* Socket connection timeout in seconds */
    #define SOCKET_RECV_TIMEOUT_SEC 10     /* Socket receive timeout in seconds */
    #define SOCKET_SEND_TIMEOUT_SEC 10     /* Socket send timeout in seconds */
    #define MAX_TLS_FAILURES 5

    /* TLS socket timeout settings */
    #define TLS_SOCKET_CONNECT_TIMEOUT_SEC 30  /* Longer timeout for TLS */

    /* TLS certificate defines */
    #define CA_CERT_TAG 1
    #define SERVER_CERT_TAG 2
    #define PEER_VERIFY_REQUIRED 2

    /* TLS socket option defines - using Zephyr's definitions */
    /* Do not redefine TLS_PEER_VERIFY, use the one from socket.h */
    #define TLS_HOSTNAME_OPTION 2
    #define TLS_CIPHERSUITE_LIST_OPTION 3
    #define TLS_HANDSHAKE_TIMEOUT_MS_OPTION 4
    #define TLS_ERROR_OPTION 5

    /* TLS credentials management */
    static bool tls_credentials_added = false;

    static void cleanup_tls_credentials(void)
    {
        int ret;
       
        if (tls_credentials_added) {
            ret = tls_credential_delete(CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE);
            if (ret < 0 && ret != -ENOENT) {
                LOG_ERR("Failed to delete CA certificate: %d", ret);
            } else {
                LOG_INF("TLS credentials cleaned up");
                tls_credentials_added = false;
            }
        }
       
        /* Force memory cleanup */
        k_sleep(K_MSEC(100));
        k_yield();
    }

    static int setup_tls_credentials(void)
    {
        int ret = 0;
       
        /* If credentials are already added, no need to add again */
        if (tls_credentials_added) {
            return 0;
        }
       
        /* Add CA certificate */
        ret = tls_credential_add(CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
            azure_ca_certificate, sizeof(azure_ca_certificate));
        if (ret < 0) {
            LOG_ERR("Failed to add CA certificate: %d", ret);
            return ret;
        }
       
        LOG_INF("CA certificate added to TLS credentials");
        tls_credentials_added = true;
       
        return 0;
    }

    /* Global variables for socket tracking */
    #define MAX_TRACKED_SOCKETS 4
    static int active_sockets_array[MAX_TRACKED_SOCKETS] = {-1, -1, -1, -1};
    static K_MUTEX_DEFINE(socket_mutex);

    /* Socket health monitoring */
    static int consecutive_socket_failures = 0;
    #define MAX_CONSECUTIVE_FAILURES 3

    /* Global variables for TLS error tracking */
    static int tls_consecutive_failures = 0;

    /* Forward declarations */
    static void cleanup_tls_credentials(void);
    static void reconnect_work_handler(struct k_work *work);
    static K_WORK_DEFINE(reconnect_work, reconnect_work_handler);
    static void force_socket_cleanup(void);

    /* Socket tracking functions */
    static void track_socket(int sock)
    {
        if (sock < 0) {
            return;
        }

        k_mutex_lock(&socket_mutex, K_FOREVER);
       
        /* First check if socket is already tracked */
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            if (active_sockets_array[i] == sock) {
                k_mutex_unlock(&socket_mutex);
                return;
            }
        }
       
        /* Find an empty slot */
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            if (active_sockets_array[i] < 0) {
                active_sockets_array[i] = sock;
                LOG_INF("Tracking socket %d in slot %d", sock, i);
                k_mutex_unlock(&socket_mutex);
                return;
            }
        }
       
        /* No empty slots, force cleanup and try again */
        LOG_WRN("No empty socket tracking slots, forcing cleanup");
        k_mutex_unlock(&socket_mutex);
        force_socket_cleanup();
       
        /* Try again after cleanup */
        k_mutex_lock(&socket_mutex, K_FOREVER);
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            if (active_sockets_array[i] < 0) {
                active_sockets_array[i] = sock;
                LOG_INF("Tracking socket %d in slot %d after cleanup", sock, i);
                k_mutex_unlock(&socket_mutex);
                return;
            }
        }
       
        LOG_ERR("Failed to track socket %d, all slots full even after cleanup", sock);
        k_mutex_unlock(&socket_mutex);
    }

    static void untrack_socket(int sock)
    {
        if (sock < 0) {
            return;
        }

        k_mutex_lock(&socket_mutex, K_FOREVER);
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            if (active_sockets_array[i] == sock) {
                LOG_INF("Untracking socket %d from slot %d", sock, i);
                active_sockets_array[i] = -1;
                k_mutex_unlock(&socket_mutex);
                return;
            }
        }
        k_mutex_unlock(&socket_mutex);
        LOG_WRN("Socket %d was not being tracked", sock);
    }

    static void cleanup_unhealthy_sockets(void)
    {
        struct zsock_pollfd fds;
        int ret;
       
        LOG_INF("Checking for unhealthy sockets");
       
        k_mutex_lock(&socket_mutex, K_FOREVER);
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            int sock = active_sockets_array[i];
            if (sock >= 0) {
                /* Check if socket is still valid */
                fds.fd = sock;
                fds.events = ZSOCK_POLLIN;
                ret = zsock_poll(&fds, 1, 0);
               
                if (ret < 0 || (fds.revents & (ZSOCK_POLLERR | ZSOCK_POLLHUP | ZSOCK_POLLNVAL))) {
                    LOG_WRN("Socket %d appears unhealthy (poll result: %d, revents: 0x%x), closing",
                            sock, ret, fds.revents);
                    close(sock);
                    active_sockets_array[i] = -1;
                }
            }
        }
        k_mutex_unlock(&socket_mutex);
    }

    static void close_all_sockets(void)
    {
        LOG_INF("Closing all tracked sockets");
       
        k_mutex_lock(&socket_mutex, K_FOREVER);
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            if (active_sockets_array[i] >= 0) {
                LOG_INF("Closing socket %d", active_sockets_array[i]);
                /* First try to gracefully shutdown the connection */
                zsock_shutdown(active_sockets_array[i], ZSOCK_SHUT_RDWR);
                /* Then close it */
                close(active_sockets_array[i]);
                active_sockets_array[i] = -1;
            }
        }
        k_mutex_unlock(&socket_mutex);
    }

    static void force_socket_cleanup(void)
    {
        int i;
        struct zsock_pollfd fds;
       
        LOG_INF("Performing forced socket cleanup");
       
        /* First check tracked sockets */
        k_mutex_lock(&socket_mutex, K_FOREVER);
        for (i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            if (active_sockets_array[i] >= 0) {
                LOG_WRN("Closing tracked socket %d", active_sockets_array[i]);
                zsock_shutdown(active_sockets_array[i], ZSOCK_SHUT_RDWR);
                close(active_sockets_array[i]);
                active_sockets_array[i] = -1;
            }
        }
        k_mutex_unlock(&socket_mutex);
       
        /* Then brute-force check common socket descriptor range */
        for (i = 0; i < CONFIG_POSIX_MAX_FDS; i++) {
            fds.fd = i;
            fds.events = ZSOCK_POLLIN;
            if (zsock_poll(&fds, 1, 0) >= 0 && !(fds.revents & ZSOCK_POLLNVAL)) {
                LOG_WRN("Force closing socket descriptor %d", i);
                zsock_shutdown(i, ZSOCK_SHUT_RDWR);
                close(i);
            }
        }
       
        /* Reset consecutive failures counter after cleanup */
        consecutive_socket_failures = 0;
    }

    static void recycle_system_resources(void)
    {
        LOG_INF("Recycling system resources to recover from potential resource exhaustion");
       
        /* Close all tracked sockets */
        close_all_sockets();
       
        /* Clean up TLS credentials */
        cleanup_tls_credentials();
       
        /* Force socket cleanup to catch any untracked sockets */
        force_socket_cleanup();
       
        /* Give the system time to free resources */
        k_sleep(K_MSEC(2000));
       
        /* Check WiFi connection and reconnect if needed */
        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(status)) >= 0) {
            if (status.state < WIFI_STATE_ASSOCIATED) {
                LOG_WRN("WiFi disconnected during resource recycling, reconnecting");
                k_work_submit(&reconnect_work);
                k_sleep(K_MSEC(5000)); /* Wait for reconnection */
            }
        }
       
        /* Run garbage collection */
        k_yield();
       
        /* Reset consecutive failures counter */
        consecutive_socket_failures = 0;
    }

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

    static bool connected;

    /* Track WiFi connection state */
    static bool wifi_connected = false;
    static bool wifi_reconnect_in_progress = false;

    /* 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 *hostname, const char *port_str, bool use_tls);
    static int 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 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(const struct shell *sh, size_t argc, char **argv)
    {
        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))) {
    #if DEBUG_GENERAL
            LOG_INF("Status request failed");
    #endif
            return -ENOEXEC;
        }

        /* Always show SSID and connection state regardless of debug level */
        LOG_INF("==================");
        LOG_INF("State: %s", wifi_state_txt(status.state));
       
        if (status.state >= WIFI_STATE_ASSOCIATED) {
            LOG_INF("SSID: %.32s", status.ssid);
        }

    #if DEBUG_WIFI_CONN
        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("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);
        }
    #endif
        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 (status->status) {
            LOG_ERR("Connection failed (%d)", status->status);
            context.connected = false;
            wifi_connected = false;
        } else {
            LOG_INF("Connected");
            context.connected = true;
            wifi_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 (status->status) {
            LOG_ERR("Connection request failed (%d)", status->status);
        } else {
            LOG_INF("Disconnected from WiFi");
            context.connected = false;
            wifi_connected = false;
           
            /* Close all active sockets when WiFi disconnects */
            close_all_sockets();
           
            /* Clean up TLS credentials */
            cleanup_tls_credentials();
           
            /* Schedule reconnection work */
            k_work_submit(&reconnect_work);
        }
       
        context.connect_result = true;  /* Use connect_result instead of disconnect_result */
    }

    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)
    {
        struct net_if_dhcpv4 *dhcpv4 = (struct net_if_dhcpv4 *)cb->info;
       
        if (dhcpv4 && dhcpv4->state == NET_DHCPV4_BOUND) {
            LOG_INF("IPv4 address: %s", net_sprint_ipv4_addr(&dhcpv4->requested_ip));
            LOG_INF("Lease time: %u seconds", dhcpv4->lease_time);
            LOG_INF("Subnet: %s", net_sprint_ipv4_addr(&dhcpv4->netmask));
        }
    }

    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;
    }

    static void net_event_handler(struct net_mgmt_event_callback *cb,
                     uint32_t mgmt_event, struct net_if *iface)
    {
        if (mgmt_event == NET_EVENT_L4_CONNECTED) {
            LOG_INF("Connected");
        } else if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
            LOG_INF("Disconnected");
        }
    }

    static int reconnect_wifi(void)
    {
        int ret;
        int attempts = 0;
       
        if (wifi_reconnect_in_progress) {
            LOG_INF("WiFi reconnection already in progress");
            return 0;
        }
       
        wifi_reconnect_in_progress = true;
       
        while (attempts < MAX_WIFI_RECONNECT_ATTEMPTS && !context.connected) {
            LOG_INF("Attempting WiFi reconnection (%d/%d)...",
                attempts + 1, MAX_WIFI_RECONNECT_ATTEMPTS);
           
            /* Reset connection state */
            context.connected = false;
            context.connect_result = false;
           
            /* Request WiFi connection */
            ret = wifi_connect();
            if (ret) {
                LOG_ERR("Failed to request WiFi connection: %d", ret);
                attempts++;
                k_sleep(K_MSEC(WIFI_RECONNECT_DELAY_MS));
                continue;
            }
           
            /* Wait for connection result */
            int timeout_counter = 0;
            const int max_timeout = 15; // 15 seconds timeout
           
            while (!context.connect_result && timeout_counter < max_timeout) {
                k_sleep(K_MSEC(1000));
                timeout_counter++;
            }
           
            if (context.connected) {
                LOG_INF("WiFi reconnection successful");
                wifi_connected = true;
                wifi_reconnect_in_progress = false;
                return 0;
            }
           
            attempts++;
            k_sleep(K_MSEC(WIFI_RECONNECT_DELAY_MS));
        }
       
        LOG_ERR("Failed to reconnect to WiFi after %d attempts", attempts);
        wifi_reconnect_in_progress = false;
        return -ETIMEDOUT;
    }

    static int connect_to_server(const char *hostname, const char *port_str, bool use_tls)
    {
        int err;
        int sock;
        int retry_count = 0;
        int port;
        struct zsock_addrinfo hints = {0};
        struct zsock_addrinfo *result;
        struct zsock_addrinfo *addr;
        struct zsock_pollfd fds;
        int flags;
        int ret;
        bool is_connected = false;
        struct timeval timeout;
       
        /* Check if WiFi is connected before attempting socket operations */
        if (!context.connected) {
            LOG_ERR("WiFi not connected, cannot create socket");
            return -ENETUNREACH;
        }
       
        /* Convert port string to integer */
        port = atoi(port_str);
        if (port <= 0 || port > 65535) {
            LOG_ERR("Invalid port number: %s", port_str);
            return -EINVAL;
        }
       
        /* Clean up any unhealthy sockets before creating a new one */
        cleanup_unhealthy_sockets();
       
        /* Set up hints for getaddrinfo */
        hints.ai_family = AF_INET;  /* IPv4 only for now */
        hints.ai_socktype = SOCK_STREAM;
       
        /* Resolve the hostname */
        LOG_INF("Resolving hostname: %s", hostname);
        err = zsock_getaddrinfo(hostname, port_str, &hints, &result);
        if (err) {
            LOG_ERR("Failed to resolve hostname %s: %d", hostname, err);
            return -EHOSTUNREACH;
        }
       
        /* Try each address until we successfully connect */
        for (addr = result; addr != NULL; addr = addr->ai_next) {
            /* Create socket */
            retry_count = 0;
            while (retry_count < MAX_SOCKET_RETRIES) {
                sock = zsock_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
                if (sock < 0) {
                    LOG_ERR("Failed to create socket, attempt %d/%d: %d",
                            retry_count + 1, MAX_SOCKET_RETRIES, errno);
                    consecutive_socket_failures++;
                   
                    if (consecutive_socket_failures >= MAX_CONSECUTIVE_FAILURES) {
                        LOG_ERR("Too many consecutive socket failures, forcing cleanup");
                        force_socket_cleanup();
                    }
                   
                    retry_count++;
                    k_sleep(K_MSEC(500));  /* Wait before retrying */
                    continue;
                }
               
                /* Track the socket immediately after creation */
                track_socket(sock);
               
                /* Set socket options */
                /* Set SO_REUSEADDR option */
                int reuse = 1;
                ret = zsock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
                if (ret < 0) {
                    LOG_WRN("Failed to set SO_REUSEADDR: %d", errno);
                    /* Continue anyway, not critical */
                }
               
                /* Set receive timeout */
                timeout.tv_sec = SOCKET_RECV_TIMEOUT_SEC;
                timeout.tv_usec = 0;
                ret = zsock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
                if (ret < 0) {
                    if (errno == ENOTSUP) {
                        LOG_WRN("Socket receive timeout not supported on this platform");
                    } else {
                        LOG_WRN("Failed to set receive timeout: %d", errno);
                    }
                    /* Continue anyway, not critical */
                }
               
                /* Set send timeout */
                timeout.tv_sec = SOCKET_SEND_TIMEOUT_SEC;
                timeout.tv_usec = 0;
                ret = zsock_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
                if (ret < 0) {
                    if (errno == ENOTSUP) {
                        LOG_WRN("Socket send timeout not supported on this platform");
                    } else {
                        LOG_WRN("Failed to set send timeout: %d", errno);
                    }
                    /* Continue anyway, not critical */
                }
               
                /* Set up TLS if requested */
                if (use_tls) {
                    /* Set up TLS credentials */
                    ret = setup_tls_credentials();
                    if (ret < 0) {
                        LOG_ERR("Failed to set up TLS credentials: %d", ret);
                        close(sock);
                        untrack_socket(sock);
                        zsock_freeaddrinfo(result);
                        return ret;
                    }
                   
                    /* Try with minimal TLS settings - just securely connect without strict verification */
                    LOG_INF("Proceeding with TLS connection with minimal verification");
                   
                    /* Skip setting TLS options if they're not supported */
                }
               
                /* Connect to server with timeout */
                LOG_INF("Connecting to %s:%s...", hostname, port_str);
               
                /* Set socket to non-blocking mode for connect with timeout */
                flags = zsock_fcntl(sock, ZSOCK_F_GETFL, 0);
                zsock_fcntl(sock, ZSOCK_F_SETFL, flags | ZSOCK_O_NONBLOCK);
               
                /* Initiate connection */
                ret = zsock_connect(sock, addr->ai_addr, addr->ai_addrlen);
                if (ret < 0 && errno != EINPROGRESS) {
                    LOG_ERR("Failed to initiate connection: %d", errno);
                    close(sock);
                    untrack_socket(sock);
                    retry_count++;
                    k_sleep(K_MSEC(500));  /* Wait before retrying */
                    continue;
                }
               
                /* Wait for connection to complete or timeout */
                fds.fd = sock;
                fds.events = ZSOCK_POLLOUT;
                int timeout_ms = use_tls ?
                    TLS_SOCKET_CONNECT_TIMEOUT_SEC * 1000 :
                    SOCKET_CONNECT_TIMEOUT_SEC * 1000;
               
                ret = zsock_poll(&fds, 1, timeout_ms);
                if (ret <= 0) {
                    if (ret == 0) {
                        LOG_ERR("Connection timed out");
                    } else {
                        LOG_ERR("Poll error: %d", errno);
                    }
                    close(sock);
                    untrack_socket(sock);
                    retry_count++;
                    k_sleep(K_MSEC(500));  /* Wait before retrying */
                    continue;
                }
               
                /* Check if connection was successful */
                if (fds.revents & ZSOCK_POLLOUT) {
                    /* Socket is writable, but we need to check for errors */
                    int err_code;
                    socklen_t err_len = sizeof(err_code);
                    ret = zsock_getsockopt(sock, SOL_SOCKET, SO_ERROR, &err_code, &err_len);
                    if (ret < 0 || err_code != 0) {
                        LOG_ERR("Connection failed with error: %d", err_code);
                        close(sock);
                        untrack_socket(sock);
                        retry_count++;
                        k_sleep(K_MSEC(500));  /* Wait before retrying */
                        continue;
                    }
                   
                    /* Connection successful */
                    is_connected = true;
                } else {
                    /* Socket has error condition */
                    LOG_ERR("Connection failed with revents: 0x%x", fds.revents);
                    close(sock);
                    untrack_socket(sock);
                    retry_count++;
                    k_sleep(K_MSEC(500));  /* Wait before retrying */
                    continue;
                }
               
                /* Set socket back to blocking mode */
                zsock_fcntl(sock, ZSOCK_F_SETFL, flags);
               
                /* If we got here, we successfully connected */
                if (is_connected) {
                    LOG_INF("Successfully connected to %s:%s", hostname, port_str);
                    consecutive_socket_failures = 0;  /* Reset failure counter on success */
                    zsock_freeaddrinfo(result);
                    return sock;
                }
            }
           
            /* If we've exhausted all retry attempts for this address, try the next one */
            LOG_WRN("Failed to connect using current address after %d attempts, trying next", MAX_SOCKET_RETRIES);
        }
       
        /* If we get here, we failed to connect to any address */
        zsock_freeaddrinfo(result);
        LOG_ERR("Failed to connect to %s:%s after trying all available addresses", hostname, port_str);
        return -ECONNREFUSED;
    }

    static int perform_http_get(int sock, const char *server, const char *path)
    {
        char http_request[256];
        int request_len;
        int sent;
        int total_sent = 0;
        int received;
        char recv_buf[1024];
        int ret = 0;
       
        /* Check WiFi connection before HTTP operation */
        if (!context.connected) {
            LOG_ERR("WiFi not connected before HTTP operation, attempting to reconnect");
            ret = reconnect_wifi();
            if (ret < 0) {
                LOG_ERR("Failed to reconnect WiFi: %d", ret);
                return ret;
            }
        }
       
        /* Formulate HTTP GET request */
        request_len = snprintf(http_request, sizeof(http_request),
                      "GET %s HTTP/1.1\r\n"
                      "Host: %s\r\n"
                      "Connection: close\r\n"
                      "\r\n",
                      path, server);
       
        if (request_len >= sizeof(http_request)) {
            LOG_ERR("HTTP request too large for buffer");
            return -ENOMEM;
        }
       
        /* Send HTTP request with timeout protection */
    #if DEBUG_AZURE
        LOG_INF("Sending HTTP GET request to %s%s", server, path);
    #endif
        int retry_count = 0;
        const int MAX_SEND_RETRIES = 3;
       
        do {
            /* Check WiFi connection before sending */
            if (!context.connected) {
                LOG_ERR("WiFi disconnected before HTTP send, attempting to reconnect");
                ret = reconnect_wifi();
                if (ret < 0) {
                    LOG_ERR("Failed to reconnect WiFi: %d", ret);
                    return ret;
                }
            }
           
            sent = zsock_send(sock, http_request + total_sent, request_len - total_sent, 0);
            if (sent < 0) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    /* Socket would block, wait and retry */
                    if (retry_count < MAX_SEND_RETRIES) {
                        LOG_WRN("Socket send would block, retrying (%d/%d)",
                            retry_count + 1, MAX_SEND_RETRIES);
                        k_sleep(K_MSEC(1000));
                        retry_count++;
                        continue;
                    } else {
                        LOG_ERR("Failed to send after %d retries", MAX_SEND_RETRIES);
                        return -ETIMEDOUT;
                    }
                } else {
                    LOG_ERR("Failed to send HTTP request: %d", errno);
                    return -errno;
                }
            }
            total_sent += sent;
        } while (total_sent < request_len);
       
        /* Receive HTTP response with timeout protection */
    #if DEBUG_AZURE
        LOG_INF("HTTP request sent, waiting for response...");
    #endif
       
        retry_count = 0;
        const int MAX_RECV_RETRIES = 5;
        bool response_complete = false;
       
        while (!response_complete) {
            /* Check WiFi connection before receiving */
            if (!context.connected) {
                LOG_ERR("WiFi disconnected during HTTP receive, attempting to reconnect");
                ret = reconnect_wifi();
                if (ret < 0) {
                    LOG_ERR("Failed to reconnect WiFi: %d", ret);
                    return ret;
                }
            }
           
            received = zsock_recv(sock, recv_buf, sizeof(recv_buf) - 1, 0);
            if (received < 0) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    /* Socket would block, wait and retry */
                    if (retry_count < MAX_RECV_RETRIES) {
                        LOG_WRN("Socket receive would block, retrying (%d/%d)",
                            retry_count + 1, MAX_RECV_RETRIES);
                        k_sleep(K_MSEC(1000));
                        retry_count++;
                        continue;
                    } else {
                        LOG_ERR("Failed to receive after %d retries", MAX_RECV_RETRIES);
                        return -ETIMEDOUT;
                    }
                } else {
                    LOG_ERR("Failed to receive HTTP response: %d", errno);
                    return -errno;
                }
            }
           
            if (received == 0) {
                /* Connection closed by server */
                response_complete = true;
                break;
            }
           
            /* Null-terminate the received data for printing */
            recv_buf[received] = 0;
    #if DEBUG_AZURE
            LOG_INF("%s", recv_buf);
    #endif
           
            /* Check for HTTP response code */
            if (strstr(recv_buf, "HTTP/1.1 200") != NULL ||
                strstr(recv_buf, "HTTP/1.0 200") != NULL) {
                /* 200 OK response */
                ret = 0;
            } else if (strstr(recv_buf, "HTTP/1.1 4") != NULL ||
                       strstr(recv_buf, "HTTP/1.0 4") != NULL) {
                /* 4xx Client Error */
                LOG_ERR("HTTP client error response");
                ret = -EBADMSG;
            } else if (strstr(recv_buf, "HTTP/1.1 5") != NULL ||
                       strstr(recv_buf, "HTTP/1.0 5") != NULL) {
                /* 5xx Server Error */
                LOG_ERR("HTTP server error response");
                ret = -EIO;  /* Using standard EIO instead of EREMOTEIO */
            }
        }
       
        /* Force memory cleanup after HTTP operations */
        k_sleep(K_MSEC(500));
        k_yield();
       
        return ret;
    }

    static int get_azure_auth_token(void)
    {
        int sock;
        int ret;
       
        LOG_INF("Getting Azure authentication token...");
        LOG_INF("Connecting to westeurope.api.cognitive.microsoft.com...");
       
        sock = connect_to_server("westeurope.api.cognitive.microsoft.com", "443", true);
        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);
       
        /* Send HTTP request matching exactly your C code */
        char http_request[512];
        int request_len;
       
        /* Notice this matches your C implementation exactly */
        request_len = snprintf(http_request, sizeof(http_request),
            "POST /sts/v1.0/issuetoken HTTP/1.1\r\n"
            "Host: westeurope.api.cognitive.microsoft.com\r\n"
            "Ocp-Apim-Subscription-Key: %s\r\n"
            "Content-Type: application/x-www-form-urlencoded\r\n"
            "Content-Length: 0\r\n"
            "\r\n",
            "5Mkszj3yFl2vmbRDchDUHDAOMiZAYmzaLzA508JrnpRYYKBsv4nqJQQJ99BCAC5RqLJXJ3w3AAAYACOGVfQg");
       
        LOG_INF("Sending HTTP request to Azure authentication server");
       
        /* Send the request */
        int sent;
        int total_sent = 0;
       
        do {
            sent = zsock_send(sock, http_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("HTTP request sent: %d bytes", total_sent);
        LOG_INF("Waiting for HTTP response...");
       
        /* Receive HTTP response */
        char recv_buf[2048];
        int received;
        int total_received = 0;
       
        while (1) {
            received = zsock_recv(sock, recv_buf + total_received,
                                sizeof(recv_buf) - 1 - total_received, 0);
           
            if (received < 0) {
                if (errno == ECONNRESET) {
                    LOG_WRN("Connection reset by peer");
                    /* Break if we already received some data */
                    if (total_received > 0) {
                        break;
                    } else {
                        disconnect_from_server(sock);
                        return -EIO;
                    }
                } else {
                    LOG_ERR("Failed to receive HTTP response, err: %d", errno);
                    disconnect_from_server(sock);
                    return -errno;
                }
            } else if (received == 0) {
                /* Connection closed by server */
                LOG_INF("Connection closed by server");
                break;
            } else {
                total_received += received;
                recv_buf[total_received] = '\0';
               
                LOG_INF("Received %d bytes (total: %d)", received, total_received);
               
                /* Print the response for debugging */
                if (total_received > 0) {
                    LOG_INF("Response: %s", recv_buf);
                }
            }
        }
       
        /* Disconnect from server */
        disconnect_from_server(sock);
       
        if (total_received > 0) {
            LOG_INF("Azure authentication successful");
            return 0;
        } else {
            LOG_ERR("Azure authentication failed - no data received");
            return -EIO;
        }
    }

    static void reconnect_work_handler(struct k_work *work)
    {
        ARG_UNUSED(work);
       
        if (!context.connected && !wifi_reconnect_in_progress) {
            reconnect_wifi();
        }
    }

    static void wifi_status_thread(void *p1, void *p2, void *p3)
    {
        ARG_UNUSED(p1);
        ARG_UNUSED(p2);
        ARG_UNUSED(p3);
       
        int consecutive_disconnects = 0;
        const int MAX_CONSECUTIVE_DISCONNECTS = 5;
        int check_interval = 5; /* seconds */
       
        while (1) {
            k_sleep(K_SECONDS(check_interval));
           
            if (context.connected) {
                LOG_INF("WiFi State: CONNECTED");
                consecutive_disconnects = 0;
                check_interval = 5; /* Normal check interval when connected */
            } else {
                LOG_INF("WiFi State: DISCONNECTED");
                consecutive_disconnects++;
               
                if (consecutive_disconnects >= MAX_CONSECUTIVE_DISCONNECTS) {
                    LOG_ERR("Multiple consecutive disconnects detected (%d), forcing reconnection",
                        consecutive_disconnects);
                   
                    /* Close all sockets to free resources */
                    close_all_sockets();
                   
                    /* Clean up TLS credentials */
                    cleanup_tls_credentials();
                   
                    /* Force reconnection */
                    if (!wifi_reconnect_in_progress) {
                        reconnect_wifi();
                    }
                   
                    consecutive_disconnects = 0;
                }
               
                /* More frequent checks when disconnected */
                check_interval = 2;
            }
           
            /* Check for any socket leaks */
            int active_count = 0;
            k_mutex_lock(&socket_mutex, K_FOREVER);
            for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
                if (active_sockets_array[i] >= 0) {
                    active_count++;
                }
            }
            k_mutex_unlock(&socket_mutex);
           
            if (active_count > 0) {
                LOG_WRN("%d active sockets tracked", active_count);
            }
        }
    }

    K_THREAD_DEFINE(wifi_status_thread_id, 1024, wifi_status_thread, NULL, NULL, NULL,
            7, 0, 0);

    static int start_app(void)
    {
        int ret;

        LOG_INF("Starting application...");

        /* Initialize LED */
        if (!device_is_ready(led.port)) {
            LOG_ERR("LED device not ready");
            return -ENODEV;
        }

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

        /* Initialize net_mgmt callbacks */
        net_mgmt_callback_init();
       
        /* Initialize work queue for reconnection */
        k_work_init(&reconnect_work, reconnect_work_handler);

        /* Connect to WiFi network */
        ret = wifi_connect();
        if (ret) {
            LOG_ERR("Failed to connect to WiFi: %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;
        }
       
        wifi_connected = true;
       
        /* 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(context.sh, 0, NULL);
       
        /* Get 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)
    {
        if (gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE) < 0) {
            LOG_ERR("Error: Failed to configure LED pin");
            return 0;
        }

        net_mgmt_callback_init();

    #ifdef CONFIG_WIFI_READY_LIB
        register_wifi_ready();
    #endif /* CONFIG_WIFI_READY_LIB */

        /* Initialize socket tracking array */
        for (int i = 0; i < MAX_TRACKED_SOCKETS; i++) {
            active_sockets_array[i] = -1;
        }

        start_app();
        return 0;
    }

    static int disconnect_from_server(int sock)
    {
        int ret;
       
        if (sock < 0) {
            LOG_WRN("Invalid socket handle %d, already disconnected", sock);
            return 0;
        }
       
        LOG_INF("Disconnecting from server, socket %d", sock);
       
        /* Untrack the socket before closing it */
        untrack_socket(sock);
       
        /* First try to gracefully shutdown the connection */
        ret = zsock_shutdown(sock, ZSOCK_SHUT_RDWR);
        if (ret < 0 && errno != ENOTCONN) {
            LOG_WRN("Socket shutdown failed: %d", errno);
            /* Continue with close anyway */
        }
       
        /* Close the socket */
        ret = close(sock);
        if (ret < 0) {
            LOG_ERR("Failed to close socket %d: %d", sock, errno);
            return -errno;
        }
       
        /* Verify socket is actually closed by attempting to get socket options */
        int error;
        socklen_t len = sizeof(error);
        ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len);
       
        if (ret == 0) {
            LOG_WRN("Socket %d appears to still be valid after close, forcing cleanup", sock);
            /* Socket is still valid, this shouldn't happen */
            force_socket_cleanup();
        } else {
            LOG_INF("Socket %d successfully closed", sock);
        }
       
        /* Add a small delay to allow system to free resources */
        k_sleep(K_MSEC(100));
       
        return 0;
    }
    ```

    And now I am getting this error:
    [00:00:11.878,631] <inf> main: State: COMPLETED
    [00:00:11.879,516] <inf> main: SSID: iPhone
    [00:00:11.880,310] <inf> main: Getting Azure authentication token...
    [00:00:11.881,408] <inf> main: Connecting to westeurope.api.cognitive.microsoft.com...
    [00:00:11.882,476] <inf> main: Checking for unhealthy sockets
    [00:00:11.883,361] <inf> main: Resolving hostname: westeurope.api.cognitive.microsoft.com
    [00:00:12.005,920] <inf> main: Tracking socket 14 in slot 0
    [00:00:12.006,713] <wrn> main: Failed to set receive timeout: 109
    [00:00:12.007,751] <wrn> main: Failed to set send timeout: 109
    [00:00:12.008,728] <inf> main: CA certificate added to TLS credentials
    [00:00:12.009,735] <inf> main: Proceeding with TLS connection with minimal verification
    [00:00:12.010,864] <inf> main: Connecting to westeurope.api.cognitive.microsoft.com:443...
    [00:00:12.112,976] <inf> main: Successfully connected to westeurope.api.cognitive.microsoft.com:443
    [00:00:12.114,349] <inf> main: Connected to Azure server, socket fd: 14
    [00:00:12.115,386] <inf> main: Sending HTTP request to Azure authentication server
    [00:00:12.117,279] <inf> main: HTTP request sent: 265 bytes
    [00:00:12.118,835] <inf> main: Waiting for HTTP response...
    [00:00:12.212,127] <wrn> main: Connection reset by peer
    [00:00:12.212,890] <inf> main: Disconnecting from server, socket 14
    [00:00:12.213,928] <inf> main: Untracking socket 14 from slot 0
    [00:00:12.214,935] <wrn> main: Socket shutdown failed: 134
    [00:00:12.216,033] <inf> main: Socket 14 successfully closed
    [00:00:12.317,047] <err> main: Azure authentication failed: -5
    [00:00:14.300,567] <inf> main: WiFi State: CONNECTED
Related