Skip to content

Conversation

@abhik-roy85
Copy link
Collaborator

@abhik-roy85 abhik-roy85 commented Nov 12, 2025

Description

Helper Note for Reviewers

This PR ports protocol_examples_common into a standalone net_connect component. Most diffs are renames or file moves. The key areas that deserve focused review are listed below.

✅ Important Areas to Review:

  1. New WiFi Configuration Architecture
  • Introduces a two-phase API:
    • net_configure_wifi_sta()
    • net_connect_wifi()
  • Adds new structures: net_wifi_sta_config_t, net_ip_config_t, net_iface_handle_t.
  1. Refactored WiFi Connection Flow
  • net_connect() now checks net_connect_wifi_is_configured().
  • Falls back to Kconfig defaults if needed.
  • Clean separation between configuration and connection logic.
  1. Internal WiFi State Management
  • New static state:
    s_wifi_sta_config, s_wifi_sta_handle, s_wifi_sta_configured
  • Helpers added for Kconfig-to-runtime translation.
  1. Public API Renaming
  • example_*net_* across the component.
  • API-breaking but consistent with new component structure.
  1. New / Updated Component Files
  • include/net_connect_wifi_config.h

You can skip reviewing pure renames, file moves, minor formatting or logging changes, and straightforward Kconfig or metadata updates.

Related

Testing


Checklist

Before submitting a Pull Request, please ensure the following:

  • 🚨 This PR does not introduce breaking changes.
  • All CI checks (GH Actions) pass.
  • Documentation is updated as needed.
  • Tests are updated or added as necessary.
  • Code is well-commented, especially in complex areas.
  • Git history is clean — commits are squashed to the minimum necessary.

Note

Introduces a standalone net_connect component with unified connect/disconnect for WiFi, Ethernet, Thread, and PPP, a new two-phase WiFi configuration API, example app, and unit tests.

  • Net Connect Component (components/net_connect):
    • Core APIs: net_connect, net_disconnect, net_get_netif_from_desc, net_configure_stdin_stdout in connect.c/include/net_connect.h.
    • WiFi:
      • New config API and structs in include/net_connect_wifi_config.h (net_wifi_sta_config_t, net_ip_config_t, net_configure_wifi_sta, net_connect_wifi, net_disconnect_wifi, net_connect_wifi_is_configured).
      • Refactored connection flow in wifi_connect.c; adds console commands in console_cmd.c.
    • Ethernet/Thread/PPP: Implement connection/shutdown flows with event handling and IP logging (eth_connect.c, thread_connect.c, ppp_connect.c).
    • Kconfig/Config: Adds Kconfig.projbuild for interface/IPv6 options; sdkconfig.rename mappings; component metadata (idf_component.yml).
    • Build/Deps: CMakeLists.txt with optional requires (console, esp_eth, openthread, tinyusb).
    • Example: examples/net_connect_example demonstrating unified connect/disconnect.
    • Tests: Unit tests for net_get_netif_from_desc with Unity/pytest harness under tests/unit_test.
  • Repo/CI:
    • Update .pre-commit-config.yaml to allow net_connect commit scope.
    • Include component in test_app/CMakeLists.txt.

Written by Cursor Bugbot for commit b20f0da. This will update automatically on new commits. Configure here.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from 24d6b84 to 712046b Compare November 20, 2025 11:34
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

#if CONFIG_NET_CONNECT_CONNECT_IPV6
xSemaphoreTake(s_semph_get_ip6_addrs, portMAX_DELAY);
#endif
return ESP_OK;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Ethernet connection hangs indefinitely if no IP

The net_connect_ethernet_connect function waits on s_semph_get_ip_addrs with portMAX_DELAY. If the Ethernet link is down or DHCP fails, the semaphore is never given, causing the application to hang indefinitely without a timeout or error return.

Fix in Cursor Fix in Web

