mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-12-04 16:19:20 +01:00
434 lines
14 KiB
C
434 lines
14 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "sdkconfig.h"
|
|
#include "esp_log.h"
|
|
#include "esp_event.h"
|
|
#include "mdns.h"
|
|
#include "mdns_private.h"
|
|
#include "mdns_mem_caps.h"
|
|
#include "mdns_utils.h"
|
|
#include "mdns_debug.h"
|
|
#include "mdns_browser.h"
|
|
#include "mdns_netif.h"
|
|
#include "mdns_pcb.h"
|
|
#include "mdns_responder.h"
|
|
#include "mdns_service.h"
|
|
|
|
static const char *TAG = "mdns_netif";
|
|
|
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
#include "esp_eth.h"
|
|
#endif
|
|
|
|
#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 0)
|
|
#define MDNS_ESP_WIFI_ENABLED CONFIG_SOC_WIFI_SUPPORTED
|
|
#else
|
|
#define MDNS_ESP_WIFI_ENABLED (CONFIG_ESP_WIFI_ENABLED || CONFIG_ESP_WIFI_REMOTE_ENABLED)
|
|
#endif
|
|
|
|
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
|
|
#include "esp_wifi.h"
|
|
#endif
|
|
|
|
typedef enum {
|
|
MDNS_IF_STA = 0,
|
|
MDNS_IF_AP = 1,
|
|
MDNS_IF_ETH = 2,
|
|
} mdns_predef_if_t;
|
|
|
|
typedef struct mdns_interfaces mdns_interfaces_t;
|
|
|
|
struct mdns_interfaces {
|
|
const bool predefined;
|
|
esp_netif_t *netif;
|
|
const mdns_predef_if_t predef_if;
|
|
mdns_if_t duplicate;
|
|
};
|
|
|
|
/*
|
|
* @brief Internal collection of mdns supported interfaces
|
|
*
|
|
*/
|
|
static mdns_interfaces_t s_esp_netifs[MDNS_MAX_INTERFACES] = {
|
|
#if CONFIG_MDNS_PREDEF_NETIF_STA
|
|
{ .predefined = true, .netif = NULL, .predef_if = MDNS_IF_STA, .duplicate = MDNS_MAX_INTERFACES },
|
|
#endif
|
|
#if CONFIG_MDNS_PREDEF_NETIF_AP
|
|
{ .predefined = true, .netif = NULL, .predef_if = MDNS_IF_AP, .duplicate = MDNS_MAX_INTERFACES },
|
|
#endif
|
|
#if CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
{ .predefined = true, .netif = NULL, .predef_if = MDNS_IF_ETH, .duplicate = MDNS_MAX_INTERFACES },
|
|
#endif
|
|
};
|
|
|
|
/**
|
|
* @brief Helper to get either ETH or STA if the other is provided
|
|
* Used when two interfaces are on the same subnet
|
|
*/
|
|
mdns_if_t mdns_priv_netif_get_other_interface(mdns_if_t tcpip_if)
|
|
{
|
|
if (tcpip_if < MDNS_MAX_INTERFACES) {
|
|
return s_esp_netifs[tcpip_if].duplicate;
|
|
}
|
|
return MDNS_MAX_INTERFACES;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert Predefined interface to the netif id from the internal netif list
|
|
* @param predef_if Predefined interface enum
|
|
* @return Ordinal number of internal list of mdns network interface.
|
|
* Returns MDNS_MAX_INTERFACES if the predefined interface wasn't found in the list
|
|
*/
|
|
static mdns_if_t mdns_if_from_preset(mdns_predef_if_t predef_if)
|
|
{
|
|
for (int i = 0; i < MDNS_MAX_INTERFACES; ++i) {
|
|
if (s_esp_netifs[i].predefined && s_esp_netifs[i].predef_if == predef_if) {
|
|
return i;
|
|
}
|
|
}
|
|
return MDNS_MAX_INTERFACES;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert Predefined interface to esp-netif handle
|
|
* @param predef_if Predefined interface enum
|
|
* @return esp_netif pointer from system list of network interfaces
|
|
*/
|
|
static inline esp_netif_t *netif_from_preset(mdns_predef_if_t predef_if)
|
|
{
|
|
switch (predef_if) {
|
|
case MDNS_IF_STA:
|
|
return esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
|
|
case MDNS_IF_AP:
|
|
return esp_netif_get_handle_from_ifkey("WIFI_AP_DEF");
|
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
case MDNS_IF_ETH:
|
|
return esp_netif_get_handle_from_ifkey("ETH_DEF");
|
|
#endif
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
esp_netif_t *mdns_priv_get_esp_netif(mdns_if_t tcpip_if)
|
|
{
|
|
if (tcpip_if < MDNS_MAX_INTERFACES) {
|
|
if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined) {
|
|
// If the local copy is NULL and this netif is predefined -> we can find it in the global netif list
|
|
s_esp_netifs[tcpip_if].netif = netif_from_preset(s_esp_netifs[tcpip_if].predef_if);
|
|
// failing to find it means that the netif is *not* available -> return NULL
|
|
}
|
|
return s_esp_netifs[tcpip_if].netif;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* @brief Clean internal mdns interface's pointer
|
|
*/
|
|
void mdns_priv_netif_disable(mdns_if_t tcpip_if)
|
|
{
|
|
if (tcpip_if < MDNS_MAX_INTERFACES) {
|
|
s_esp_netifs[tcpip_if].netif = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @brief Convert esp-netif handle to mdns if
|
|
*/
|
|
static mdns_if_t get_if_from_netif(esp_netif_t *esp_netif)
|
|
{
|
|
for (int i = 0; i < MDNS_MAX_INTERFACES; ++i) {
|
|
// The predefined netifs in the static array are NULL when firstly calling this function
|
|
// if IPv4 is disabled. Set these netifs here.
|
|
if (s_esp_netifs[i].netif == NULL && s_esp_netifs[i].predefined) {
|
|
s_esp_netifs[i].netif = netif_from_preset(s_esp_netifs[i].predef_if);
|
|
}
|
|
if (esp_netif == s_esp_netifs[i].netif) {
|
|
return i;
|
|
}
|
|
}
|
|
return MDNS_MAX_INTERFACES;
|
|
}
|
|
|
|
static esp_err_t post_custom_action(mdns_if_t mdns_if, mdns_event_actions_t event_action)
|
|
{
|
|
if (!mdns_priv_is_server_init() || mdns_if >= MDNS_MAX_INTERFACES) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
mdns_action_t *action = (mdns_action_t *)mdns_mem_calloc(1, sizeof(mdns_action_t));
|
|
if (!action) {
|
|
HOOK_MALLOC_FAILED;
|
|
return ESP_ERR_NO_MEM;
|
|
}
|
|
action->type = ACTION_SYSTEM_EVENT;
|
|
action->data.sys_event.event_action = event_action;
|
|
action->data.sys_event.interface = mdns_if;
|
|
|
|
if (!mdns_priv_queue_action(action)) {
|
|
mdns_mem_free(action);
|
|
}
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Dispatch interface changes based on system events
|
|
*/
|
|
static inline void post_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol)
|
|
{
|
|
post_custom_action(mdns_if_from_preset(preset_if),
|
|
protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_DISABLE_IP4 : MDNS_EVENT_DISABLE_IP6);
|
|
}
|
|
|
|
static inline void post_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol)
|
|
{
|
|
post_custom_action(mdns_if_from_preset(preset_if),
|
|
protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ENABLE_IP4 : MDNS_EVENT_ENABLE_IP6);
|
|
}
|
|
|
|
static inline void post_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol)
|
|
{
|
|
post_custom_action(mdns_if_from_preset(preset_if),
|
|
protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ANNOUNCE_IP4 : MDNS_EVENT_ANNOUNCE_IP6);
|
|
}
|
|
|
|
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
static void handle_system_event_for_preset(void *arg, esp_event_base_t event_base,
|
|
int32_t event_id, void *event_data)
|
|
{
|
|
if (!mdns_priv_is_server_init()) {
|
|
return;
|
|
}
|
|
|
|
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
|
|
if (event_base == WIFI_EVENT) {
|
|
esp_netif_dhcp_status_t dcst;
|
|
switch (event_id) {
|
|
case WIFI_EVENT_STA_CONNECTED:
|
|
if (!esp_netif_dhcpc_get_status(netif_from_preset(MDNS_IF_STA), &dcst)) {
|
|
if (dcst == ESP_NETIF_DHCP_STOPPED) {
|
|
post_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4);
|
|
}
|
|
}
|
|
break;
|
|
case WIFI_EVENT_STA_DISCONNECTED:
|
|
post_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4);
|
|
post_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6);
|
|
break;
|
|
case WIFI_EVENT_AP_START:
|
|
post_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4);
|
|
break;
|
|
case WIFI_EVENT_AP_STOP:
|
|
post_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4);
|
|
post_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else
|
|
#endif
|
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
if (event_base == ETH_EVENT) {
|
|
esp_netif_dhcp_status_t dcst;
|
|
switch (event_id) {
|
|
case ETHERNET_EVENT_CONNECTED:
|
|
if (!esp_netif_dhcpc_get_status(netif_from_preset(MDNS_IF_ETH), &dcst)) {
|
|
if (dcst == ESP_NETIF_DHCP_STOPPED) {
|
|
post_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4);
|
|
}
|
|
}
|
|
break;
|
|
case ETHERNET_EVENT_DISCONNECTED:
|
|
post_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4);
|
|
post_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else
|
|
#endif
|
|
if (event_base == IP_EVENT) {
|
|
switch (event_id) {
|
|
case IP_EVENT_STA_GOT_IP:
|
|
post_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4);
|
|
post_announce_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6);
|
|
break;
|
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
case IP_EVENT_ETH_GOT_IP:
|
|
post_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4);
|
|
break;
|
|
#endif
|
|
case IP_EVENT_GOT_IP6: {
|
|
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *) event_data;
|
|
mdns_if_t mdns_if = get_if_from_netif(event->esp_netif);
|
|
if (mdns_if >= MDNS_MAX_INTERFACES) {
|
|
return;
|
|
}
|
|
post_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6);
|
|
post_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4);
|
|
mdns_priv_browse_send_all(mdns_if);
|
|
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH */
|
|
|
|
static inline void set_default_duplicated_interfaces(void)
|
|
{
|
|
mdns_if_t wifi_sta_if = MDNS_MAX_INTERFACES;
|
|
mdns_if_t eth_if = MDNS_MAX_INTERFACES;
|
|
for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; i++) {
|
|
if (s_esp_netifs[i].predefined && s_esp_netifs[i].predef_if == MDNS_IF_STA) {
|
|
wifi_sta_if = i;
|
|
}
|
|
if (s_esp_netifs[i].predefined && s_esp_netifs[i].predef_if == MDNS_IF_ETH) {
|
|
eth_if = i;
|
|
}
|
|
}
|
|
if (wifi_sta_if != MDNS_MAX_INTERFACES && eth_if != MDNS_MAX_INTERFACES) {
|
|
s_esp_netifs[wifi_sta_if].duplicate = eth_if;
|
|
s_esp_netifs[eth_if].duplicate = wifi_sta_if;
|
|
}
|
|
}
|
|
|
|
void mdns_priv_netif_unregister_predefined_handlers(void)
|
|
{
|
|
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
|
|
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset);
|
|
#endif
|
|
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset);
|
|
#endif
|
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset);
|
|
#endif
|
|
}
|
|
|
|
esp_err_t mdns_priv_netif_init(void)
|
|
{
|
|
esp_err_t err = ESP_OK;
|
|
// zero-out local copy of netifs to initiate a fresh search by interface key whenever a netif ptr is needed
|
|
for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) {
|
|
s_esp_netifs[i].netif = NULL;
|
|
}
|
|
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
|
|
if ((err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset, NULL)) != ESP_OK) {
|
|
goto free_event_handlers;
|
|
}
|
|
#endif
|
|
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
if ((err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset, NULL)) != ESP_OK) {
|
|
goto free_event_handlers;
|
|
}
|
|
#endif
|
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
if ((err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, handle_system_event_for_preset, NULL)) != ESP_OK) {
|
|
goto free_event_handlers;
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
set_default_duplicated_interfaces();
|
|
#endif
|
|
|
|
uint8_t i;
|
|
#ifdef CONFIG_LWIP_IPV6
|
|
esp_ip6_addr_t tmp_addr6;
|
|
#endif
|
|
#ifdef CONFIG_LWIP_IPV4
|
|
esp_netif_ip_info_t if_ip_info;
|
|
#endif
|
|
|
|
for (i = 0; i < MDNS_MAX_INTERFACES; i++) {
|
|
#ifdef CONFIG_LWIP_IPV6
|
|
if (!esp_netif_get_ip6_linklocal(mdns_priv_get_esp_netif(i), &tmp_addr6) && !mdns_utils_ipv6_address_is_zero(tmp_addr6)) {
|
|
mdns_priv_pcb_enable(i, MDNS_IP_PROTOCOL_V6);
|
|
}
|
|
#endif
|
|
#ifdef CONFIG_LWIP_IPV4
|
|
if (!esp_netif_get_ip_info(mdns_priv_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) {
|
|
mdns_priv_pcb_enable(i, MDNS_IP_PROTOCOL_V4);
|
|
}
|
|
#endif
|
|
}
|
|
return ESP_OK;
|
|
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH
|
|
free_event_handlers:
|
|
mdns_priv_netif_unregister_predefined_handlers();
|
|
#endif
|
|
return err;
|
|
}
|
|
|
|
esp_err_t mdns_priv_netif_deinit(void)
|
|
{
|
|
for (int i = 0; i < MDNS_MAX_INTERFACES; i++) {
|
|
mdns_priv_pcb_disable(i, MDNS_IP_PROTOCOL_V6);
|
|
mdns_priv_pcb_disable(i, MDNS_IP_PROTOCOL_V4);
|
|
s_esp_netifs[i].duplicate = MDNS_MAX_INTERFACES;
|
|
}
|
|
return ESP_OK;
|
|
}
|
|
|
|
/*
|
|
* Public Methods
|
|
* */
|
|
esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action)
|
|
{
|
|
return post_custom_action(get_if_from_netif(esp_netif), event_action);
|
|
}
|
|
|
|
esp_err_t mdns_register_netif(esp_netif_t *esp_netif)
|
|
{
|
|
if (!mdns_priv_is_server_init()) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
esp_err_t err = ESP_ERR_NO_MEM;
|
|
mdns_priv_service_lock();
|
|
for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) {
|
|
if (s_esp_netifs[i].netif == esp_netif) {
|
|
mdns_priv_service_unlock();
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
}
|
|
|
|
for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) {
|
|
if (!s_esp_netifs[i].predefined && s_esp_netifs[i].netif == NULL) {
|
|
s_esp_netifs[i].netif = esp_netif;
|
|
err = ESP_OK;
|
|
break;
|
|
}
|
|
}
|
|
mdns_priv_service_unlock();
|
|
return err;
|
|
}
|
|
|
|
esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif)
|
|
{
|
|
if (!mdns_priv_is_server_init()) {
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
esp_err_t err = ESP_ERR_NOT_FOUND;
|
|
mdns_priv_service_lock();
|
|
for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) {
|
|
if (!s_esp_netifs[i].predefined && s_esp_netifs[i].netif == esp_netif) {
|
|
s_esp_netifs[i].netif = NULL;
|
|
err = ESP_OK;
|
|
break;
|
|
}
|
|
}
|
|
mdns_priv_service_lock();
|
|
return err;
|
|
}
|