@abhik-roy85 abhik-roy85 marked this pull request as draft November 20, 2025 12:06
Key features:
- Port network connection logic from protocol_examples_common into a standalone net_connect component.
- Provide unified APIs for WiFi, Ethernet, Thread, and PPP connectivity.
- Add comprehensive Kconfig options and example usage.
- Introduce programmatic WiFi STA configuration APIs:
  - net_configure_wifi_sta()
  - net_connect_wifi()
  - net_disconnect_wifi()
- Simplify WiFi connection flow and remove redundant config prefixes.
- Add backward-compatibility mappings via sdkconfig.rename.

Ethernet migration & cleanup:
- Migrate Ethernet setup to the new ethernet_init component.
- Simplify Kconfig by delegating Ethernet options to the main config.
- Add interface init/deinit logging.
- Fix missing Thread/PPP shutdown handlers.
- Remove obsolete net_get_eth_handle() API.

Misc:
- Update component structure, CMake files, and general cleanup.
@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from c94572e to c18c062 Compare December 2, 2025 10:28
@abhik-roy85 abhik-roy85 self-assigned this Dec 2, 2025
@abhik-roy85 abhik-roy85 marked this pull request as ready for review December 3, 2025 10:56
@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from f614be6 to 695a0cb Compare December 4, 2025 10:15
Copy link
Collaborator

@david-cermak david-cermak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a few high-level topics to talk about, no need to be addressed or fixed, just related to the structural/modular ideas of this component

Comment on lines +38 to +51
void net_connect_wifi_start(void);
void net_connect_wifi_stop(void);
esp_err_t net_connect_wifi_sta_do_connect(wifi_config_t wifi_config, bool wait);
esp_err_t net_connect_wifi_sta_do_disconnect(void);
bool net_connect_is_our_netif(const char *prefix, esp_netif_t *netif);
void net_connect_print_all_netif_ips(const char *prefix);
void net_connect_wifi_shutdown(void);
void net_connect_ethernet_shutdown(void);
esp_err_t net_connect_ethernet_connect(void);
void net_connect_thread_shutdown(void);
esp_err_t net_connect_thread_connect(void);
esp_err_t net_connect_ppp_connect(void);
void net_connect_ppp_start(void);
void net_connect_ppp_shutdown(void);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we somehow unify these methods across interfaces?

Matrix of wifi/ethernet/thead/ppp vs start/stop/connect/disconnect

}


esp_err_t net_disconnect(void)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we handle lifecycle of different interfaces? Do we support re-connect after disconnection for various interfaces?
i.e. Ethernet shutdown and reconnect while the Wi-Fi is connected?

#if CONFIG_NET_CONNECT_ETHERNET
ESP_LOGI(TAG, "Deinitializing Ethernet interface...");
net_connect_ethernet_shutdown();
ESP_ERROR_CHECK(esp_unregister_shutdown_handler(&net_connect_ethernet_shutdown));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we handle errors in more graceful way?

Applies to other places as well, uses ESP_ERROR_CHECK() in some places returns errors or error goto macros in others.

net_connect_wifi_stop();
}

net_iface_handle_t net_configure_wifi_sta(net_wifi_sta_config_t *config)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now wifi provides ample runtime configuration, while others are more or less Kconfig options.
should we unify this, or do we prefer runtime to compile-time config?

static const char *TAG = "ethernet_connect";
static SemaphoreHandle_t s_semph_get_ip_addrs = NULL;
#if CONFIG_NET_CONNECT_IPV6
static SemaphoreHandle_t s_semph_get_ip6_addrs = NULL;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the IPv6 be handled somehow globally, not per interface? Does it make sense to rework the architecture to provide netif-agnostic event/handlers, while keeping lifecycle netif/driver specific?

@@ -0,0 +1,66 @@
# net_connect
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also consider design for testablity? Suggest adding a simple unit test, just the see how the current design is modular/testable

#include "driver/uart.h"
#include "sdkconfig.h"

esp_err_t net_configure_stdin_stdout(void)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this API logically belong to this component?

}
}

static void ot_task_worker(void *aContext)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses worker thread, while other interfaces use sync calls. Should be use sync/async approach here?

@gabsuren
Copy link
Collaborator

gabsuren commented Dec 4, 2025

@abhik-roy85 General note: I didn’t see any CI or testing coverage mentioned in the PR or workflows.
Are there plans to add CI build/test validation for this component in a follow-up PR?

@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from 695a0cb to a8cef47 Compare December 4, 2025 11:22
{
if (s_semph_get_ip_addrs == NULL) {
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Ethernet IPv6-only shutdown skips resource cleanup

The net_connect_ethernet_shutdown() function checks if s_semph_get_ip_addrs == NULL to determine whether to proceed with cleanup and returns early if it's NULL. However, when only CONFIG_NET_CONNECT_IPV6 is enabled without CONFIG_NET_CONNECT_IPV4, s_semph_get_ip_addrs is never created and remains NULL. This causes the function to return early without cleaning up the IPv6 semaphore or stopping ethernet, leading to resource leaks. This scenario is common when Thread is enabled, since NET_CONNECT_IPV4 defaults to n for Thread configurations.

Fix in Cursor Fix in Web

#elif CONFIG_NET_CONNECT_PPP_DEVICE_UART
s_stop_task = true;
vTaskDelay(pdMS_TO_TICKS(1000)); // wait for the ppp task to stop
#endif
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: PPP UART missing cleanup on shutdown

When using PPP over UART, ppp_task() registers an event handler at line 163 (esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, esp_netif_action_connected, s_netif)), but net_connect_ppp_shutdown() only unregisters the on_ip_event handler and never unregisters esp_netif_action_connected. Additionally, the UART driver installed in ppp_task() via uart_driver_install() is never deleted during shutdown, causing a resource leak.

Additional Locations (1)

Fix in Cursor Fix in Web

esp_vfs_eventfd_unregister();
vSemaphoreDelete(s_semph_thread_set_dns_server);
vSemaphoreDelete(s_semph_thread_attached);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Thread event handler never unregistered on shutdown

In net_connect_thread_connect(), an event handler is registered with esp_event_handler_register(OPENTHREAD_EVENT, ESP_EVENT_ANY_ID, thread_event_handler, NULL) at line 120. However, net_connect_thread_shutdown() never calls esp_event_handler_unregister() to remove this handler. This leaves a dangling event handler registered after shutdown that could cause issues if the semaphores are deleted but events are still dispatched.

Additional Locations (1)

Fix in Cursor Fix in Web

xSemaphoreTake(s_semph_get_ip_addrs, portMAX_DELAY);
vSemaphoreDelete(s_semph_get_ip_addrs);
s_semph_get_ip_addrs = NULL;
#endif
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: WiFi semaphore leak when IPv4 disabled

In net_connect_wifi_sta_do_connect(), s_semph_get_ip_addrs is created unconditionally at line 188 when wait=true, but it's only deleted inside the #if CONFIG_NET_CONNECT_IPV4 block at lines 218-220. When CONFIG_NET_CONNECT_IPV4 is disabled (which is the default when Thread is enabled), the semaphore is created but never deleted, causing a memory leak. The creation should also be conditional on CONFIG_NET_CONNECT_IPV4, matching the deletion logic.

Fix in Cursor Fix in Web

memset(wifi_config.sta.password, 0, sizeof(wifi_config.sta.password));
temp = strtok_r(NULL, " ", &rest);
if (temp) {
strncpy((char*)wifi_config.sta.password, temp, sizeof(wifi_config.sta.password));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: WiFi stdin path missing null-termination for SSID/password

The strncpy calls at lines 312 and 316 use the full buffer size (sizeof(wifi_config.sta.ssid) and sizeof(wifi_config.sta.password)) without ensuring null-termination. This is inconsistent with convert_to_wifi_config() which correctly uses size - 1 and explicitly null-terminates. If a user enters an SSID of 32+ characters or password of 64+ characters from stdin, the resulting strings won't be null-terminated, potentially causing buffer over-reads when the WiFi stack processes these values.

Fix in Cursor Fix in Web

endif()


idf_component_register(SRCS "${srcs}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all these dependencies necessary?

@@ -0,0 +1,316 @@
menu "Net Connect Configuration"

orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why source from the example?

Choose the preferred interface (WiFi, Ethernet, Thread, PPPoS) to connect to the network and configure the interface.

It is possible to enable multiple interfaces simultaneously making the connection phase to block until all the chosen interfaces acquire IP addresses.
It is also possible to disable all interfaces, skipping the connection phase altogether.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what is the use of the component in this case?


### WiFi

Choose WiFi connection method (for chipsets that support it) and configure basic WiFi connection properties:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the device doesn't support it, we should provide the means for it, using esp_wifi_remote


#define HOST_IP_SIZE 128

esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_storage *dest_addr)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function seems to be a good fit for having a single point of return cleaning up allocated resources.

return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
}

static bool netif_desc_matches_with(esp_netif_t *netif, void *ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static bool netif_desc_matches_with(esp_netif_t *netif, void *ctx)
static bool netif_desc_matches_with(esp_netif_t *netif, char *ctx)

extern "C" {
#endif

#if !CONFIG_IDF_TARGET_LINUX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the guard are necessary for the defines.

#endif

#if CONFIG_NET_CONNECT_WIFI_SCAN_METHOD_FAST
#define NET_CONNECT_WIFI_SCAN_METHOD WIFI_FAST_SCAN
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to redefine WIFI related configs? Seems that this might lead us to compatibility issues in the future.

*/
esp_netif_t *net_get_netif_from_desc(const char *desc);

#if CONFIG_NET_CONNECT_PROVIDE_WIFI_CONSOLE_CMD
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be only available if WIFI is also enabled.

switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_ERROR_CHECK(esp_netif_create_ip6_linklocal(esp_netif));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Net Connect going to be a common component, we should stop using ESP_ERROR_CHECK (which asserts) and return error gracefully.

description: Network connection component providing WiFi, Ethernet, Thread, and PPP connection methods for ESP32 boards.
dependencies:
idf:
version: '>=5.0'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ethernet_init is compatible starting with IDF ver 5.4.3 (or more precisely '>=5.4.3,!=5.5.0,!=5.5.1'). Does it make sense to be this component compatible starting with 5.0?

#define NGX_UNESCAPE_REDIRECT (2)


uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, unsigned int type)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be part of net_connect component. It could rather be separate component.


#define HOST_IP_SIZE 128

esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_storage *dest_addr)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is not used by Net connect. It seems to be a common function not related to connect hence it should be separate component.

*/

/**
* @file net_connect_example.c
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this example built in CI?

esp_netif_action_connected(s_netif, 0, 0, 0);
#else // DEVICE is UART
s_stop_task = false;
if (xTaskCreate(ppp_task, "ppp connect", 4096, NULL, 5, NULL) != pdTRUE) {
Copy link
Collaborator

@alisitsyn alisitsyn Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the ppp task stack be configurable like for thread connection? May be other parameters can be configurable as well.

ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, BUF_SIZE, 0, 16, &event_queue, 0));
ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, CONFIG_NET_CONNECT_UART_TX_PIN, CONFIG_NET_CONNECT_UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_ERROR_CHECK(uart_set_rx_timeout(UART_NUM_1, 1));
Copy link
Collaborator

@alisitsyn alisitsyn Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the UART RX timeout feature used for PPP to separate the frames for netif? This should generate timeout event after 1 symbol silence time on current baudrate but also on fifo full event because the timeout flag on data event is not checked. Is this expected behavior? The data received on DATA event will never reach 1024 bytes of buffer allocated because the DATA event will come every fifo full event (usually 120 bytes). It is better to check the timeout flag of the event structure to handle the timeout event correctly instead of every fifo full event and then use the whole allocated buffer to transfer the data from UART to netif more effectively.

@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from a8cef47 to 76a84fa Compare December 5, 2025 10:32
s_semph_get_ip6_addrs = NULL;
#endif
eth_stop();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Ethernet shutdown skipped when only IPv6 enabled

The net_connect_ethernet_shutdown() function uses s_semph_get_ip_addrs == NULL as its guard condition to return early. However, when only IPv6 is enabled (not IPv4), this semaphore is never created because its creation is guarded by #if CONFIG_NET_CONNECT_IPV4. This causes the shutdown function to return immediately without calling eth_stop(), leaving the ethernet interface and resources unreleased in IPv6-only configurations.

Fix in Cursor Fix in Web

}
free(buffer);
vTaskDelete(NULL);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: UART driver and event handler leaked in PPP shutdown

When using UART for PPP, the ppp_task installs the UART driver at line 150 and registers an event handler at line 163, but neither is cleaned up on shutdown. When s_stop_task is set and the task exits, it only frees the buffer and deletes itself without calling uart_driver_delete(). The net_connect_ppp_shutdown() function also doesn't unregister the esp_netif_action_connected handler. This causes resource leaks and prevents proper re-initialization.

Additional Locations (1)

Fix in Cursor Fix in Web

return ESP_FAIL;
}
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
memcpy(dest_addr, cur->ai_addr, sizeof(*dest_addr));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Buffer over-read when copying address from getaddrinfo result

The memcpy copies sizeof(*dest_addr) bytes (typically 128 bytes for struct sockaddr_storage) from cur->ai_addr, but getaddrinfo allocates only enough memory for the actual address type - 16 bytes for sockaddr_in (IPv4) or 28 bytes for sockaddr_in6 (IPv6). This reads beyond the allocated memory bounds, causing undefined behavior. The copy size should use cur->ai_addrlen instead of sizeof(*dest_addr).

Fix in Cursor Fix in Web

esp_vfs_eventfd_unregister();
vSemaphoreDelete(s_semph_thread_set_dns_server);
vSemaphoreDelete(s_semph_thread_attached);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Thread event handler never unregistered on shutdown

The thread_event_handler registered via esp_event_handler_register(OPENTHREAD_EVENT, ...) at line 120 in net_connect_thread_connect() is never unregistered in net_connect_thread_shutdown(). This causes a resource leak and the handler could be invoked after shutdown, potentially accessing deleted semaphores s_semph_thread_attached and s_semph_thread_set_dns_server.

Fix in Cursor Fix in Web

Addresses code review feedback from GitHub cursor bot.
Add comprehensive unit test suite for net_get_netif_from_desc() function
with 11 test cases covering:

- Successful lookup for different netif types (STA, ETH, Thread, PPP, custom)
- Error handling for NULL, empty string, and non-existent descriptions
- Edge cases including case-sensitive matching, exact match requirements,
  and consistency across multiple calls

The test suite uses Unity test framework with proper setup/teardown for
netif creation and memory leak detection. Includes CMakeLists.txt files
for build configuration and pytest integration for CI/CD.
@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from 76a84fa to 5211944 Compare December 5, 2025 12:33
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();

Check warning

Code scanning / clang-tidy

The value '153' provided to the cast expression is not in the valid range of values for 'esp_netif_flags' [clang-analyzer-optin.core.EnumCastOutOfRange] Warning

The value '153' provided to the cast expression is not in the valid range of values for 'esp_netif_flags' [clang-analyzer-optin.core.EnumCastOutOfRange]
}
}
free(buffer);
vTaskDelete(NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: PPP UART task leaks UART driver on exit

The ppp_task function installs the UART driver at line 150 and registers an event handler at line 163, but when the task exits normally (lines 181-182), neither resource is cleaned up. The UART driver is never deleted with uart_driver_delete() and the IP_EVENT_PPP_GOT_IP event handler registered with esp_netif_action_connected is never unregistered. This causes resource leaks that prevent proper re-initialization of the PPP connection.

Additional Locations (1)

Fix in Cursor Fix in Web

esp_vfs_eventfd_unregister();
vSemaphoreDelete(s_semph_thread_set_dns_server);
vSemaphoreDelete(s_semph_thread_attached);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Thread event handler never unregistered during shutdown

In net_connect_thread_connect(), an event handler for OPENTHREAD_EVENT is registered at line 120, but net_connect_thread_shutdown() never calls esp_event_handler_unregister() to remove it. This causes the thread_event_handler callback to remain active after shutdown, potentially leading to crashes or undefined behavior if OpenThread events are received after resources are freed.

Additional Locations (1)

Fix in Cursor Fix in Web

ESP_LOGI(TAG, "WiFi shutdown handler called");
net_connect_wifi_sta_do_disconnect();
net_connect_wifi_stop();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: WiFi state flag not reset after shutdown

The s_wifi_sta_configured flag is set to true in net_configure_wifi_sta() but never reset to false in either net_connect_wifi_shutdown() or net_disconnect_wifi(). This means after a disconnect-reconnect cycle, the code incorrectly believes WiFi is already configured, and subsequent calls to net_connect() will skip reconfiguration and attempt to use stale state, potentially causing connection failures.

Additional Locations (1)

Fix in Cursor Fix in Web

char *temp = strtok_r(buf, " ", &rest);
if (temp == NULL) {
ESP_LOGE(TAG, "SSID is empty or invalid");
return ESP_ERR_INVALID_ARG;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: WiFi resources leaked when stdin input fails

When CONFIG_NET_CONNECT_WIFI_SSID_PWD_FROM_STDIN is enabled, net_connect_wifi_start() is called at line 291 to initialize the WiFi driver and create the netif. However, if fgets() fails at line 301 or strtok_r() returns NULL at line 312, the function returns early without calling net_connect_wifi_stop(). This leaves the WiFi driver initialized and the netif allocated, causing a resource leak that prevents proper re-initialization on subsequent connection attempts.

Fix in Cursor Fix in Web

}
}
free(buffer);
vTaskDelete(NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: PPP UART resource leak on shutdown

In PPP UART mode, ppp_task installs UART driver (line 150) and registers an event handler for IP_EVENT_PPP_GOT_IP with esp_netif_action_connected (line 163). When the task exits after s_stop_task becomes true, only buffer is freed. The UART driver is never deleted via uart_driver_delete(UART_NUM_1), and the event handler is never unregistered. The net_connect_ppp_shutdown function only unregisters on_ip_event, not the handler registered in ppp_task. This causes persistent resource leaks after shutdown.

Additional Locations (1)

Fix in Cursor Fix in Web

esp_vfs_eventfd_unregister();
vSemaphoreDelete(s_semph_thread_set_dns_server);
vSemaphoreDelete(s_semph_thread_attached);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Thread shutdown missing event handler unregistration

The thread_event_handler event handler registered in net_connect_thread_connect at line 120 is never unregistered during net_connect_thread_shutdown. This leaves a dangling event handler that could be invoked after shutdown with invalid semaphore handles, potentially causing undefined behavior or crashes.

Additional Locations (1)

Fix in Cursor Fix in Web

*/
bool net_connect_is_our_netif(const char *prefix, esp_netif_t *netif)
{
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Prefix comparison missing last character check

The net_connect_is_our_netif function uses strlen(prefix) - 1 as the comparison length in strncmp, which means the last character of the prefix is never compared. For example, with prefix "net_connect_netif_sta", only the first 20 characters are compared, so "net_connect_netif_stX" (where X is any character) would incorrectly match. The correct length comparison would be strlen(prefix).

Fix in Cursor Fix in Web

}
ESP_ERROR_CHECK(esp_register_shutdown_handler(&net_connect_ppp_shutdown));
ESP_LOGI(TAG, "PPP interface initialized successfully");
#endif
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: net_connect error path leaks previously initialized interfaces

In net_connect, when a later interface fails to initialize, previously initialized interfaces are not cleaned up. For example, if Ethernet succeeds (lines 98-105) but WiFi fails (lines 111-119), the function returns ESP_FAIL without calling net_connect_ethernet_shutdown() or unregistering its shutdown handler. This causes resource leaks for all interfaces that were successfully initialized before the failure.

Fix in Cursor Fix in Web

- Remove protocol_examples_utils and addr_from_stdin files
- Add null checks in ethernet shutdown to prevent crashes
- Add proper cleanup in wifi shutdown and error paths
- Update CMakeLists to reflect removed source files
@abhik-roy85 abhik-roy85 force-pushed the component/net_connect branch from 6ff42aa to b20f0da Compare December 10, 2025 12:44
esp_vfs_eventfd_unregister();
vSemaphoreDelete(s_semph_thread_set_dns_server);
vSemaphoreDelete(s_semph_thread_attached);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Thread event handler never unregistered during shutdown

The thread_event_handler is registered with esp_event_handler_register() in net_connect_thread_connect() but is never unregistered in net_connect_thread_shutdown(). This causes a resource leak and potential use-after-free if events are delivered after the semaphores s_semph_thread_attached and s_semph_thread_set_dns_server are deleted since the handler still references them via xSemaphoreGive().

Additional Locations (1)

Fix in Cursor Fix in Web

esp_netif_destroy(s_openthread_netif);
esp_vfs_eventfd_unregister();
vTaskDelete(NULL);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Thread task double-cleanup causes use-after-free

If esp_openthread_launch_mainloop() returns (due to an error), the task at lines 79-83 cleans up resources and deletes itself with vTaskDelete(NULL). However, s_ot_task_handle is never set to NULL by the task. When net_connect_thread_shutdown() is later called, it passes the stale handle to vTaskDelete() (use-after-free) and then calls the same cleanup functions (esp_openthread_netif_glue_deinit, esp_netif_destroy, esp_vfs_eventfd_unregister) again, causing double-free issues.

Additional Locations (1)

Fix in Cursor Fix in Web

}
}
free(buffer);
vTaskDelete(NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: PPP UART task leaks driver and event handler

The ppp_task installs a UART driver at line 150 but doesn't call uart_driver_delete(UART_NUM_1) when exiting normally after s_stop_task becomes true. Additionally, the event handler registered at line 163 for IP_EVENT_PPP_GOT_IP is never unregistered, leading to resource leaks and potential crashes if events are delivered after s_netif is destroyed.

Additional Locations (1)

Fix in Cursor Fix in Web

esp_err_t err = net_connect_wifi_sta_do_connect(wifi_config, true);
if (err != ESP_OK) {
return err;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: WiFi connection failure doesn't stop WiFi driver

In net_connect_wifi(), when net_connect_wifi_sta_do_connect() fails at line 334, the function returns the error without calling net_connect_wifi_stop(). Since net_connect_wifi_start() was called at line 293, this leaves the WiFi driver initialized and the netif created, causing resource leaks.

Fix in Cursor Fix in Web

*/
bool net_connect_is_our_netif(const char *prefix, esp_netif_t *netif)
{
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: strncmp uses incorrect length causing matching errors

The net_connect_is_our_netif() function uses strlen(prefix) - 1 as the comparison length for strncmp(). Since strlen() returns size_t (unsigned), if prefix is an empty string, this underflows to SIZE_MAX, causing undefined comparison behavior. For non-empty strings, omitting the last character from comparison could cause false positive matches if two netif descriptions differ only in their last character.

Fix in Cursor Fix in Web

s_eth_netif = esp_netif_new(&netif_config);

s_eth_glue = esp_eth_new_netif_glue(s_eth_handles[0]);
esp_netif_attach(s_eth_netif, s_eth_glue);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Ethernet netif creation not checked for NULL

In eth_start(), the return value of esp_netif_new() at line 93 is not checked for NULL before being used at line 96 in esp_netif_attach(). If netif creation fails due to memory exhaustion, this would pass a NULL pointer to esp_netif_attach(), potentially causing a crash.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants